%% sockctrl.tex
%%
-%% Copyright (C) 2004 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2004-2005 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Prefazione",
\subsection{La struttura del \textit{resolver}}
\label{sec:sock_resolver}
+\index{\textit{resolver}|(}
La risoluzione dei nomi è associata tradizionalmente al servizio del
\textit{Domain Name Service} che permette di identificare le macchine su
internet invece che per numero IP attraverso il relativo \textsl{nome a
\begin{figure}[htb]
\centering
- \includegraphics[width=10cm]{img/resolver}
+ \includegraphics[width=9cm]{img/resolver}
\caption{Schema di funzionamento delle routine del \textit{resolver}.}
\label{fig:sock_resolver_schema}
\end{figure}
funzioni di libreria, prevedendo un ordine di interrogazione predefinito e
non modificabile (a meno di una ricompilazione delle librerie stesse).}
+\index{\textit{Name~Service~Switch}|(}
Per risolvere questa serie di problemi la risoluzione dei nomi a dominio
eseguirà dal \textit{resolver} è stata inclusa all'interno di un meccanismo
generico per la risoluzione di corrispondenze fra nomi ed informazioni ad essi
disposizione,\footnote{è cura della implementazione fattane nelle \acr{glibc}
tenere conto della presenza del \textit{Name Service Switch}.} e sono queste
quelle che tratteremo nelle sezioni successive.
+\index{\textit{Name~Service~Switch}|)}
\subsection{Le funzioni di interrogazione del \textit{resolver}}
\const{C\_IN} & indirizzi internet, in pratica i soli utilizzati oggi.\\
\const{C\_HS} & indirizzi \textit{Hesiod}, utilizzati solo al MIT, oggi
completamente estinti. \\
- \const{C\_CHAOS}& indizzi per la rete \textit{Chaosnet}, un'altra rete
+ \const{C\_CHAOS}& indirizzi per la rete \textit{Chaosnet}, un'altra rete
sperimentale nata al MIT. \\
\const{C\_ANY} & indica un indirizzo di classe qualunque.\\
\hline
\noindent che, come l'analoga \func{strerror}, restituisce una stringa con un
messaggio di errore già formattato, corrispondente al codice passato come
argomento (che si presume sia dato da \var{h\_errno}).
+\index{\textit{resolver}|)}
\subsection{La risoluzione dei nomi a dominio}
\label{sec:sock_name_services}
-La principale funzionalità del \textit{resolver} resta quella di risolvere i
-nomi a dominio in indirizzi IP, per cui non ci dedicheremo oltre alle funzioni
-di richiesta generica ed esamineremo invece le funzioni a questo dedicate. La
-prima funzione è \funcd{gethostbyname} il cui scopo è ottenere l'indirizzo di
-una stazione noto il suo nome a dominio, il suo prototipo è:
+La principale funzionalità del \index{\textit{resolver}}\textit{resolver}
+resta quella di risolvere i nomi a dominio in indirizzi IP, per cui non ci
+dedicheremo oltre alle funzioni di richiesta generica ed esamineremo invece le
+funzioni a questo dedicate. La prima funzione è \funcd{gethostbyname} il cui
+scopo è ottenere l'indirizzo di una stazione noto il suo nome a dominio, il
+suo prototipo è:
\begin{prototype}{netdb.h}
{struct hostent *gethostbyname(const char *name)}
IPv4, se si vogliono ottenere degli indirizzi IPv6 occorrerà prima impostare
l'opzione \const{RES\_USE\_INET6} nel campo \texttt{\_res.options} e poi
chiamare \func{res\_init} (vedi sez.~\ref{sec:sock_resolver_functions}) per
-modificare le opzioni del resolver; dato che questo non è molto comodo è stata
-definita\footnote{questa è una estensione fornita dalle \acr{glibc},
- disponibile anche in altri sistemi unix-like.} un'altra funzione,
-\funcd{gethostbyname2}, il cui prototipo è:
+modificare le opzioni del \index{\textit{resolver}}\textit{resolver}; dato che
+questo non è molto comodo è stata definita\footnote{questa è una estensione
+ fornita dalle \acr{glibc}, disponibile anche in altri sistemi unix-like.}
+un'altra funzione, \funcd{gethostbyname2}, il cui prototipo è:
\begin{functions}
\headdecl{netdb.h}
\headdecl{sys/socket.h}
Vediamo allora un primo esempio dell'uso delle funzioni di risoluzione, in
fig.~\ref{fig:mygethost_example} è riportato un estratto del codice di un
-programma che esegue una semplice interrogazione al \textit{resolver} usando
-\func{gethostbyname} e poi ne stampa a video i risultati. Al solito il
-sorgente completo, che comprende il trattamento delle opzioni ed una funzione
-per stampare un messaggio di aiuto, è nel file \texttt{mygethost.c} dei
-sorgenti allegati alla guida.
+programma che esegue una semplice interrogazione al
+\index{\textit{resolver}}\textit{resolver} usando \func{gethostbyname} e poi
+ne stampa a video i risultati. Al solito il sorgente completo, che comprende
+il trattamento delle opzioni ed una funzione per stampare un messaggio di
+aiuto, è nel file \texttt{mygethost.c} dei sorgenti allegati alla guida.
Il programma richiede un solo argomento che specifichi il nome da cercare,
senza il quale (\texttt{\small 12--15}) esce con un errore. Dopo di che
modo si può far ricominciare da capo una lettura sequenziale. L'argomento
\param{stayopen}, se diverso da zero, fa sì che il file resti aperto anche fra
diverse chiamate a \func{getservbyname} e \func{getservbyaddr}.\footnote{di
- default dopo una chiamata a queste funzioni il file viene chiuso, cosicchè
+ default dopo una chiamata a queste funzioni il file viene chiuso, cosicché
una successiva chiamata a \func{getservent} riparte dall'inizio.} La terza
funzione, \funcd{endservent}, provvede semplicemente a chiudere il file.
\const{IN6ADDR\_ANY\_INIT} per IPv6), altrimenti
verrà usato l'indirizzo dell'interfaccia di
\textit{loopback}. Se invece non è impostato gli
- indirizzi verrano restituiti in formato adatto ad
+ indirizzi verranno restituiti in formato adatto ad
una chiamata a \func{connect} o \func{sendto}.\\
\const{AI\_CANONNAME} & richiede la restituzione del nome canonico della
macchina, che verrà salvato in una stringa il cui
\end{figure}
Come primo esempio di uso di \func{getaddrinfo} vediamo un programma
-elementare di interrogazione del resolver basato questa funzione, il cui corpo
-principale è riportato in fig.~\ref{fig:mygetaddr_example}. Il codice completo
-del programma, compresa la gestione delle opzioni in cui è gestita l'eventuale
-inizializzazione dell'argomento \var{hints} per restringere le ricerche su
-protocolli, tipi di socket o famiglie di indirizzi, è disponibile nel file
-\texttt{mygetaddr.c} dei sorgenti allegati alla guida.
+elementare di interrogazione del \index{\textit{resolver}}\textit{resolver}
+basato questa funzione, il cui corpo principale è riportato in
+fig.~\ref{fig:mygetaddr_example}. Il codice completo del programma, compresa
+la gestione delle opzioni in cui è gestita l'eventuale inizializzazione
+dell'argomento \var{hints} per restringere le ricerche su protocolli, tipi di
+socket o famiglie di indirizzi, è disponibile nel file \texttt{mygetaddr.c}
+dei sorgenti allegati alla guida.
\begin{figure}[!htb]
\footnotesize \centering
Se la funzione ha restituito un valore nullo il programma prosegue
inizializzando (\texttt{\small 12}) il puntatore \var{ptr} che sarà usato nel
-sucessivo ciclo (\texttt{\small 14--35}) di scansione della lista delle
+successivo ciclo (\texttt{\small 14--35}) di scansione della lista delle
strutture \struct{addrinfo} restituite dalla funzione. Prima di eseguire
questa scansione (\texttt{\small 12}) viene stampato il valore del nome
canonico che è presente solo nella prima struttura.
cui sarà effettuata la risoluzione; seguono il protocollo da usare (da
specificare con il valore numerico di \file{/etc/protocols}) ed il tipo di
socket (al solito specificato con i valori illustrati in
-sez.~\ref{sec:sock_type}).
-
-La funzione ritorna il valore del file descriptor (un numero positivo)
-associato al socket in caso di successo, o -1 in caso di errore. Per risolvere
-il problema di non poter passare indietro i valori di ritorno di
-\func{getaddrinfo} con i codici di errore\footnote{non si può avere nessuna
- certezza che detti valori siano negativi, è questo è invece nessario per
- evitare ogni possibile ambiguità nei confronti del valore di ritorno in caso
- di successo.} si è provvisto a stampare direttamente all'interno della
-funzione i rispettivi errori, si potrà riconoscere questo caso ottenendo -1
-per il valore di ritorno, ma un valore nullo di \var{errno}.
+sez.~\ref{sec:sock_type}). La funzione ritorna il valore del file descriptor
+associato al socket (un numero positivo) in caso di successo, o -1 in caso di
+errore; per risolvere il problema di non poter passare indietro i valori di
+ritorno di \func{getaddrinfo} contenenti i relativi codici di
+errore\footnote{non si può avere nessuna certezza che detti valori siano
+ negativi, è questo è invece nessario per evitare ogni possibile ambiguità
+ nei confronti del valore di ritorno in caso di successo.} si sono stampati i
+messaggi d'errore direttamente nella funzione.
Una volta definite le variabili necessarie (\texttt{\small 3--5}) la funzione
prima (\texttt{\small 6}) azzera il contenuto della struttura \var{hint} e poi
controlla (\texttt{\small 12-16}) il codice di ritorno, in modo da stampare un
avviso di errore, azzerare \var{errno} ed uscire in caso di errore. Dato che
ad una macchina possono corrispondere più indirizzi IP, e di tipo diverso (sia
-IPv4 che IPv6), ed il servizio può essere in ascolto soltanto su uno solo di
-questi, si provvede a tentare la connessione per ciascun indirizzo restituito
-all'interno di un ciclo (\texttt{\small 18-40}) di scansione della lista
-restituita da \func{getaddrinfo}, ma prima (\texttt{\small 17}) si salva il
-valore del puntatore per poterlo riutilizzare alla fine per disallocare la
+IPv4 che IPv6), mantre il servizio può essere in ascolto soltanto su uno solo
+di questi, si provvede a tentare la connessione per ciascun indirizzo
+restituito all'interno di un ciclo (\texttt{\small 18-40}) di scansione della
+lista restituita da \func{getaddrinfo}, ma prima (\texttt{\small 17}) si salva
+il valore del puntatore per poterlo riutilizzare alla fine per disallocare la
lista.
-Il ciclo viene ripetuto fintanto che si hanno indirizzi validi, ed inizia
-(\texttt{\small 19}) con l'apertura del socket; se questa fallisce si
-controlla (\texttt{\small 20}) se sono disponibili altri indirizzi, nel qual
-caso si passa al successivo (\texttt{\small 21}) ricominciando il ciclo
-(\texttt{\small 22}), se non ve ne sono si stampa l'errore ritornado
-immediatamente (\texttt{\small 24-27}). Se la creazione del socket ha avuto
-successo si procede (\texttt{\small 29}) con la connessione
-
-
-
-
-
-Se la risoluzione del nome ha successo si provvede (\texttt{\small 19--23}) ad
-aprire il socket, ed a connettersi ad esso (\texttt{\small 25--29}); in
-entrambi casi si gestisce il caso di errore, con una stampa ed il ritorno del
-valore -1. Infine prima di ritornare (\texttt{\small 31}) il valore del file
-descriptor del socket si provvede (\texttt{\small 30}) a liberare le strutture
-\struct{addrinfo} allocate da \func{getaddrinfo}.
-
-Si noti come la funzione si limiti ad usare i valori contenuti nella prima
-struttura \struct{addrinfo} ritornata da \func{getaddrinfo}, non eseguendo
-ulteriori tentativi sulle successive in caso di errore. Un'altra
-caratteristica della funzione è che è del tutto irrilevante se la struttura
-ritornata usa indirizzi IPv6 o IPv4, in quanto si fa uso direttamente dei dati
-relativi alle strutture degli indirizzi di \struct{addrinfo} che sono
+Il ciclo viene ripetuto (\texttt{\small 18}) fintanto che si hanno indirizzi
+validi, ed inizia (\texttt{\small 19}) con l'apertura del socket; se questa
+fallisce si controlla (\texttt{\small 20}) se sono disponibili altri
+indirizzi, nel qual caso si passa al successivo (\texttt{\small 21}) e si
+riprende (\texttt{\small 22}) il ciclo da capo; se non ve ne sono si stampa
+l'errore ritornando immediatamente (\texttt{\small 24-27}). Quando la
+creazione del socket ha avuto successo si procede (\texttt{\small 29})
+direttamente con la connessione, di nuovo in caso di fallimento viene ripetuto
+(\texttt{\small 30--38}) il controllo se vi sono o no altri indirizzi da
+provare nella stessa modalità fatta in precedenza, aggiungendovi però in
+entrambi i casi (\texttt{\small 32} e (\texttt{\small 36}) la chiusura del
+socket precedentemente aperto, che non è più utilizzabile.
+
+Se la connessione ha avuto successo invece si termina (\texttt{\small 39})
+direttamente il ciclo, e prima di ritornare (\texttt{\small 31}) il valore del
+file descriptor del socket si provvede (\texttt{\small 30}) a liberare le
+strutture \struct{addrinfo} allocate da \func{getaddrinfo} utilizzando il
+valore del relativo puntatore precedentemente (\texttt{\small 17}) salvato.
+Si noti come per la funzione sia del tutto irrilevante se la struttura
+ritornata contiene indirizzi IPv6 o IPv4, in quanto si fa uso direttamente dei
+dati relativi alle strutture degli indirizzi di \struct{addrinfo} che sono
\textsl{opachi} rispetto all'uso della funzione \func{connect}.
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/TCP_echo_fifth.c}
+ \end{minipage}
+ \normalsize
+ \caption{Il nuovo codice per la connessione del client \textit{echo}.}
+ \label{fig:TCP_echo_fifth}
+\end{figure}
+
Per usare questa funzione possiamo allora modificare ulteriormente il nostro
programma client per il servizio \textit{echo}; in questo caso rispetto al
codice usato finora per collegarsi (vedi fig.~\ref{fig:TCP_echo_client_1})
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \includecodesample{listati/TCP_echo_fifth.c}
+ \includecodesample{listati/sockbind.c}
\end{minipage}
\normalsize
- \caption{Il nuovo codice per la connessione del client \textit{echo}.}
- \label{fig:TCP_echo_fifth}
+ \caption{Il codice della funzione \func{sockbind}.}
+ \label{fig:sockbind_code}
\end{figure}
La seconda funzione di ausilio è \func{sockbind}, il cui corpo principale è
notare la funzione è del tutto analoga alla precedente \func{sockconn}, e
prende gli stessi argomenti, però invece di eseguire una connessione con
\func{connect} si limita a chiamare \func{bind} per collegare il socket ad una
-porta.
+porta.
-Dato che la funzione è pensata per utilizzata da un server ci si può chiedere
-a quale scopo mantenere l'argomento \param{host} quando l'indirizzo di questo
-è usualmente noto. Si ricordi però quanto detto in
+Dato che la funzione è pensata per essere utilizzata da un server ci si può
+chiedere a quale scopo mantenere l'argomento \param{host} quando l'indirizzo
+di questo è usualmente noto. Si ricordi però quanto detto in
sez.~\ref{sec:TCP_func_bind}, relativamente al significato della scelta di un
indirizzo specifico come argomento di \func{bind}, che consente di porre il
server in ascolto su uno solo dei possibili diversi indirizzi presenti su di
-una macchina.
+una macchina. Se non si vuole che la funzione esegua \func{bind} su un
+indirizzo specifico, ma utilizzi l'indirizzo generico, occorrerà avere cura di
+passare un valore \const{NULL} come valore per l'argomento \var{host}; l'uso
+del valore \const{AI\_PASSIVE} serve ad ottenere il valore generico nella
+rispettiva struttura degli indirizzi.
-Se non si vuole che la funzione esegua \func{bind} su un indirizzo specifico,
-ma utilizzi l'indirizzo generico, occorrerà avere cura di passare un valore
-\const{NULL} come valore per l'argomento \var{host}; l'uso del valore
-\const{AI\_PASSIVE} serve ad ottenere il valore generico nella rispettiva
-struttura degli indirizzi.
+Come già detto la funzione è analoga a \func{sockconn} ed inizia azzerando ed
+inizializzando (\texttt{\small 6-11}) opportunamente la struttura \var{hint}
+con i valori ricevuti come argomenti, soltanto che in questo caso si è usata
+(\texttt{\small 8}) una impostazione specifica dei flag di \var{hint} usando
+\const{AI\_PASSIVE} per indicare che il socket sarà usato per una apertura
+passiva. Per il resto la chiamata (\texttt{\small 12-18}) a \func{getaddrinfo}
+e ed il ciclo principale (\texttt{\small 20--42}) sono identici, solo che si è
+sostituita (\texttt{\small 31}) la chiamata a \func{connect} con una chiamata
+a \func{bind}. Anche la conclusione (\texttt{\small 43--44}) della funzione è
+identica.
+
+Si noti come anche in questo caso si siano inserite le stampe degli errori
+sullo standard error, nonostante la funzione possa essere invocata da un
+demone. Nel nostro caso questo non è un problema in quanto se la funzione non
+ha successo il programma deve uscire immediatamente prima di essere posto in
+background, e può quindi scrivere gli errori direttamente sullo standard
+error.
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \includecodesample{listati/sockbind.c}
+ \includecodesample{listati/TCP_echod_third.c}
\end{minipage}
\normalsize
- \caption{Il codice della funzione \func{sockbind}.}
- \label{fig:sockbind_code}
+ \caption{Nuovo codice per l'apertura passiva del server \textit{echo}.}
+ \label{fig:TCP_echod_third}
\end{figure}
-Come già detto la funzione è analoga a \func{sockconn} ed inizia azzerando ed
-inizializzando (\texttt{\small 6-11}) opportunamente la struttura \var{hint}
-con i valori ricevuti come argomenti, soltanto che in questo caso si è usata
-(\texttt{\small 8}) una impostazione specifica dei flag di \var{hint} usando
-\const{AI\_PASSIVE} per indicare che il socket sarà usato per una apertura
-passiva. Per il resto la chiamata a \func{getaddrinfo} (\texttt{\small 12-17})
-e quella a \func{socket} (\texttt{\small 19--23}) sono identiche, mentre si è
-sostituita (\texttt{\small 25--29}) la chiamata a \func{connect} con una
-chiamata a \func{bind}. La conclusione (\texttt{\small 30--31}) della funzione
-è identica. Si noti come anche in questo caso si siano inserite le stampe
-degli errori sullo standard output, nonostante la funzione possa essere
-invocata da un demone. Nel nostro caso questo non è un problema in quanto se
-la funzione non ha successo il programma deve uscire immediatamente prima di
-essere posto in background, e può quindi scrivere gli errori direttamente
-sullo standard output.
-
Con l'uso di questa funzione si può modificare anche il codice del nostro
server \textit{echo}, che rispetto a quanto illustrato nella versione iniziale
di fig.~\ref{fig:TCP_echo_server_first_code} viene modificato nella forma
che si cura anche della eventuale risoluzione di un indirizzo specifico sul
quale si voglia far ascoltare il server.
+
+
+\section{Le opzioni dei socket}
+\label{sec:sock_options}
+
+Benché dal punto di vista del loro uso come canali di trasmissione di dati i
+socket siano trattati allo stesso modo dei file, ed acceduti tramite i file
+descriptor, la normale interfaccia usata per la gestione dei file non è
+sufficiente a poterne controllare tutte le caratteristiche, che variano tra
+l'altro a seconda del loro tipo (e della relativa forma di comunicazione
+sottostante). In questa sezione vedremo allora quali sono le funzioni dedicate
+alla gestione delle caratteristiche specifiche dei vari tipi di socket, le
+cosiddette \textit{socket options}.
+
+
+\subsection{Le funzioni \func{setsockopt} e \func{getsockopt}}
+\label{sec:sock_setsockopt}
+
+Le varie caratteristiche dei socket possono essere gestite attraverso l'uso di
+due funzioni generiche che permettono rispettivamente di impostarle e di
+recuperarne il valore corrente. La prima di queste due funzioni, quella usata
+per impostare le \textit{socket options}, è \funcd{setsockopt}, ed il suo
+prototipo è:
+\begin{functions}
+ \headdecl{sys/socket.h}
+ \headdecl{sys/types.h}
+
+ \funcdecl{int setsockopt(int sock, int level, int optname, const void
+ *optval, socklen\_t optlen)}
+ Imposta le opzioni di un socket.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] il file descriptor \param{sock} non è valido.
+ \item[\errcode{EFAULT}] l'indirizzo \param{optval} non è valido.
+ \item[\errcode{EINVAL}] il valore di \param{optlen} non è valido.
+ \item[\errcode{ENOPROTOOPT}] l'opzione scelta non esiste per il livello
+ indicato.
+ \item[\errcode{ENOTSOCK}] il file descriptor \param{sock} non corrisponde ad
+ un socket.
+ \end{errlist}
+}
+\end{functions}
+
+
+Il primo argomento della funzione, \param{sock}, indica il socket su cui si
+intende operare; per indicare l'opzione da impostare si devono usare i due
+argomenti successivi, \param{level} e \param{optname}. Come abbiamo visto in
+sez.~\ref{sec:net_protocols} i protocolli di rete sono strutturati su vari
+livelli, ed l'interfaccia dei socket può usarne più di uno. Si avranno allora
+funzionalità e caratteristiche diverse per ciascun protocollo usato da un
+socket, e quindi saranno anche diverse le opzioni che si potranno impostare
+per ciascun socket, a seconda del \textsl{livello} (trasporto, rete, ecc.) su
+cui si vuole andare ad operare.
+
+Il valore di \param{level} seleziona allora il protocollo su cui vuole
+intervenire, mentre \param{optname} permette di scegliere su quale delle
+opzioni che sono definite per quel protocollo si vuole operare. In sostanza la
+selezione di una specifica opzione viene fatta attraverso una coppia di valori
+\param{level} e \param{optname} e chiaramente la funzione avrà successo
+soltanto se il protocollo in questione prevede quella opzione ed è utilizzato
+dal socket. Infine \param{level} prevede anche il valore speciale
+\const{SOL\_SOCKET} usato per le opzioni generiche che sono disponibili per
+qualunque tipo di socket.
+
+I valori usati per \param{level}, corrispondenti ad un dato protocollo usato
+da un socket, sono quelli corrispondenti al valore numerico che identifica il
+suddetto protocollo in \file{/etc/protocols}; dato che la leggibilità di un
+programma non trarrebbe certo beneficio dall'uso diretto dei valori numerici,
+più comunemente si indica il protocollo tramite le apposite costanti
+\texttt{SOL\_*} riportate in tab.~\ref{tab:sock_option_levels}, dove si sono
+riassunti i valori che possono essere usati per l'argomento
+\param{level}.\footnote{la notazione in questo caso è, purtroppo, abbastanza
+ confusa: infatti in Linux il valore si può impostare sia usando le costanti
+ \texttt{SOL\_*}, che le analoghe \texttt{IPPROTO\_*} (citate anche da
+ Stevens in \cite{UNP1}); entrambe hanno gli stessi valori che sono
+ equivalenti ai numeri di protocollo di \file{/etc/protocols}, con una
+ eccesione specifica, che è quella del protocollo ICMP, per la quale non
+ esista una costante, il che è comprensibile dato che il suo valore, 1, è
+ quello che viene assegnato a \const{SOL\_SOCKET}.}
+
+\begin{table}[!htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Livello} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{SOL\_SOCKET}& opzioni generiche dei socket.\\
+ \const{SOL\_IP} & opzioni specifiche per i socket che usano IPv4.\\
+ \const{SOL\_TCP} & opzioni per i socket che usano TCP.\\
+ \const{SOL\_IPV6} & opzioni specifiche per i socket che usano IPv6.\\
+ \const{SOL\_ICMPV6}& opzioni specifiche per i socket che usano ICMPv6.\\
+ \hline
+ \end{tabular}
+ \caption{Possibili valori dell'argomento \param{level} delle
+ funzioni \func{setsockopt} e \func{getsockopt}.}
+ \label{tab:sock_option_levels}
+\end{table}
+
+Il quarto argomento, \param{optval} è un puntatore ad una zona di memoria che
+contiene i dati che specificano il valore dell'opzione che si vuole passare al
+socket, mentre l'ultimo argomento \param{optlen},\footnote{questo argomento è
+ in realtà sempre di tipo \ctyp{int}, come era nelle \acr{libc4} e
+ \acr{libc5}; l'uso di \ctyp{socklen\_t} è stato introdotto da POSIX (valgono
+ le stesse considerazioni per l'uso di questo tipo di dato fatte in
+ sez.~\ref{sec:TCP_func_accept}) ed adottato dalle \acr{glibc}.} è la
+dimensione in byte dei dati presenti all'indirizzo indicato da \param{optval}.
+Dato che il tipo di dati varia a seconda dell'opzione scelta, occorrerà
+individuare qual è quello che deve essere usato, ed utilizzare le opportune
+variabili.
+
+La gran parte delle opzioni utilizzano per \param{optval} un valore intero, se
+poi l'opzione esprime una condizione logica, il valore è sempre un intero, am
+si dovrà usare un valore non nullo per abilitarla ed un valore nullo per
+disabilitarla. Se invece l'opzione non prevede di dover ricevere nessun tipo
+di valore si deve impostare \param{optval} a \const{NULL}. Un piccolo numero
+di opzioni però usano dei tipi di dati peculiari, è questo il motivo per cui
+\param{optval} è stato definito come puntatore generico.
+
+La seconda funzione usata per controllare le proprietà dei socket è
+\funcd{getsockopt}, che serve a leggere i valori delle opzioni dei socket ed a
+farsi restituire i dati relativi al loro funzionamento; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/socket.h}
+ \headdecl{sys/types.h}
+
+ \funcdecl{int getsockopt(int s, int level, int optname, void *optval,
+ socklen\_t *optlen)} Legge le opzioni di un socket.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] il file descriptor \param{sock} non è valido.
+ \item[\errcode{EFAULT}] l'indirizzo \param{optval} o quello di
+ \param{optlen} non è valido.
+ \item[\errcode{ENOPROTOOPT}] l'opzione scelta non esiste per il livello
+ indicato.
+ \item[\errcode{ENOTSOCK}] il file descriptor \param{sock} non corrisponde ad
+ un socket.
+ \end{errlist}
+}
+\end{functions}
+
+I primi tre argomenti sono identici ed hanno lo stesso significato di quelli
+di \func{setsockopt}, anche se non è detto che tutte le opzioni siano definite
+per entrambe le funzioni. In questo caso \param{optval} viene usato per
+ricevere le informazioni ed indica l'indirizzo a cui andranno scritti i dati
+letti dal socket, infine \param{optlen} diventa un puntatore ad una variabile
+che viene usata come \textit{value result argument} per indicare, prima della
+chiamata della funzione, la lunghezza del buffer allocato per \param{optval} e
+per ricevere indietro, dopo la chiamata della funzione, la dimensione
+effettiva dei dati scritti su di esso. Se la dimenzione del buffer allocato
+per \param{optval} non è sufficiente si avrà un errore.
+
+
+
+\subsection{Le opzioni generiche}
+\label{sec:sock_generic_options}
+
+Come accennato esiste un insieme generico di opzioni dei socket che possono
+applicarsi a qualunque tipo di socket,\footnote{una descrizione di queste
+ opzioni è generalmente disponibile nella settima sezione delle pagine di
+ manuale, nel caso specifico la si può consultare con \texttt{man 7 socket}.}
+indipendentemente da quale protocollo venga poi utilizzato. Se si vuole
+operare su queste opzioni generiche il livello da utilizzare è
+\const{SOL\_SOCKET}; si è riportato un elenco di queste opzioni in
+tab.~\ref{tab:sock_opt_socklevel}.
+
+
+\begin{table}[!htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|c|c|c|l|l|}
+ \hline
+ \textbf{Opzione}&\texttt{get}&\texttt{set}&\textbf{flag}&\textbf{Tipo}&
+ \textbf{Descrizione}\\
+ \hline
+ \hline
+ \const{SO\_KEEPALIVE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ controlla l'attività della connessione.\\
+ \const{SO\_OOBINLINE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ lascia in linea i dati \textit{out-of-band}.\\
+ \const{SO\_RCVLOWAT} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ basso livello sul buffer di ricezione.\\
+ \const{SO\_SNDLOWAT} &$\bullet$&$\bullet$& &\texttt{int}&
+ basso livello sul buffer di trasmissione.\\
+ \const{SO\_RCVTIMEO} &$\bullet$&$\bullet$& &\texttt{timeval}&
+ timeout in ricezione.\\
+ \const{SO\_SNDTIMEO} &$\bullet$&$\bullet$& &\texttt{timeval}&
+ timeout in trasmissione.\\
+ \const{SO\_BSDCOMPAT}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ abilita la compatibilità con BSD.\\
+ \const{SO\_PASSCRED} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ abilita la ricezione di credenziali.\\
+ \const{SO\_PEERCRED} &$\bullet$& & &\texttt{ucred}&
+ restituisce le credenziali del processo remoto.\\
+ \const{SO\_BINDTODEVICE}&$\bullet$&$\bullet$& &\texttt{char *}&
+ lega il socket ad un dispositivo.\\
+ \const{SO\_DEBUG} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ abilita il debugging sul socket.\\
+ \const{SO\_REUSEADDR}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ consente il riutilizzo di un indirizzo locale.\\
+ \const{SO\_TYPE} &$\bullet$& & &\texttt{int}&
+ restituisce il tipo di socket.\\
+ \const{SO\_ACCEPTCONN}&$\bullet$& & &\texttt{int}&
+ indica se il socket è in ascolto.\\
+ \const{SO\_DONTROUTE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ non invia attraverso un gateway.\\
+ \const{SO\_BROADCAST}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ attiva o disattiva il \textit{broadcast}.\\
+ \const{SO\_SNDBUF} &$\bullet$&$\bullet$& &\texttt{int}&
+ imposta dimensione del buffer di trasmissione.\\
+ \const{SO\_RCVBUF} &$\bullet$&$\bullet$& &\texttt{int}&
+ imposta dimensione del buffer di ricezione.\\
+ \const{SO\_LINGER} &$\bullet$&$\bullet$& &\texttt{linger}&
+ indugia nella chiusura con dati da spedire.\\
+ \const{SO\_PRIORITY} &$\bullet$&$\bullet$& &\texttt{int}&
+ imposta la priorità del socket.\\
+ \const{SO\_ERROR} &$\bullet$& & &\texttt{int}&
+ riceve e cancella gli errori pendenti.\\
+ \hline
+ \end{tabular}
+ \caption{Le opzioni disponibili al livello \const{SOL\_SOCKET}.}
+ \label{tab:sock_opt_socklevel}
+\end{table}
+
+La tabella elenca le costanti che identificano le singole opzioni da usare
+come valore per \param{optname}; le due colonne seguenti indicano per quali
+delle due funzioni (\func{getsockopt} o \func{setsockopt}) l'opzione è
+disponibile, mentre la colonna successiva indica, quando di ha a che fare con
+un valore di \param{optval} intero, se l'opzione è da considerare un numero o
+un valore logico. Si è inoltre riportato sulla quinta colonna il tipo di dato
+usato per \param{optval} ed una breve descrizione del significato delle
+singole opzioni sulla sesta.
+
+
+Questo ci consentirà anche
+di trattare approfonditamente alcune opzioni che, nonostante siano
+classificate fra quelle generiche, hanno un significato effettivo solo per
+alcuni tipi di socket.TCP/IP. L'elenco dettagliato del significato delle
+opzioni generiche dei socket è allora il seguente:
+
+
+Le descrizioni delle opzioni presenti in tab.~\ref{tab:sock_opt_socklevel}
+sono estremamente sommarie, è perciò necessario fornire un po' più di
+informazioni; alcune opzioni comunque hanno una notevole rilevanza nella
+gestione dei socket, e pertanto il loro utilizzo sarà approfondito
+separatamente in sez.~\ref{sec:sock_options_main}. Quello che segue pertanto è
+soltanto un elenco più dettagliato di quanto scritto in
+tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
+\begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{SO\_KEEPALIVE}] questa opzione abilita un meccanismo di verifica
+ della persistenza di una connessione associata al socket (ed è pertanto
+ effettiva solo sui socket che supportano le connessioni, ed è usata
+ principalmente con il TCP). L'opzione utilizza per \param{optval} un intero
+ usato come valore logico. Maggiori dettagli sul suo funzionamento sono
+ forniti in sez.~\ref{sec:sock_options_main}.
+
+\item[\const{SO\_OOBINLINE}] se questa opzione viene abilitata i dati
+ \textit{out-of-band} vengono inviati direttamente nel flusso di dati del
+ socket (e sono quindi letti con una normale \func{read}) invece che restare
+ disponibili solo per l'accesso con l'uso del flag \const{MSG\_OOB} di
+ \func{recvmsg}. L'argomento è trattato in dettaglio in
+ sez.~\ref{sec:TCP_urgent_data}. L'opzione funziona soltanto con socket che
+ supportino i dati \textit{out-of-band} (non ha senso per socket UDP ad
+ esempio), ed utilizza per \param{optval} un intero usato come valore logico.
+
+
+\item[\const{SO\_RCVLOWAT}] questa opzione imposta il valore che indica il
+ numero minimo di byte che devono essere presenti nel buffer di ricezione
+ perché il kernel passi i dati all'utente, restituendoli ad una \func{read} o
+ segnalando ad una \func{select} (vedi sez.~\ref{sec:TCP_sock_select}) che ci
+ sono dati in ingresso. L'opzione utilizza per \param{optval} un intero che
+ specifica il numero di byte, ma con Linux questo valore è sempre 1 e non può
+ essere cambiato; \func{getsockopt} leggerà questo valore mentre
+ \func{setsockopt} darà un errore di \errcode{ENOPROTOOPT}.
+
+
+\item[\const{SO\_SNDLOWAT}] questa opzione imposta il valore che indica il
+ numero minimo di byte che devono essere presenti nel buffer di scrittura
+ perché il kernel li invii al protocollo successivo, consentendo ad una
+ \func{write} di ritornare o segnalando ad una \func{select} (vedi
+ sez.~\ref{sec:TCP_sock_select}) che è possibile eseguire una scrittura.
+ L'opzione utilizza per \param{optval} un intero che specifica il numero di
+ byte, come per la precedente \const{SO\_RCVLOWAT} con Linux questo valore è
+ sempre 1 e non può essere cambiato; \func{getsockopt} leggerà questo valore
+ mentre \func{setsockopt} darà un errore di \errcode{ENOPROTOOPT}.
+
+
+\item[\const{SO\_RCVTIMEO}] l'opzione permette di impostare un tempo massimo
+ sulle operazioni di lettura da un socket, e prende per \param{optval} una
+ struttura di tipo \struct{timeval} (vedi fig.~\ref{fig:sys_timeval_struct})
+ identica a quella usata con \func{select}. Con \func{getsockopt} si può
+ leggere il valore attuale, mentre con \func{setsockopt} si imposta il tempo
+ voluto, usando un valore nullo per \struct{timeval} il timeout viene
+ rimosso.
+
+ Se l'opzione viene attivata tutte le volte che una delle funzioni di lettura
+ (\func{read}, \func{readv}, \func{recv}, \func{recvfrom} e \func{recvmsg})
+ si blocca in attesa di dati per un tempo maggiore di quello impostato, essa
+ ritornerà un valore -1 e la variabile \var{errno} sarà impostata con un
+ errore di \errcode{EAGAIN} e \errcode{EWOULDBLOCK}, così come sarebbe
+ avvenuto se si fosse aperto il socket in modalità non bloccante.\footnote{in
+ teoria, se il numero di byte presenti nel buffer di ricezione fosse
+ inferiore a quello specificato da \const{SO\_RCVLOWAT}, l'effetto potrebbe
+ essere semplicemente quello di provocare l'uscita delle funzioni di
+ lettura restituendo il numero di byte fino ad allora ricevuti; dato che
+ con Linux questo valore è sempre 1 questo caso non esiste.}
+
+ In genere questa opzione non è molto utilizzata se si ha a che fare con la
+ lettura dei dati, in quanto è sempre possibile usare una \func{select} che
+ consente di specificare un \textit{timeout}; l'uso di \func{select} non
+ consente però di impostare il timout per l'uso di \func{connect}, per avere
+ il quale si può ricorrere a questa opzione.
+
+% verificare con un programma di test
+
+\item[\const{SO\_SNDTIMEO}] l'opzione permette di impostare un tempo massimo
+ sulle operazioni di scrittura su un socket, ed usa gli stessi valori di
+ \const{SO\_RCVTIMEO}. In questo caso però si avrà un errore di
+ \errcode{EAGAIN} o \errcode{EWOULDBLOCK} per le funzioni di scrittura
+ \func{write}, \func{writev}, \func{send}, \func{sendfrom} e \func{sendmsg}
+ qualora queste restino bloccate per un tempo maggiore di quello specificato.
+
+\item[\const{SO\_BSDCOMPAT}] questa opzione abilita la compatibilità con il
+ comportamento di BSD (in particolare ne riproduce i bug). Attualmente è una
+ opzione usata solo per il protocollo UDP e ne è prevista la rimozione in
+ futuro. L'opzione utilizza per \param{optval} un intero usato come valore
+ logico.
+
+ Quando viene abilitata gli errori riportati da messaggi ICMP per un socket
+ UDP non vengono passati al programma in user space. Con le versioni 2.0.x
+ del kernel erano anche abilitate altre opzioni per i socket raw, che sono
+ state rimosse con il passaggio al 2.2; è consigliato correggere i programmi
+ piuttosto che usare questa funzione.
+
+\item[\const{SO\_PASSCRED}] questa opzione abilita sui socket unix-domain
+ (vedi sez.~\ref{sec:unix_socket}) la ricezione dei messaggi di controllo di
+ tipo \const{SCM\_CREDENTIALS}. Prende come \param{optval} un intero usato
+ come valore logico.
+
+\item[\const{SO\_PEERCRED}] questa opzione restituisce le credenziali del
+ processo remoto connesso al socket; l'opzione è disponibile solo per socket
+ unix-domain e può essere usata solo con \func{getsockopt}. Utilizza per
+ \param{optval} una apposita struttura \struct{ucred} (vedi
+ sez.~\ref{sec:unix_socket_xxx}).
+
+\item[\const{SO\_BINDTODEVICE}] questa opzione permette di \textsl{legare} il
+ socket ad una particolare interfaccia, in modo che esso possa ricevere ed
+ inviare pacchetti solo su quella. L'opzione richiede per \param{optval} il
+ puntatore ad una stringa contenente il nome dell'interfaccia (ad esempio
+ \texttt{eth0}); utilizzando una stringa nulla o un valore nullo per
+ \param{optlen} si può rimuovere un precedente collegamento.
+
+ Il nome della interfaccia deve essere specificato con una stringa terminata
+ da uno zero e di lunghezza massima pari a \const{IFNAMSIZ}; l'opzione è
+ effettiva solo per alcuni tipi di socket, ed in particolare per quelli della
+ famiglia \const{AF\_INET}; non è invece supportata per i \textit{packet
+ socket} (vedi sez.~\ref{cha:advanced_socket_xxx}).
+
+\item[\const{SO\_DEBUG}] questa opzione abilita il debugging delle operazioni
+ dei socket; l'opzione utilizza per \param{optval} un intero usato come
+ valore logico, e può essere utilizzata solo da un processo con i privilegi
+ di amministratore (in particolare con la \textit{capability}
+ \const{CAP\_NET\_ADMIN}). L'opzione necessita inoltre dell'opportuno
+ supporto nel kernel;\footnote{deve cioè essere definita la macro di
+ preprocessore \macro{SOCK\_DEBUGGING} nel file \file{include/net/sock.h}
+ dei sorgenti del kernel, questo è sempre vero nei kernel delle serie
+ superiori alla 2.3, per i kernel delle serie precedenti invece è
+ necessario aggiungere a mano detta definizione; è inoltre possibile
+ abilitare anche il tracciamento degli stati del TCP definendo la macro
+ \macro{STATE\_TRACE} in \file{include/net/tcp.h}.} quando viene
+ abilitata una serie di messaggi con le informazioni di debug vengono inviati
+ direttamente al sistema del kernel log.\footnote{si tenga presente che il
+ comportamento è diverso da quanto avviene con BSD, dove l'opzione opera
+ solo sui socket TCP, causando la scrittura di tutti i pacchetti inviati
+ sulla rete su un buffer circolare che viene letto da un apposito
+ programma, \cmd{trpt}.}
+
+\item[\const{SO\_REUSEADDR}] questa opzione permette di eseguire la funzione
+ \func{bind} su indirizzi locali che siano già in uso da altri socket;
+ l'opzione utilizza per \param{optval} un intero usato come valore logico.
+ Questa opzione modifica il comportamento normale dell'interfaccia dei socket
+ che fa fallire l'esecuzione della funzione \func{bind} con un errore di
+ \errcode{EADDRINUSE} quando l'indirizzo locale\footnote{più propriamente il
+ controllo viene eseguito sulla porta.} è già in uso da parte di un altro
+ socket. Maggiori dettagli sul suo funzionamento sono forniti in
+ sez.~\ref{sec:sock_options_main}.
+
+
+\item[\const{SO\_TYPE}] questa opzione permette di leggere il tipo di socket
+ su cui si opera; funziona solo con \func{getsockopt}, ed utilizza per
+ \param{optval} un intero in cui verrà restituto il valore numerico che lo
+ identifica (ad esempio \const{SOCK\_STREAM}).
+
+\item[\const{SO\_ACCEPTCONN}] questa opzione permette di rilevare se il socket
+ su cui opera è stato posto in modalità di ricezione di eventuali connessioni
+ con una chiamata a \func{listen}. L'opzione può essere usata soltanto con
+ \func{getsockopt} e utilizza per \param{optval} un intero in cui viene
+ restituito 1 se il socket è in ascolto e 0 altrimenti.
+
+\item[\const{SO\_DONTROUTE}] questa opzione forza l'invio diretto dei
+ pacchetti del socket, saltando ogni processo relativo all'uso della tabella
+ di routing del kernel. Prende per \param{optval} un intero usato come valore
+ logico.
+
+\item[\const{SO\_BROADCAST}] questa opzione abilita il \textit{broadcast};
+ quanto abilitata i socket di tipo \const{SOCK\_DGRAM} riceveranno i
+ pacchetti inviati all'indirizzo di broadcast, e potranno scrivere pacchetti
+ su tale indirizzo. Prende per \param{optval} un intero usato come valore
+ logico. L'opzione non ha effetti su un socket di tipo \const{SOCK\_STREAM}.
+
+
+\item[\const{SO\_SNDBUF}] questa opzione imposta la dimenzione del buffer di
+ uscita del socket. Prende per \param{optval} un intero indicante il numero
+ di byte. Il valore di default ed il valore massimo che si può specificare
+ come argomento per questa opzione sono impostabili tramiti gli opportuni
+ valori di \func{sysctl} (vedi sez.~\ref{sec:sock_sysctl}).
+
+
+\item[\const{SO\_RCVBUF}] questa opzione imposta la dimenzione del buffer di
+ ingresso del socket. Prende per \param{optval} un intero indicante il numero
+ di byte. Il valore di default ed il valore massimo che si può specificare
+ come argomento per questa opzione sono impostabili tramiti gli opportuni
+ valori di \func{sysctl} (vedi sez.~\ref{sec:sock_sysctl}).
+
+
+\item[\const{SO\_LINGER}] questa opzione controlla le modalità con cui viene
+ chiuso un socket quando si utilizza un protocollo che supporta le
+ connessioni (è pertanto usata con i socket TCP ed ignorata per UDP) e
+ modifica il comportamento delle funzioni \func{close} e \func{shutdown}.
+ L'opzione richiede che l'argomento \param{optval} sia una struttura di tipo
+ \struct{linger}, definita in \texttt{sys/socket.h} ed illustrata in
+ fig.~\ref{fig:sock_linger_struct}. Maggiori dettagli sul suo funzionamento
+ sono forniti in sez.~\ref{sec:sock_options_main}.
+
+\item[\const{SO\_PRIORITY}] questa opzione permette di impostare le priorità
+ per tutti i pacchetti che sono inviati sul socket, prende per \param{optval}
+ un valore intero. Con questa opzione il kernel usa il valore per ordinare le
+ priorità sulle code di rete,\footnote{questo richiede che sia abilitato il
+ sistema di \textit{Quality of Service} disponibile con le opzioni di
+ routing avanzato.} i pacchetti con priorità più alta vengono processati
+ per primi, in modalità che dipendono dalla disciplina di gestione della
+ coda. Nel caso di protocollo IP questa opzione permette anche di impostare i
+ valori del campo \textit{type of service} (noto come TOS, vedi
+ sez.~\ref{sec:IP_xxx}) per i pacchetti uscenti. Per impostare una priorità
+ al di fuori dell'intervallo di valori fra 0 e 6 sono richiesti i privilegi
+ di amministratore con la capability \const{CAP\_NET\_ADMIN}.
+
+\item[\const{SO\_ERROR}] questa opzione riceve un errore presente sul socket;
+ può essere utilizzata soltanto con \func{getsockopt} e prende per
+ \param{optval} un valore intero.
+\end{basedescript}
+
+
+\subsection{Le uso delle principali opzioni dei socket}
+\label{sec:sock_options_main}
+
+L'elenco sintetico delle caratteristiche delle opzioni dei socket riportato in
+sez.~\ref{sec:sock_generic_options} non è sufficientemente dettagliato per
+permetterci di approfondire il significato di alcune di esse, che assumono
+grande importanza nella programmazione dei socket. Per questo motivo
+tratteremo ulteriormente l'uso di alcune di esse in questa sezione.
+
+\index{\texttt{SO\_KEEPALIVE} (costante)|(}
+La prima opzione da approfondire è \const{SO\_KEEPALIVE}, che come accennato
+permette di controllare automaticamente lo stato di una connessione. Una
+connessione infatti può restare attiva anche se non viene effettuato alcun
+traffico su di essa, ma in certi casi però può essere utile controllarne lo
+stato per accorgersi di eventuali problemi.
+
+Per questo, se si imposta questa opzione, è cura del kernel inviare degli
+appositi messaggi sulla rete (detti appunto \textit{keep-alive}) per
+verificare se la connessione è attiva. L'opzione funziona soltanto con socket
+che supportino le connessioni (non ha senso per socket UDP ad esempio), ed
+utilizza per \param{optval} un intero usato come valore logico.
+
+L'opzione si applica principalmente ai socket TCP. Con le impostazioni di
+default (che sono riprese da BSD) Linux emette un messaggio di
+\textit{keep-alive} verso l'altro capo della connessione se questa è rimasta
+senza traffico per più di due ore. Se è tutto a posto il messaggio viene
+ricevuto e verrà emesso un segmento ACK di risposta, alla cui ricezione
+ripartirà un'altro ciclo di attesa per altre due ore di inattività; tutto ciò
+viene effettuato dal kernel e le applicazioni non riceveranno nessun dato.
+
+In caso di problemi invece si possono avere i due casi già illustrati in
+sez.~\ref{sec:TCP_conn_crash} per il caso di terminazione prococe del server:
+il primo è quello in cui la macchina remota è caduta ed è stata riavviata, per
+cui dopo il riavvio la connessione non viene più riconosciuta,\footnote{si
+ ricordi che un normale riavvio non ha questo effetto, in quanto si passa per
+ la chiusura del processo, che chiude anche il socket inviando un segmento
+ FIN all'altro capo della connessione.} e si otterrà come risposta un RST. In
+tal caso il socket viene chiuso dopo aver impostato un errore
+\errcode{ECONNRESET}.
+
+Se invece non viene ricevuta nessuna risposta (indice che la macchina non è
+più raggiungibile) l'emissione dei messaggi viene ripetuta ad intervalli di 75
+secondi ad un massimo di 9 volte\footnote{entrambi questi valori possono
+ essere opportunamente modificati con gli opportuni parametri illustrati in
+ sez.~\ref{sec:sock_sysctl}, si tenga presente che però questo vale a livello
+ di kernel ed i valori saranno applicati a \textsl{tutti} i socket.} (per un
+totale di 11 minuti e 15 secondi) dopo di che, se non si è ricevuta nessuna
+risposta, il socket viene chiuso dopo aver impostato un errore di
+\errcode{ETIMEDOUT}. Se invece si riceve in risposta ad uno di questi messaggi
+un pacchetto ICMP di destinazione irraggiungibile, verrà restituito l'errore
+corrispondente.
+
+In generale questa opzione serve per individuare una caduta della
+connessione,\footnote{il crash di un processo di nuovo comporta la chiusura di
+ tutti i file che aveva aperti e la relativa emissione degli opportuni
+ segmenti FIN nel caso dei socket.} e viene usata sui server per evitare di
+mantenere impegnate le risorse dedicate a trattare delle connessioni in realtà
+terminate. Abilitandola le connessioni effettivamente terminate vengono
+chiuse ed una \func{select} potrà rilevare la conclusione delle stesse e
+ricevere il relativo errore. Si tenga però presente che non si ha la certezza
+assoluta che un errore di \errcode{ETIMEDOUT} corrisponda ad una reale
+conclusione della connessione, il problema potrebbe essere dovuto ad un
+problema di routing che perduri per un tempo maggiore di quello impiegato nei
+vari tentativi di ritrasmissione del \textit{keep-alive}.
+\index{\texttt{SO\_KEEPALIVE} (costante)|)}
+
+
+\index{\texttt{SO\_REUSEADDR} (costante)|(}
+La seconda opzione da approfondire è \const{SO\_REUSEADDR}. Come Stevens
+sottolinea in \cite{UNP1} si distinguono quattro casi per l'utilizzo di questa
+opzione; il primo è quello in cui un server è terminato ma esistono ancora dei
+processi figli che mantengono attiva almeno una connessione remota che
+utilizza l'indirizzo locale. Quando si riavvia il server questo viene bloccato
+sulla chiamata a \func{bind} dato che la porta è ancora utilizzata in una
+connessione esistente.\footnote{questa è una delle domande più frequenti sui
+ newsgroup dedicati allo sviluppo, in quanto è piuttosto comune in questa
+ situazione quando si sta sviluppando un server che si ferma e si riavvia in
+ continuazione.} Inoltre se si usa il protocollo TCP questo può avvenire
+anche dopo che l'ultimo processo figlio è terminato, dato che la connessione
+può restare attiva anche dopo la chiusura del socket mantenendosi nello stato
+\texttt{TIME\_WAIT}.
+
+Usando \const{SO\_REUSEADDR} fra la chiamata a \func{socket} e quella a
+\func{bind} si consente a quest'ultima di avere comunque successo anche se la
+connessione è attiva (o nello stato \texttt{TIME\_WAIT}). È bene però
+ricordare (si riveda quanto detto in sez.~\ref{sec:TCP_time_wait}) che la
+presenza dello stato \texttt{TIME\_WAIT} ha una ragione, ed infatti se si usa
+questa opzione esiste sempre una probabilità, anche se estremamente
+remota,\footnote{perché ciò avvenga infatti non solo devono coincidere gli
+ indirizzi IP e le porte degli estremi della nuova connessione, ma anche i
+ numeri di sequenza dei pacchetti, e questo è estremamente improbabile.} che
+eventuali pacchetti rimasti intrappolati in una precedente connessione possano
+finire fra quelli di una nuova.
+
+Il secondo caso in cui viene usata questa opzione è quando si ha una macchina
+cui sono assegnati diversi numeri IP (o come suol dirsi \textit{multi-homed})
+e si vuole porre in ascolto sulla stessa porta un programma diverso (o una
+istanza diversa dello stesso programma) per indirizzi IP diversi. Si ricordi
+infatti che è sempre possibile indicare a \func{bind} di collegarsi solo su di
+un indirizzo specifico; in tal caso se un altro programma cerca di
+riutilizzare la stessa porta (anche specificando un indirizzo diverso) otterrà
+un errore a meno di non aver preventivamente impostato \const{SO\_REUSEADDR}.
+Usando questa opzione diventa anche possibile eseguire \func{bind}
+sull'indirizzo generico, e questo permetterà il collegamento per tutti gli
+indirizzi (di quelli presenti) per i quali la porta non risulti occupata da
+una precedente chiamata più specifica. Infine si tenga presente che con il
+protocollo TCP non è mai possibile far partire server che eseguano \func{bind}
+sullo stesso indirizzo e la stessa porta, cioè ottenere quello che viene
+chiamato un \textit{completely duplicate binding}.
+
+Il terzo impiego è simile al precedente e prevede l'uso di \func{bind}
+all'interno dello stesso programma per associare indirizzi locali diversi a
+socket diversi. In genere questo viene fatto per i socket UDP quando è
+necessario ottenere l'indirizzo a cui sono rivolte le richieste del client ed
+il sistema non supporta l'opzione \const{IP\_RECVDSTADDR};\footnote{nel caso
+ di Linux questa opzione è stata supportata per in certo periodo nello
+ sviluppo del kernel 2.1.x, ma è in seguito stata soppiantata dall'uso di
+ \const{IP\_PKTINFO} (vedi sez.~\ref{sec:sock_ipv4_options}).} in tale modo
+si può sapere a quale socket corrisponde un certo indirizzo. Non ha senso per
+socket TCP dato che su di essi si può sempre invocare \func{getsockname} una
+volta che si è completata la connessione.
+
+Infine il quarto caso è quello in si vuole effettivamente ottenere un
+\textit{completely duplicate binding}, quando cioè si vuole eseguire
+\func{bind} su un indirizzo ed una porta che sono già \textsl{legati} ad un
+altro socket. Questo ovviamente non ha senso per il normale traffico di rete,
+in cui i pacchetti vengono scambiati direttamente fra due applicazioni; ma
+quando un sistema supporta il traffico in multicast, in cui una applicazione
+invia i pacchetti a molte altre (vedi sez.~\ref{sec:multicast_xxx}), allora ha
+senso che su una macchina i pacchetti provenienti dal traffico in multicast
+possano essere ricevuti da più applicazioni\footnote{l'esempio classico di
+ traffico in multicast è quello di uno streaming di dati (audio, video,
+ ecc.), l'uso del multicast consente in tal caso di trasmettere un solo
+ pacchetto, che potrà essere ricevuto da tutti i possibili destinatari
+ (invece di inviarne un duplicato a ciascuno); in questo caso è perfettamente
+ logico aspettarsi che sulla stessa macchina più utenti possano lanciare un
+ programma che permetta loro di ricevere gli stessi dati.} o da diverse
+istanze della stessa applicazione.
+
+In questo caso utilizzando \const{SO\_REUSEADDR} si consente ad una
+applicazione eseguire \func{bind} sulla stessa porta ed indirizzo usata da
+un'altra, così che anche essa possa ricevere gli stessi pacchetti (chiaramente
+la cosa non ha alcun senso per i socket TCP, ed infatti in questo tipo di
+applicazione è normale l'uso del protovollo UDP). La regola è che quando si
+hanno più applicazioni che hanno eseguito \func{bind} sulla stessa porta, di
+tutti pacchetti destinati ad un indirizzo di broadcast o di multicast viene
+inviata una copia a ciascuna applicazione. Non è definito invece cosa accade
+qualora il pacchetto sia destinato ad un indirizzo normale (unicast).
+
+Essendo questo un caso particolare in alcuni sistemi (come BSD) è stata
+introdotta una opzione ulteriore, \const{SO\_REUSEPORT} che richiede che detta
+opzione sia specificata per tutti i socket per i quali si vuole eseguire il
+\textit{completely duplicate binding}. Nel caso di Linux questa opzione non
+esiste, ma il comportamento di \const{SO\_REUSEADDR} è analogo, sarà cioè
+possibile effettuare un \textit{completely duplicate binding} ed ottenere il
+successo di \func{bind} su un socket legato allo stesso indirizzo e porta solo
+se il primo programma che ha eseguito \func{bind} su di essi ha impostato
+questa opzione.\footnote{Questa restrizione permette di evitare il cosiddetto
+ \textit{port stealing}, in cui un programma, usando \const{SO\_REUSEADDR},
+ può collegarsi ad una porta già in uso e ricevere i pacchetti destinati ad
+ un altro programma; con questa caratteristica ciò è possibile soltanto se il
+ primo programma a consentirlo, avendo usato fin dall'inizio
+ \const{SO\_REUSEADDR}.}
+\index{\texttt{SO\_REUSEADDR} (costante)|)}
+
+
+\index{\texttt{SO\_LINGER} (costante)|(} La terza opzione da approfondire è
+\const{SO\_LINGER}; essa, come il nome suggerisce, consente di
+\textsl{indugiare} nella chiusura di un socket. Il comportamento standard sia
+di \func{close} che \func{shutdown} è quello di terminare immediatamente dopo
+la chiamata, mentre il procedimento di chiusura della connessione e l'invio
+sulla rete di tutti i dati ancora presenti nei buffer viene gestito in
+sottofondo dal kernel.
+
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \includecodesample{listati/TCP_echod_third.c}
+ \includestruct{listati/linger.h}
\end{minipage}
- \normalsize
- \caption{Nuovo codice per l'apertura passiva del server \textit{echo}.}
- \label{fig:TCP_echod_third}
+ \caption{La struttura \structd{linger} richiesta come valore dell'argomento
+ \param{optval} per l'impostazione dell'opzione dei socket
+ \const{SO\_LINGER}.}
+ \label{fig:sock_linger_struct}
\end{figure}
+L'uso di \const{SO\_LINGER} permette di modificare (ed eventualmente
+ripristinare) questo comportamento in base ai valori passati nei campi della
+stuttura \struct{linger}. Fintanto che il valore del campo \var{l\_onoff} di
+\struct{linger} è nullo la modalità che viene impostata (qualunque sia il
+valore di \var{l\_linger}) è quella standard appena illustrata.
+Se però si utilizza un valore di \var{l\_onoff} diverso da zero per
+l'impostazione di \const{SO\_LINGER} il comportamento dipende dal valore di
+\var{l\_linger}; se quest'ultimo è nullo l'uso delle funzioni \func{close} e
+\func{shutdown} provoca la terminazione immediata della connessione: nel caso
+di TCP cioè non viene eseguito il procedimento di chiusura illustrato in
+sez.~\ref{sec:TCP_conn_term}, ma viene inviato un segmento di RST che termina
+immediatamente la connessione. Se invece \var{l\_linger} ha un valore diverso
+da zero sia \func{close} che \func{shutdown} si bloccano e non ritornano
+fintanto che non si sia concluso il procedimento di chiusura della
+connessione, o non siano passati il numero di secondi specificati da
+\var{l\_linger}.
+\index{\texttt{SO\_LINGER} (costante)|)}
-\section{Le opzioni dei socket}
-\label{sec:TCP_sock_options}
-Finora abbiamo trattato i socket nel loro comportamento più comune, è però
-possibile attivare alcune modalità diverse di funzionamento degli stessi
-Dato che la maggior parte delle opzioni dei socket sono relative ai socket
- TCP, ed hanno poi significato analogo quando usate con altri socket, abbiamo
-preferito trattare l'argomento in generale in questa sezione piuttosto che nel
-capitolo dedicato alla trattazione generica dei socket.
-\section{Altre funzioni di controllo}
-\label{sec:TCP_sock_ctrl}
+\subsection{Le opzioni per il protocollo IPv4}
+\label{sec:sock_ipv4_options}
+
+Il secondo insieme di opzioni dei socket che tratteremo è quello relativo ai
+socket che usano il protocollo IPv4.\footnote{come per le precedenti opzioni
+ generiche una descrizione di esse è disponibile nella settima sezione delle
+ pagine di manuale, nel caso specifico la documentazione si può consultare
+ con \texttt{man 7 ip}.} Se si vuole operare su queste opzioni generiche il
+livello da utilizzare è \const{SOL\_IP}; si è riportato un elenco di queste
+opzioni in tab.~\ref{tab:sock_opt_iplevel}.
+\begin{table}[!htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|c|c|c|l|l|}
+ \hline
+ \textbf{Opzione}&\texttt{get}&\texttt{set}&\textbf{flag}&\textbf{Tipo}&
+ \textbf{Descrizione}\\
+ \hline
+ \hline
+ \const{IP\_OPTIONS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Imposta o riceve le opzioni di IP.\\
+ \const{IP\_PKTINFO}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Passa un messaggio di informazione.\\
+ \const{IP\_RECVTOS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Passa un messaggio col campo TOS.\\
+ \const{IP\_RECVTTL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Passa un messaggio col campo TTL.\\
+ \const{IP\_RECVOPTS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Passa un messaggio con le opzioni IP.\\
+ \const{IP\_RETOPTS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Passa un messaggio con le opzioni IP non
+ trattate.\\
+ \const{IP\_TOS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Imposta il valore del campo TOS.\\
+ \const{IP\_TTL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Imposta il valore del campo TTL.\\
+ \const{IP\_HDRINCL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Passa l'intestazione di IP nei dati.\\
+ \const{IP\_RECVERR}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Abilita la gestione degli errori.\\
+ \const{IP\_MTU\_DISCOVER}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Imposta il Path MTU Discovery.\\
+ \const{IP\_MTU}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Legge il valore attuale della MTU.\\
+ \const{IP\_ROUTER\_ALERT}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Imposta l'opzione \textit{IP router alert} sui
+ pacchetti.\\
+ \const{IP\_MULTICAST\_TTL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Imposta il TTL per i pacchetti multicast.\\
+ \const{IP\_MULTICAST\_LOOP}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Controlla il reinvio a se
+ stessi dei dati di multicast.\\
+ \const{IP\_ADD\_MEMBERSHIP}& &$\bullet$&$\bullet$&\texttt{int}&
+ Si unisce a un gruppo di multicast.\\
+ \const{IP\_DROP\_MEMBERSHIP}& &$\bullet$&$\bullet$&\texttt{int}&
+ Si sgancia da un gruppo di multicast.\\
+ \const{IP\_MULTICAST\_IF}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+ Imposta l'interfaccia locale di un socket
+ multicast.\\
+ \hline
+ \end{tabular}
+ \caption{Le opzioni disponibili al livello \const{SOL\_IP}.}
+ \label{tab:sock_opt_iplevel}
+\end{table}
+
+
+Le descrizioni di tab.~\ref{tab:sock_opt_iplevel} sono estremamente succinte,
+una maggiore quantità di dettagli su queste opzioni è fornito nel seguente
+elenco:
+\begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{IP\_MULTICAST\_LOOP}] L'opzione consente di decidere se i dati
+ che si inviano su un socket usato con il multicast vengano ricevuti anche
+ sulla stessa macchina da cui li si stanno inviando. Prende per
+ \param{optval} un intero usato come valore logico.
+
+ In generale se si vuole che eventuali client possano ricevere i dati che si
+ inviano occorre che questa funzionalità sia abilitata (come avviene di
+ default). Qualora però non si voglia generare traffico per dati che già sono
+ disponibili l'uso di questa opzione permette di disabilitare questo tipo di
+ traffico.
+
+\end{basedescript}
+
+
+
+
+
+\section{Altre funzioni di controllo}
+\label{sec:sock_ctrl_func}
+
+Benché la maggior parte delle caratteristiche dei socket sia gestita
+attraverso le due funzioni \func{setsockopt} e \func{getsockopt}, alcune
+funzionalità possono essere impostate attraverso quelle che sono le funzioni
+classiche per il controllo delle proprietà dei file, cioè \func{fcntl} e
+\func{ioctl}.
+
+
+\subsection{L'uso di \func{fcntl} per i socket}
+\label{sec:sock_fcntl}
+
+Abbiamo già trattato l'uso di \func{fcntl} in sez.~\ref{sec:file_fcntl}, dove
+però ne abbiamo descritto le funzionalità nell'ambito della sua applicazione a
+file descriptor associati a file normali; tratteremo qui invece il suo uso
+specifico quando la si impiega su file descriptor associati a dei socket.
+
+
+\subsection{L'uso di \func{ioctl} per i socket}
+\label{sec:sock_ioctl}
+
+Come per \func{fcntl} abbiamo trattato l'uso di \func{ioctl} in
+sez.~\ref{sec:file_ioctl}, dove ne abbiamo descritto le funzionalità
+nell'ambito dell'applicazione su file normali; tratteremo qui il suo uso
+specifico quando la si impiega su file descriptor associati a dei socket.
+
+
+\subsection{L'uso di \func{sysctl} per le proprietà della rete}
+\label{sec:sock_sysctl}
+
+Come ultimo argomento di questa sezione tratteremo l'uso della funzione
+\func{sysctl} (che è stata introdotta nelle sue funzionalità generiche in
+sez.~\ref{sec:sys_sysctl}) per quanto riguarda le sue capacità di effettuare
+impostazioni relative a proprietà generali dei socket (di tutti quelli di un
+certo tipo o di tutti quelli che usano un certo protocollo) rispetto alle
+funzioni viste finora che consentono di controllare quelle di un singolo
+socket.
+
+Le opzioni disponibili per le proprietà della rete sono riportate nella
+gerarchia dei valori impostabili con \func{sysctl}, sotto il nodo
+\texttt{net}, o, se acceduti tramite l'interfaccia del filesystem
+\texttt{/proc}, sotto \texttt{/proc/sys/net}. In genere sotto questa directory
+compaiono le sottodirectory (corrispondenti ad altrettanti sottonodi per
+\func{sysctl}) relative ai vari protocolli e tipi di interfacce su cui è
+possibile intervenire; un contenuto tipico è il seguente:
+\begin{verbatim}
+/proc/sys/net/
+|-- core
+|-- ethernet
+|-- ipv4
+|-- ipv6
+|-- irda
+|-- token-ring
+`-- unix
+\end{verbatim}
+
+
+Nella directory \texttt{/proc/sys/net/core} sono disponibili le opzioni
+generiche dei socket, descritte anche nella rispettiva pagina di
+manuale.\footnote{quella accessibile con \texttt{man 7 socket}.} Queste sono:
+
+\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}}
+\item[\texttt{rmem\_default}] imposta la dimensione di default del buffer di
+ lettura (cioè per i dati in ingresso) dei socket.
+\item[\texttt{rmem\_max}] imposta la dimensione massima che si può assegnare al
+ buffer di ingresso dei socket attraverso l'uso dell'opzione
+ \const{SO\_RCVBUF}.
+\item[\texttt{wmem\_default}] imposta la dimensione di default del buffer di
+ scrittura (cioè per i dati in uscita) dei socket.
+\item[\texttt{wmem\_max}] imposta la dimensione massima che si può assegnare al
+ buffer di uscita dei socket attraverso l'uso dell'opzione
+ \const{SO\_SNDBUF}.
+\item[\texttt{message\_cost}]
+\item[\texttt{message\_burst}]
+\item[\texttt{netdev\_max\_backlog}]
+\item[\texttt{optmem\_max}]
+\end{basedescript}
%%% Local Variables: