%% 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}
+\itindbeg{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
dominio}.\footnote{non staremo ad entrare nei dettagli della definizione di
cosa è un nome a dominio, dandolo per noto, una introduzione alla
- problematica si trova in \cite{AGL} (cap. 9) mentre per una trattazione
+ problematica si trova in \cite{AGL} (cap.~9) mentre per una trattazione
approfondita di tutte le problematiche relative al DNS si può fare
riferimento a \cite{DNSbind}.} In realtà per DNS si intendono spesso i
server che forniscono su internet questo servizio, mentre nel nostro caso
\begin{figure}[htb]
\centering
- \includegraphics[width=10cm]{img/resolver}
- \caption{Schema di funzionamento delle routine del \textit{resolver}.}
+ \includegraphics[width=9cm]{img/resolver}
+ \caption{Schema di funzionamento delle funzioni del \textit{resolver}.}
\label{fig:sock_resolver_schema}
\end{figure}
sez.~\ref{sec:sys_user_group} per le corrispondenze fra nomi di utenti e
gruppi e relativi identificatori numerici; per quanto riguarda però tutti i
nomi associati a identificativi o servizi relativi alla rete il servizio di
-risoluzione è gestito in maniera unificata da un insieme di routine fornite
+risoluzione è gestito in maniera unificata da un insieme di funzioni fornite
con le librerie del C, detto appunto \textit{resolver}.
Lo schema di funzionamento del \textit{resolver} è illustrato in
funzioni di libreria, prevedendo un ordine di interrogazione predefinito e
non modificabile (a meno di una ricompilazione delle librerie stesse).}
+\itindbeg{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
(\acr{uid}, ecc.).\\
\texttt{group} & corrispondenze fra nome del gruppo e proprietà dello
stesso.\\
- \texttt{aliases} & alias per la posta elettronica\\
+ \texttt{aliases} & alias per la posta elettronica.\\
\texttt{ethers} & corrispondenze fra numero IP e MAC address della
scheda di rete.\\
\texttt{hosts} & corrispondenze fra nome a dominio e numero IP.\\
\label{tab:sys_NSS_classes}
\end{table}
-Il sistema del \textit{Name Service Switch} è controllato dal contenuto del
+Il sistema del \textit{Name Service Switch} è controllato dal contenuto del
file \file{/etc/nsswitch.conf}; questo contiene una riga\footnote{seguendo una
convezione comune per i file di configurazione le righe vuote vengono
ignorate e tutto quello che segue un carattere ``\texttt{\#}'' viene
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.
+\itindend{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
messaggio di errore già formattato, corrispondente al codice passato come
argomento (che si presume sia dato da \var{h\_errno}).
-
+\itindend{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 \itindex{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 \itindex{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
+\itindex{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
i dati, in quanto questa contiene puntatori ad altri dati, che pure possono
essere sovrascritti; per questo motivo, se si vuole salvare il risultato di
una chiamata, occorrerà eseguire quella che si chiama una
-\index{\textit{deep~copy}}\textit{deep copy}.\footnote{si chiama così quella
- tecnica per cui, quando si deve copiare il contenuto di una struttura
- complessa (con puntatori che puntano ad altri dati, che a loro volta possono
- essere puntatori ad altri dati) si deve copiare non solo il contenuto della
+\itindex{deep~copy}\textit{deep copy}.\footnote{si chiama così quella tecnica
+ per cui, quando si deve copiare il contenuto di una struttura complessa (con
+ puntatori che puntano ad altri dati, che a loro volta possono essere
+ puntatori ad altri dati) si deve copiare non solo il contenuto della
struttura, ma eseguire una scansione per risolvere anche tutti i puntatori
contenuti in essa (e così via se vi sono altre sottostrutture con altri
puntatori) e copiare anche i dati da questi referenziati.}
\param{buf} e \param{buflen}.
Gli ultimi due argomenti vengono utilizzati per avere indietro i risultati
-come \index{\textit{value~result~argument}}\textit{value result argument}, si
-deve specificare l'indirizzo della variabile su cui la funzione dovrà salvare
-il codice di errore con \param{h\_errnop} e quello su cui dovrà salvare il
+come \itindex{value~result~argument}\textit{value result argument}, si deve
+specificare l'indirizzo della variabile su cui la funzione dovrà salvare il
+codice di errore con \param{h\_errnop} e quello su cui dovrà salvare il
puntatore che si userà per accedere i dati con \param{result}.
In caso di successo entrambe le funzioni restituiscono un valore nullo,
In questo caso l'argomento \param{addr} dovrà essere il puntatore ad una
appropriata struttura contenente il valore dell'indirizzo IP (o IPv6) che si
-vuole risolvere. L'uso del tipo \type{char *} per questo argomento è storico,
-il dato dovrà essere fornito in una struttura \struct{in\_addr}\footnote{si
- ricordi che, come illustrato in fig.~\ref{fig:sock_sa_ipv4_struct}, questo
- in realtà corrisponde ad un numero intero, da esprimere comunque in
- \textit{network order}, non altrettanto avviene però per \var{in6\_addr},
- pertanto è sempre opportuno inizializzare questi indirizzi con
- \func{inet\_pton} (vedi sez.~\ref{sec:sock_conv_func_gen}).} per un
-indirizzo IPv4 ed una struttura \struct{in6\_addr} per un indirizzo IPv6,
-mentre in \param{len} se ne dovrà specificare la dimensione (rispettivamente 4
-o 16), infine l'argomento \param{type} indica il tipo di indirizzo e dovrà
-essere o \const{AF\_INET} o \const{AF\_INET6}.
+vuole risolvere. L'uso del tipo \texttt{char *} per questo argomento è
+storico, il dato dovrà essere fornito in una struttura
+\struct{in\_addr}\footnote{si ricordi che, come illustrato in
+ fig.~\ref{fig:sock_sa_ipv4_struct}, questo in realtà corrisponde ad un
+ numero intero, da esprimere comunque in \textit{network order}, non
+ altrettanto avviene però per \struct{in6\_addr}, pertanto è sempre opportuno
+ inizializzare questi indirizzi con \func{inet\_pton} (vedi
+ sez.~\ref{sec:sock_conv_func_gen}).} per un indirizzo IPv4 ed una struttura
+\struct{in6\_addr} per un indirizzo IPv6, mentre in \param{len} se ne dovrà
+specificare la dimensione (rispettivamente 4 o 16), infine l'argomento
+\param{type} indica il tipo di indirizzo e dovrà essere o \const{AF\_INET} o
+\const{AF\_INET6}.
La funzione restituisce, in caso di successo, un puntatore ad una struttura
\struct{hostent}, solo che in questo caso la ricerca viene eseguita
sistema è associata ad un indirizzo di tale tipo.\\
\const{AI\_DEFAULT} & il valore di default, è equivalente alla
combinazione di \const{AI\_ADDRCONFIG} e di
- \const{AI\_V4MAPPED)}.\\
+ \const{AI\_V4MAPPED}.\\
\hline
\end{tabular}
\caption{Valori possibili per i bit dell'argomento \param{flags} della
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.
\textbf{Informazione}&\multicolumn{3}{|c|}{\textbf{Funzioni}}\\
\hline
\hline
- indirizzo&\func{sethostent}&\func{gethostent}&\func{endhostent} \\
- servizio &cd te\func{setservent}&\func{getservent}&\func{endservent}\\
- rete &\func{setnetent}&\func{getnetent}&\func{endnetent}\\
+ indirizzo &\func{sethostent} &\func{gethostent} &\func{endhostent} \\
+ servizio &\func{setservent} &\func{getservent} &\func{endservent}\\
+ rete &\func{setnetent} &\func{getnetent} &\func{endnetent}\\
protocollo&\func{setprotoent}&\func{getprotoent}&\func{endprotoent}\\
\hline
\end{tabular}
risoluzioni sui nomi dei servizi indipendentemente dal protocollo (ad esempio
TCP o UDP) che questi possono utilizzare.
+Come ultimo argomento in \param{res} deve essere passato un puntatore ad una
+variabile (di tipo puntatore ad una struttura \struct{addrinfo}) che verrà
+utilizzata dalla funzione per riportare (come \itindex{value~result~argument}
+\textit{value result argument}) i propri risultati. La funzione infatti è
+rientrante, ed alloca autonomamente tutta la memoria necessaria in cui
+verranno riportati i risultati della risoluzione. La funzione scriverà
+all'indirizzo puntato da \param{res} il puntatore iniziale ad una
+\itindex{linked~list}\textit{linked list} di strutture di tipo
+\struct{addrinfo} contenenti tutte le informazioni ottenute.
+
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
\label{fig:sock_addrinfo_struct}
\end{figure}
-La struttura \struct{addrinfo}, la cui definizione\footnote{la definizione è
- ripresa direttamente dal file \texttt{netdb.h} in questa struttura viene
- dichiarata, la pagina di manuale riporta \type{size\_t} come tipo di dato
- per il campo \var{ai\_addrlen}, qui viene usata quanto previsto dallo
- standard POSIX, in cui viene utilizzato \type{socklen\_t}; i due tipi di
- dati sono comunque equivalenti.} è riportata in
+Come illustrato la struttura \struct{addrinfo}, la cui definizione\footnote{la
+ definizione è ripresa direttamente dal file \texttt{netdb.h} in questa
+ struttura viene dichiarata, la pagina di manuale riporta \type{size\_t} come
+ tipo di dato per il campo \var{ai\_addrlen}, qui viene usata quanto previsto
+ dallo standard POSIX, in cui viene utilizzato \type{socklen\_t}; i due tipi
+ di dati sono comunque equivalenti.} è riportata in
fig.~\ref{fig:sock_addrinfo_struct}, viene usata sia in ingresso, per passare
dei valori di controllo alla funzione, che in uscita, per ricevere i
risultati. Il primo campo, \var{ai\_flags}, è una maschera binaria di bit che
famiglia di indirizzi, il tipo di socket e il protocollo, in ingresso vengono
usati per impostare una selezione (impostandone il valore nella struttura
puntata da \param{hints}), mentre in uscita indicano il tipo di risultato
-contenuto nella struttura.
+contenuto nella struttura.
Tutti i campi seguenti vengono usati soltanto in uscita; il campo
\var{ai\_addrlen} indica la dimensione della struttura degli indirizzi
\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
\label{tab:ai_flags_values}
\end{table}
-Come ultimo argomento di \func{getaddrinfo} deve essere passato un puntatore
-ad una variabile (di tipo puntatore ad una struttura \struct{addrinfo}) che
-verrà utilizzata dalla funzione per riportare (come \textit{value result
- argument}) i propri risultati. La funzione infatti è rientrante, ed alloca
-autonomamente tutta la memoria necessaria in cui verranno riportati i
-risultati della risoluzione. La funzione scriverà in \param{res} il puntatore
-iniziale ad una \textit{linked list} di strutture di tipo \struct{addrinfo}
-contenenti tutte le informazioni ottenute.
-
La funzione restituisce un valore nullo in caso di successo, o un codice in
caso di errore. I valori usati come codice di errore sono riportati in
tab.~\ref{tab:addrinfo_error_code}; dato che la funzione utilizza altre
\const{EAI\_SYSTEM} & c'è stato un errore di sistema, si può controllare
\var{errno} per i dettagli. \\
% \hline
-% estensioni GNU, trovarne la documentazione
+% TODO estensioni GNU, trovarne la documentazione
% \const{EAI\_INPROGRESS}& richiesta in corso. \\
% \const{EAI\_CANCELED}& la richiesta è stata cancellata.\\
% \const{EAI\_NOTCANCELED}& la richiesta non è stata cancellata. \\
\begin{figure}[!htb]
\centering
\includegraphics[width=10cm]{img/addrinfo_list}
- \caption{La \textit{linked list} delle strutture \struct{addrinfo}
- restituite da \func{getaddrinfo}.}
+ \caption{La \itindex{linked~list}\textit{linked list} delle strutture
+ \struct{addrinfo} restituite da \func{getaddrinfo}.}
\label{fig:sock_addrinfo_list}
\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 \itindex{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.
\end{Verbatim}
%$
-Una volta estratti i risultati dalla \textit{linked list} puntata da
-\param{res} se questa non viene più utilizzata si dovrà avere cura di
-disallocare opportunamente tutta la memoria, per questo viene fornita
+Una volta estratti i risultati dalla \itindex{linked~list}\textit{linked list}
+puntata da \param{res} se questa non viene più utilizzata si dovrà avere cura
+di disallocare opportunamente tutta la memoria, per questo viene fornita
l'apposita funzione \funcd{freeaddrinfo}, il cui prototipo è:
\begin{functions}
\headdecl{netdb.h}
Si tenga presente infine che se si copiano i risultati da una delle strutture
\struct{addrinfo} restituite nella lista indicizzata da \param{res}, occorre
-avere cura di eseguire una \index{\textit{deep~copy}}\textit{deep copy} in cui
+avere cura di eseguire una \itindex{deep~copy}\textit{deep copy} in cui
si copiano anche tutti i dati presenti agli indirizzi contenuti nella
struttura \struct{addrinfo}, perché una volta disallocati i dati con
\func{freeaddrinfo} questi non sarebbero più disponibili.
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
-diverse funzionalità e caratteristiche per ciascun protocollo usato da un
-socket, e quindi saranno anche diverse le opzioni che di potranno impostare, a
-seconda del \textsl{livello} (trasporto, rete, ecc.) su cui si va ad operare.
+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, e permette di usare per \param{optname} i valori delle opzioni
-che sono definite su quel protocollo. Esiste però anche il valore speciale
-\const{SOL\_SOCKET} che indica un livello di base e cioè le opzioni
-disponibili per qualunque tipo di socket. Per impostare le opzioni relative
-alle funzionalità dei singoli protocolli si deve utilizzare il valore numerico
-che identifica questi ultimi in \file{/etc/protocols}; più comunemente si
-usano le apposite costanti \texttt{SOL\_*} riportate in
-tab.~\ref{tab:sock_option_levels}, dove si sono riassunti i valori possibili
-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
+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
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 (e il tipo di dati varia a seconda dell'opzione), 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
+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 si deve usare particolare 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}.
+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 è
-\func{getsockopt}, che serve a leggere i valori delle opzioni dd a farsi
-restituire i dati relativi al loro funzionamento; il suo prototipo è:
+\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}
\end{functions}
I primi tre argomenti sono identici ed hanno lo stesso significato di quelli
-di \func{setsockopt}, mentre \param{optval} in questo caso indica l'indirizzo
-a cui andranno scritti i dati letti dal socket, e \param{optlen} è usata come
-\textit{value result argument} per indicare la lunghezza del buffer allocato
-per \param{optval} e per ricevere indietro la dimensione effettiva dei dati
-scritti su di esso.
+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 \itindex{value~result~argument}\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}
-Anche se ciascun tipo di socket presenta una serie di caratteristiche
-particolari, gestite attraverso delle opzioni specifiche, esiste un insieme
-generico di opzioni che possono applicarsi a qualunque tipo di
-socket.\footnote{una descrizione di queste opzioni è generalmente disponibile
- nella quarta sezione delle pagine di manuale con \texttt{man 4 socket}.}
-Come detto in tal caso il livello da scegliere è \const{SOL\_SOCKET}
+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.
+
+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 inoltre 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 è quindi
+soltanto un elenco più dettagliato della breve descrizione di
+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.
+
+% TODO verificare il timeout 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{sendto} 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 \itindex{capabilities}
+ \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_header}) 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 \itindex{capabilities} 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{L'uso delle principali opzioni dei socket}
+\label{sec:sock_options_main}
+
+La descrizione sintetica del significato delle opzioni generiche dei socket,
+riportata nell'elenco in sez.~\ref{sec:sock_generic_options}, è
+necessariamente sintentica, alcune di queste però possono essere utilizzate
+per controllare delle funzionalità che hanno una notevole rilevanza nella
+programmazione dei socket. Per questo motivo faremo in questa sezione un
+approfondimento sul significato delle opzioni generiche più importanti.
+
+
+\index{costante!{SO\_KEEPALIVE}@{{\tt {SO\_KEEPALIVE}}}|(}
+\subsubsection{L'opzione \const{SO\_KEEPALIVE}}
+
+La prima opzione da approfondire è \const{SO\_KEEPALIVE} che permette di
+tenere sotto controllo lo stato di una connessione. Una connessione infatti
+resta attiva anche quando non viene effettuato alcun traffico su di essa,
+questo può comportare che un crollo della connessione, qualora avvenisse ad
+esempio in conseguenza di una interruzione completa della rete, potrebbe
+passare inosservato.
+
+Se si imposta questa opzione, è invece 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) e si applica
+principalmente ai socket TCP.
+
+Con le impostazioni di default (che sono riprese da BSD) Linux emette un
+messaggio di \textit{keep-alive}\footnote{in sostanza un segmento ACK vuoto,
+ cui sarà risposto con un altro segmento ACK vuoto.} 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à; il tutto avviene all'interno del 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 in tal caso
+ si passa per la chiusura del processo, e questo, come illustrato in
+ sez.~\ref{sec:file_close}, comporta la chiusura del socket col'invio di un
+ segmento FIN all'altro capo della connessione, che verrà regolarmente
+ chiusa.} in questo caso all'invio del messaggio di \textit{keep-alive} si
+otterrà come risposta un segmento RST che indica che l'altro capo non
+riconosce più l'esistenza della connessione. 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 per 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 suddetti 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}. Qualora la connessione si sia ristabilita e si riceva un
+successivo messaggio di risposta il ciclo riparte come se niente fosse
+avvenuto. Infine se invece si riceve come risposta un pacchetto ICMP di
+destinazione irraggiungibile (vedi sez.~\ref{sec:icmp_protocol_xxx}), verrà
+restituito l'errore corrispondente.
+
+In generale questa opzione serve per individuare una caduta della connessione
+anche quando non si sta facendo traffico su di essa. Viene usata
+principalmente sui server per evitare di mantenere impegnate le risorse che
+verrbbero dedicate a trattare delle connessioni che in realtà sono già
+terminate (quelle che vengono anche chiamate connessioni
+\textsl{semi-aperte}); in tutti quei casi cioè in cui il server si trova in
+attesa di dati in ingresso su una connessione che non arriveranno mai perché o
+il client sull'altro capo non è più attivo o non è più in grado di comunicare
+con il server via rete.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/TCP_echod_fourth.c}
+ \end{minipage}
+ \normalsize
+ \caption{La sezione della nuova versione del server del servizio
+ \textit{echo} che prevede l'attivazione del \textit{keepalive} sui
+ socket.}
+ \label{fig:echod_keepalive_code}
+\end{figure}
+Abilitandola dopo un certo tempo le connessioni effettivamente terminate
+verrano comunque chiuse per cui, utilizzando ad esempio una \func{select}, se
+be potrà rilevare la conclusione e ricevere il relativo errore. Si tenga
+presente però che non può avere la certezza assoluta che un errore di
+\errcode{ETIMEDOUT} ottenuto dopo aver abilitato questa opzione corrisponda
+necessariamente ad una reale conclusione della connessione, il problema
+potrebbe anche 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} (anche se questa non è una condizione molto probabile).
+
+Come esempio dell'utilizzo di questa opzione introduciamo all'interno del
+nostro server per il servizio \textit{echo} la nuova opzione \texttt{-k} che
+permette di attivare il \textit{keep-alive} sui socket; tralasciando la parte
+relativa alla gestione di detta opzione (che si limita ad assegnare ad 1 la
+variabile \var{keepalive}) tutte le modifiche al server sono riportate in
+fig.~\ref{fig:echod_keepalive_code}. Al solito il codice completo è contenuto
+nel file \texttt{TCP\_echod\_fourth.c} dei sorgenti allegati alla guida.
+
+Come si può notare la variabile \var{keepalive} è preimpostata (\texttt{\small
+ 8}) ad un valore nullo; essa viene utilizzata sia come variabile logica per
+la condizione (\texttt{\small 14}) che controlla l'attivazione del
+\textit{keep-alive} che come valore dell'argomento \param{optval} della
+chiamata a \func{setsockopt} (\texttt{\small 16}). A seconda del suo valore
+tutte le volte che un processo figlio viene eseguito in risposta ad una
+connessione verrà pertanto eseguita o meno la sezione (\texttt{\small 14--17})
+che esegue l'impostazione di \const{SO\_KEEPALIVE} sul socket connesso,
+attivando il relativo comportamento.
+\index{costante!{SO\_KEEPALIVE}@{{\tt {SO\_KEEPALIVE}}}|)}
+
+
+
+\index{costante!{SO\_REUSEADDR}@{{\tt {SO\_REUSEADDR}}}|(}
+\subsubsection{L'opzione \const{SO\_REUSEADDR}}
+
+La seconda opzione da approfondire è \const{SO\_REUSEADDR}, che consente di
+eseguire \func{bind} su un socket anche quando la porta specificata è già in
+uso da parte di un altro socket. Si ricordi infatti che, come accennato in
+sez.~\ref{sec:TCP_func_bind}, normalmente la funzione \func{bind} fallisce con
+un errore di \errcode{EADDRINUSE} se la porta scelta è già utilizzata da un
+altro socket, proprio per evitare che possano essere lanciati due server sullo
+stesso indirizzo e la stessa porta, che verrebbero a contendersi i pacchetti
+aventi quella destinazione.
+
+Esistono però situazioni ed esigenze particolari in cui non si vuole che
+questo comportamento di salvaguardia accada, ed allora si può fare ricorso a
+questa opzione. La questione è comunque abbastanza complessa in quanto, come
+sottolinea Stevens in \cite{UNP1}, si distinguono ben quattro casi diversi in
+cui è prevista la possibilità di un utilizzo di questa opzione, il che la
+rende una delle più difficili da capire.
+
+Il primo caso, che è anche il più comune, in cui si fa ricorso a
+\const{SO\_REUSEADDR} è quello in cui un server è terminato ma esistono ancora
+dei processi figli che mantengono attiva almeno una connessione remota che
+utilizza l'indirizzo locale, mantenendo occupata la porta. Quando si riesegue
+il server allora questo riceve un errore 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 trovarsi in questa situazione quando si sta
+ sviluppando un server che si ferma e si riavvia in continuazione dopo aver
+ fatto modifiche.} Inoltre se si usa il protocollo TCP questo può avvenire
+anche dopo tutti i processi figli sono terminati, dato che una connessione può
+restare attiva anche dopo la chiusura del socket, mantenendosi nello stato
+\texttt{TIME\_WAIT} (vedi sez.~\ref{sec:TCP_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.
+
+Come esempio di uso di questa connessione abbiamo predisposto una nuova
+versione della funzione \func{sockbind} (vedi fig.~\ref{fig:sockbind_code})
+che consenta l'impostazione di questa opzione. La nuova funzione è
+\func{sockbindopt}, e le principali differenze rispetto alla precedente sono
+illustrate in fig.~\ref{fig:sockbindopt_code}, dove si sono riportate le
+sezioni di codice modificate rispetto alla versione precedente. Il codice
+completo della funzione si trova, insieme alle altre funzioni di servizio dei
+socket, all'interno del file \texttt{SockUtils.c} dei sorgenti allegati alla
+guida.
-In generale il valore di \param{optname} viene passato invariato al
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/sockbindopt.c}
+ \end{minipage}
+ \normalsize
+ \caption{Le sezioni della funzione \func{sockbindopt} modificate rispetto al
+ codice della precedente \func{sockbind}.}
+ \label{fig:sockbindopt_code}
+\end{figure}
+In realtà tutto quello che si è fatto è stato introdurre nella nuova funzione
+(\texttt{\small 1}) un nuovo argomento intero, \param{reuse}, che conterrà il
+valore logico da usare nella successiva chiamata (\texttt{\small 14}) a
+\func{setsockopt}. Si è poi aggiunta una sezione (\texttt{\small 13-17}) che
+esegue l'impostazione dell'opzione fra la chiamata a \func{socket} e quella a
+\func{bind}.
+
+
+A questo punto basterà modificare il server per utilizzare la nuova
+funzione; in fig.~\ref{fig:TCP_echod_fifth} abbiamo riportato le sezioni
+modificate rispetto alla precedente versione di
+fig.~\ref{fig:TCP_echod_third}. Al solito il codice completo è coi sorgenti
+allegati alla guida, nel file \texttt{TCP\_echod\_fifth.c}.
+
+Anche in questo caso si è introdotta (\texttt{\small 8}) una nuova variabile
+\var{reuse} che consente di controllare l'uso dell'opzione e che poi sarà
+usata (\texttt{\small 14}) come ultimo argomento di \func{setsockopt}. Il
+valore di default di questa variabile è nullo, ma usando l'opzione \texttt{-r}
+nell'invocazione del server (al solito la gestione delle opzioni non è
+riportata in fig.~\ref{fig:TCP_echod_fifth}) se ne potrà impostare ad 1 il
+valore, per cui in tal caso la successiva chiamata (\texttt{\small 13-17}) a
+\func{setsockopt} attiverà l'opzione \const{SO\_REUSEADDR}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/TCP_echod_fifth.c}
+ \end{minipage}
+ \normalsize
+ \caption{Il nuovo codice per l'apertura passiva del server \textit{echo} che
+ usa la nuova funzione \func{sockbindopt}.}
+ \label{fig:TCP_echod_fifth}
+\end{figure}
+Il secondo caso in cui viene usata \const{SO\_REUSEADDR} è 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
+fare questa operazione per un 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 cui 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 \itindex{multicast}\textit{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.
+\itindex{multicast}
+
+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 \itindex{multicast}
+\texttt{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 programma che ha eseguito per primo \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{costante!{SO\_REUSEADDR}@{{\tt {SO\_REUSEADDR}}}|)}
+
+\index{costante!{SO\_LINGER}@{{\tt {SO\_LINGER}}}|(}
+\subsubsection{L'opzione \const{SO\_LINGER}}
+
+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} è infatti
+quello di terminare immediatamente dopo la chiamata, mentre il procedimento di
+chiusura della connessione (o di un lato di essa) ed il rispettivo 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}
+ \includestruct{listati/linger.h}
+ \end{minipage}
+ \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} con \func{setsockopt} permette di modificare (ed
+eventualmente ripristinare) questo comportamento in base ai valori passati nei
+campi della stuttura \struct{linger}, illustrata in
+fig.~\ref{fig:sock_linger_struct}. 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; questa combinazione viene utilizzata per riportarsi al
+comportamento normale qualora esso sia stato cambiato da una precedente
+chiamata.
+
+Se si utilizza un valore di \var{l\_onoff} diverso da zero, il comportamento
+alla chiusura viene a dipendere dal valore specificato per il campo
+\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 tutti i dati ancora presenti nel buffer
+vengono immediatamente scartati e sulla rete viene inviato un segmento di RST
+che termina immediatamente la connessione.
+
+Un esempio di questo comportamento si può abilitare nel nostro client del
+servizio \textit{echo} utilizzando l'opzione \texttt{-r}; riportiamo in
+fig.~\ref{fig:TCP_echo_sixth} la sezione di codice che permette di introdurre
+questa funzionalità,; al solito il codice completo è disponibile nei sorgenti
+allegati.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/TCP_echo_sixth.c}
+ \end{minipage}
+ \normalsize
+ \caption{La sezione del codice del client \textit{echo} che imposta la
+ terminazione immediata della connessione in caso di chiusura.}
+ \label{fig:TCP_echo_sixth}
+\end{figure}
+
+La sezione indicata viene eseguita dopo aver effettuato la connessione e prima
+di chiamare la funzione di gestione, cioè fra le righe (\texttt{\small 12}) e
+(\texttt{\small 13}) del precedente esempio di fig.~\ref{fig:TCP_echo_fifth}.
+Il codice si limita semplicememente a controllare (\texttt{\small 3}) il
+valore della variabile \var{reset} che assegnata nella gestione delle opzioni
+in corrispondenza all'uso di \texttt{-r} nella chiamata del client. Nel caso
+questa sia diversa da zero vengono impostati (\texttt{\small 5--6}) i valori
+della struttura \var{ling} che permettono una terminazione immediata della
+connessine. Questa viene poi usata nella successiva (\texttt{\small 7})
+chiamata a \func{setsockopt}. Al solito si controlla (\texttt{\small 7--10})
+il valore di ritorno e si termina il programma in caso di errore, stampadone
+il valore.
+
+Infine l'ultima possibilità, quella in cui si utilizza effettivamente
+\const{SO\_LINGER} per \textsl{indugiare} nella chiusura, è quella in cui sia
+\var{l\_onoff} che \var{l\_linger} hanno un valore diverso da zero. Se si
+esegue l'impostazione con questi valori sia \func{close} che \func{shutdown}
+si bloccano, nel frattempo viene eseguita la normale procedura di conclusione
+della connessione (quella di sez.~\ref{sec:TCP_conn_term}) ma entrambe le
+funzioni non ritornano fintanto che non si sia concluso il procedimento di
+chiusura della connessione, o non sia passato un numero di
+secondi\footnote{questa è l'unità di misura indicata da POSIX ed adottata da
+ Linux, altri kernel possono usare unità di misura diverse, oppure usare il
+ campo \var{l\_linger} come valore logico (ignorandone il valore) per rendere
+ (quando diverso da zero) \func{close} e \func{shutdown} bloccanti fino al
+ completamento della trasmissione dei dati sul buffer.} pari al valore
+specificato in \var{l\_linger}.
+
+\index{costante!{SO\_LINGER}@{{\tt {SO\_LINGER}}}|)}
+
+
+
+
+
+\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}. Le costanti indicanti le opzioni e
+tutte le altre costanti ad esse collegate sono definite in
+\file{netinet/ip.h}, ed accessibili includendo detto file.
+
+
+\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$&\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\_OPTIONS}] l'opzione permette di impostare o leggere le
+ opzioni del protocollo IP (si veda sez.~\ref{sec:IP_options}). L'opzione
+ prende come valore dell'argomento \param{optval} un puntatore ad un buffer
+ dove sono mantenute le opzioni, mentre \param{optlen} indica la dimensione
+ di quest'ultimo. Quando la si usa con \func{getsockopt} vengono lette le
+ opzioni IP utilizzate per la spedizione, quando la si usa con
+ \func{setsockopt} vengono impostate le opzioni specificate. L'uso di questa
+ opzione richiede una profonda conoscenza del funzionamento del protocollo,
+ torneremo in parte sull'argomento in sez.~\ref{sec:sock_advanced_xxx}.
+
+
+\item[\const{IP\_PKTINFO}] Quando abilitata l'opzione permette di ricevere
+ insieme ai pacchetti un messaggio ancillare (vedi
+ sez.~\ref{sec:TCP_ancillary_data}) di tipo \const{IP\_PKTINFO} contenente
+ una struttura \struct{pktinfo} (vedi fig.~\ref{fig:sock_pktinfo_struct}) che
+ mantiene una serie di informazioni riguardo i pacchetti in arrivo. In
+ particolare è possibile conoscere l'interfaccia su cui è stato ricevuto un
+ pacchetto (nel campo \var{ipi\_ifindex}), l'indirizzo locale da esso
+ utilizzato (nel campo \var{ipi\_spec\_dst}) e l'indirizzo remoto dello
+ stesso (nel campo \var{ipi\_addr}).
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/pktinfo.h}
+ \end{minipage}
+ \caption{La struttura \structd{pktinfo} usata dall'opzione
+ \const{IP\_PKTINFO} per ricavare informazioni sui pacchetti di un socket
+ di tipo \const{SOCK\_DGRAM}.}
+ \label{fig:sock_pktinfo_struct}
+\end{figure}
+
+
+L'opzione è utilizzabile solo per socket di tipo \const{SOCK\_DGRAM}. Questa è
+una opzione introdotta con i kernel della serie 2.2.x, ed è specifica di
+Linux;\footnote{non dovrebbe pertanto essere utilizzata se si ha a cuore la
+ portabilità.} essa permette di sostituire le opzioni \const{IP\_RECVDSTADDR}
+e \const{IP\_RECVIF} presenti in altri Unix (la relativa informazione è quella
+ottenibile rispettivamente dai campi \var{ipi\_addr} e \var{ipi\_ifindex} di
+\struct{pktinfo}).
+
+
+\item[\const{IP\_RECVTOS}] Quando abilitata l'opzione permette di ricevere
+ insieme ai pacchetti un messaggio ancillare di tipo \const{IP\_TOS}, che
+ contiene un byte con il valore del campo \textit{Type of Service}
+ dell'intestazione IP del pacchetto stesso (vedi sez.~\ref{sec:IP_header}).
+ Prende per \param{optval} un intero usato come valore logico.
+
+\item[\const{IP\_RECVTTL}] Quando abilitata l'opzione permette di ricevere
+ insieme ai pacchetti un messaggio ancillare di tipo \const{IP\_RECVTTL},
+ contenente un byte con il valore del campo \textit{Time to Live}
+ dell'intestazione IP (vedi sez.~\ref{sec:IP_header}). L'opzione richiede
+ per \param{optval} un intero usato come valore logico. L'opzione non è
+ supportata per socket di tipo \const{SOCK\_STREAM}.
+
+\item[\const{IP\_RECVOPTS}] Quando abilitata l'opzione permette di ricevere
+ insieme ai pacchetti un messaggio ancillare di tipo \const{IP\_OPTIONS},
+ contenente le opzioni IP del protocollo (vedi sez.~\ref{sec:IP_options}). Le
+ intestazioni di instradamento e le altre opzioni sono già riempite con i
+ dati locali. L'opzione richiede per \param{optval} un intero usato come
+ valore logico. L'opzione non è supportata per socket di tipo
+ \const{SOCK\_STREAM}.
+
+\item[\const{IP\_RETOPTS}] Identica alla precedente \const{IP\_RECVOPTS}, ma
+ in questo caso restituisce i dati grezzi delle opzioni, senza che siano
+ riempiti i capi di instradamento e le marche temporali. L'opzione richiede
+ per \param{optval} un intero usato come valore logico. L'opzione non è
+ supportata per socket di tipo \const{SOCK\_STREAM}.
+
+
+\item[\const{IP\_TOS}] L'opzione consente di leggere o impostare il campo
+ \textit{Type of Service} dell'intestazione IP (vedi
+ sez.~\ref{sec:IP_header}) che permette di indicare le priorità dei
+ pacchetti. Il campo TOS è di 8 bit e l'opzione richiede per \param{optval}
+ un intero che ne contiene il valore. Sono definite anche alcune costanti che
+ definiscono alcuni valori standardizzati per il \textit{Type of Service},
+ riportate in tab.~\ref{tab:IP_TOS_values}, il valore di default usato da
+ Linux è \const{IPTOS\_LOWDELAY}, ma esso può essere modificato con le
+ funzionalità del cosiddetto \textit{Advanced Routing}. Si ricordi che la
+ priorità dei pacchetti può essere impostata anche in maniera indipendente
+ dal protocollo utilizzando l'opzione \const{SO\_PRIORITY} illustrata in
+ sez.~\ref{sec:sock_generic_options}.
+
+
+\item[\const{IP\_TTL}] L'opzione consente di leggere o impostare il campo
+ \textit{Time to Live} dell'intestazione IP (vedi sez.~\ref{sec:IP_header})
+ per tutti i pacchetti associati al socket. Il campo TTL è di 8 bit e
+ l'opzione richiede che \param{optval} sia un intero, che ne conterrà il
+ valore.
+
+
+\item[\const{IP\_HDRINCL}] Se abilitata l'utente deve fornire lui stesso
+ l'intestazione IP in cima ai propri dati. L'opzione è valida soltanto per
+ socket di tipo \const{SOCK\_RAW}, e quando utilizzata eventuali valori
+ impostati con \const{IP\_OPTIONS}, \const{IP\_TOS} o \const{IP\_TTL} sono
+ ignorati. In ogni caso prima della spedizione alcuni campi
+ dell'instestazione vengono comunque modificati dal kernel, torneremo
+ sull'argomento in sez.~\ref{sec:socket_raw_xxx}
+
+
+\item[\const{IP\_RECVERR}] Questa è una opzione introdotta con i kernel della
+ serie 2.2.x, ed è specifica di Linux. Essa permette di usufruire di un
+ meccanismo affidabile per ottenere un maggior numero di informazioni in caso
+ di errori. Se l'opzione è abilitata tutti gli errori generati su un socket
+ vengono memorizzati su una coda, dalla quale poi possono essere letti con
+ \func{recvmsg} (torneremo su questo in sez.~\ref{sec:TCP_ancillary_data}).
+ L'opzione richiede per \param{optval} un intero usato come valore logico;
+ l'opzione non è applicabile a socket di tipo \const{SOCK\_STREAM}.
+
+\item[\const{IP\_MTU\_DISCOVER}] Questa è una opzione introdotta con i
+ kernel della serie 2.2.x, ed è specifica di Linux. L'opzione
+ permette di scrivere o leggere le impostazioni usate nella
+ determinazione della \textit{Maximum Tranfer Unit} (vedi
+ sez.~\ref{sec:net_lim_dim}) per il socket. Il valore di default è
+ determinato dal parametro \texttt{ip\_no\_pmtu\_disc} di
+ \func{sysctl} per i socket di tipo \const{SOCK\_STREAM}, mentre è
+ diabilitato per tutti gli altri.
+
+\item[\const{IP\_MTU}] Permette di leggere il valore della \textit{Maximum
+ Tranfer Unit} di percorso del socket. L'opzione richiede per
+ \param{optval} un intero che conterrà il valore della MTU in byte. Questa è
+ una opzione introdotta con i kernel della serie 2.2.x, ed è specifica di
+ Linux.
+
+\item[\const{IP\_ROUTER\_ALERT}] Questa è una opzione introdotta con i
+ kernel della serie 2.2.x, ed è specifica di Linux. Prende per
+ \param{optval} un intero usato come valore logico. Se abilitata
+ passa tutti i pacchetti con l'opzione \textit{IP Router Alert} (vedi
+ sez.\ref{sec:IP_options}) che devono essere inoltrati al socket
+ corrente. Può essere usata soltanto per socket di tipo raw.
+
+\item[\const{IP\_MULTICAST\_TTL}] L'opzione permette di impostare o leggere il
+ valore del campo TTL per i pacchetti in uscita associati al socket. È
+ importante che questo valore sia il più basso possibile, ed il default è 1,
+ che significa che i pacchetti non potranno uscire dalla rete locale. Questa
+ opzione consente ai programmi che lo richiedono di superare questo limite.
+ L'opzione richiede per \param{optval} un intero che conterrà il valore del
+ TTL.
+
+\item[\const{IP\_MULTICAST\_LOOP}] L'opzione consente di decidere se i
+ dati che si inviano su un socket usato con il \itindex{multicast}
+ \texttt{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 in locale l'uso di questa opzione permette di disabilitare
+ questo tipo di traffico.
+
+\item[\const{IP\_ADD\_MEMBERSHIP}] L'opzione consente di unirsi ad
+ gruppo di \itindex{multicast} \texttt{multicast}, e può essere usata
+ solo con \func{setsockopt}. L'argomento \param{optval} in questo
+ caso deve essere una struttura di tipo \struct{ip\_mreqn},
+ illustrata in fig.~\ref{fig:ip_mreqn_struct}, che permette di
+ indicare, con il campo \var{imr\_multiaddr} l'indirizzo del gruppo
+ di multicast a cui ci si vuole unire, con il campo
+ \var{imr\_address} l'indirizzo dell'interfaccia locale con cui
+ unirsi al gruppo di multicast e con \var{imr\_ifindex} l'indice
+ dell'interfaccia da utilizzare (un valore nullo indica una
+ interfaccia qualunque).
+
+ Per compatibilità è possibile utilizzare anche un argomento di tipo
+ \struct{ip\_mreq}, una precedente versione di \struct{ip\_mreqn}, che
+ differisce da essa soltanto per l'assenza del campo \var{imr\_ifindex}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/ip_mreqn.h}
+ \end{minipage}
+ \caption{La struttura \structd{ip\_mreqn} utilizzata dalle opzioni dei socket
+ per le operazioni concernenti l'appartenenza ai gruppi di multicast.}
+ \label{fig:ip_mreqn_struct}
+\end{figure}
+
+
+\item[\const{IP\_DROP\_MEMBERSHIP}] Lascia un gruppo di
+ \itindex{multicast} \texttt{multicast}, prende per \param{optval} la
+ stessa struttura \struct{ip\_mreqn} (o \struct{ip\_mreq}) usata
+ anche per \const{IP\_ADD\_MEMBERSHIP}.
+
+\item[\const{IP\_MULTICAST\_IF}] Imposta l'interfaccia locale per
+ i'utilizzo del multicast, ed utilizza come \param{optval} le stesse
+ strutture \struct{ip\_mreqn} o \struct{ip\_mreq} delle due
+ precedenti opzioni.
+
+
+\end{basedescript}
\func{ioctl}.
-\subsection{L'uso di \func{fcntl} per i socket}
-\label{sec:sock_fcntl}
+\subsection{L'uso di \func{ioctl} per i socket}
+\label{sec:sock_ioctl}
-Abbiamo già trattato l'uso di \func{fcntl} in sez.~\ref{sec:file_fcntl}, dove
+Abbiamo già trattato l'uso di \func{ioctl} in sez.~\ref{sec:file_ioctl}, 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.
+specifico quando la si impiega su file descriptor associati a dei socket.
+
+Quanto utilizzata con socket generici i valori utilizzabili per il secondo
+argomento della funzione (\param{request}, che indica il tipo di operazione
+richiesta) sono quelli riportati nel seguente elenco, il terzo argomento della
+funzione (quello usato per inviare o ricevere i dati) dipende dalla richiesta
+effettuata, ed è anch'esso illustrato nell'elenco in corrispondenza alla
+relativa richiesta:
+\begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{SIOCGSTAMP}] restituisce una struttura \struct{timeval} con la
+ marca temporale dell'ultimo pacchetto ricevuto sul socket, questa operazione
+ può essere utilizzata per effettuare delle misurazioni precise del tempo di
+ andata e ritorno\footnote{il cosiddetto \itindex{round~trip~time}
+ \textit{round trip time}.} dei pacchetti sulla rete.
+\item[\const{SIOCSPGRP}] imposta il processo o il \itindex{process~group}
+ \textit{process group} a cui inviare i segnali \const{SIGIO} e
+ \const{SIGURG} quando viene completata una operazione di I/O asincrono o
+ arrivano dei dati urgenti. Il terzo argomento deve essere un puntatore ad una
+ variabile di tipo \type{pid\_t}; un valore positivo indica direttamente il
+ \acr{pid} del processo, mentre un valore negativo indica (col valore
+ assoluto) il \textit{process group}. Senxa privilegi di amministratore o la
+ capability \const{CAP\_KILL} si può impostare solo se stessi o il proprio
+ \textit{process group}.
+
+\item[\const{FIOASYNC}] .
+
+
+\item[\const{SIOCGPGRP}] .
+\end{basedescript}
-\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à
+\subsection{L'uso di \func{fcntl} per i socket}
+\label{sec:sock_fcntl}
+
+
+Come per \func{ioctl} abbiamo trattato l'uso di \func{fcntl} in
+sez.~\ref{sec:file_fcntl}, 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.
+specifico quando la si impiega su file descriptor associati a dei socket.
\subsection{L'uso di \func{sysctl} per le proprietà della rete}
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.
+impostazioni relative alle proprietà dei socket. La differenza nell'uso di
+\func{sysctl} rispetto alle funzioni viste finora è che esse consentono di
+controllare le proprietà di un singolo socket, mentre con \func{sysctl} si
+impostano proprietà (o valori di default) validi a livello dell'intero
+sistema.
+
+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 per effettuare impostazioni; un contenuto tipico di
+questa directory è il seguente:
+\begin{verbatim}
+/proc/sys/net/
+|-- core
+|-- ethernet
+|-- ipv4
+|-- ipv6
+|-- irda
+|-- token-ring
+`-- unix
+\end{verbatim}
+e sono presenti varie centinaia di diversi parametri; nel nostro caso ci
+limiteremo a vedere quelli più significativi.
+
+Nella directory \texttt{/proc/sys/net/core} sono disponibili i parametri
+generici validi per tutti i socket, quelli descritti anche nella rispettiva
+pagina di manuale.\footnote{quella accessibile con \texttt{man 7 socket}.}
+I principali sono:
+
+\begin{basedescript}{\desclabelwidth{3.2cm}\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}, \texttt{message\_burst}] impostano i valori
+ delle impostazioni del \itindex{bucket~filter} \textit{bucket filter}
+ (rispettivamente flusso a regime e dimensione di picchi di emissione) che
+ limita l'ammontare dei messaggi di avvertimento inviati dal kernel a causa
+ di eventi esterni sulla rete.
+% TODO: spiegare il ucket filter e questa opzione
+\item[\texttt{netdev\_max\_backlog}] numero massimo di pacchetti che possono
+ essere contenuti nella coda di ingresso generale.
+\item[\texttt{optmem\_max}] lunghezza massima dei dati ancillari e di
+ controllo (vedi sez.~\ref{sec:TCP_ancillary_data}).
+\end{basedescript}
+
+Nella directory \texttt{/proc/sys/net/ipv4} sono disponibili i parametri per i
+socket IPv4, descritti anche nella rispettiva pagina di
+manuale.\footnote{quella accessibile con \texttt{man 7 ip}.} I principali
+sono:
+\begin{basedescript}{\desclabelwidth{3.2cm}\desclabelstyle{\nextlinelabel}}
+
+\item[\texttt{ip\_default\_ttl}] imposta il valore di default per il campo TTL
+ (vedi sez.~\ref{sec:IP_header}) di tutti i pacchetti uscenti. Il valore può
+ essere modificato per il singolo socket con l'opzione
+ \const{IP\_TTL}. Prende un valore intero.
+
+\item[\texttt{ip\_forward}] abilita l'inoltro dei pacchetti da una interfaccia
+ ad un altra, e può essere impostato anche per la singola
+ interfaccia. Prende un valore logico (0 disabilita, diverso da zero abilita).
+
+\item[\texttt{ip\_dynaddr}] Abilita la riscrittura automatica degli indirizzi
+ associati ad un socket quando una interfaccia cambia indirizzo. Viene usato
+ per le interfacce usate nei collegamenti in dial-up, il cui indirizzo IP
+ viene assegnato dinamicamente dal provider, e può essere modificato. Un
+ valore nullo disabilita la funzionalità, con 1 la si abilita, con 2 la si
+ abilità in modalità \textsl{prolissa}.
+
+\item[\texttt{ip\_autoconfig}] non documentato
+
+\item[\texttt{ip\_local\_port\_range}] imposta l'intervallo dei valori usati
+ per l'assegnazione delle porte effimere, permette cioè di modificare i
+ valori illustrati in fig.~\ref{fig:TCP_port_alloc}; prende due valori
+ numerici, che indicano gli estremi dell'intervallo. Si abbia cura di non
+ definire un intervallo che si sovrappone a quello delle porte usate per il
+ \itindex{masquerading} \textit{masquerading}, il kernel può gestire la
+ sovrapposizione, ma si avrà una perdita di prestazioni. Si imposti sempre un
+ valore iniziale maggiore di 1024 (o meglio ancora di 4096) per evitare
+ conflitti con le porte usate dai servizi noti.
+
+\item[\texttt{ip\_no\_pmtu\_disc}] imposta la discliplina di ricerca della
+ \textit{Path MTU} (vedi sez.~\ref{sec:net_lim_dim} e
+ sez.~\ref{sec:sock_ipv4_options}).
+
+\item[\texttt{ipfrag\_high\_thresh}] limite massimo (espresso in numero di
+ byte) sui pacchetti IP frammentati presenti in coda; quando questo valore
+ viene raggiunta la coda viene ripulita fino al valore
+ \texttt{ipfrag\_low\_thresh}.
+
+\item[\texttt{ipfrag\_low\_thresh}] soglia bassa (specificata in byte) cui
+ viene riportata la coda dei pacchetti IP frammentati quando si raggiunge il
+ valore \texttt{ipfrag\_high\_thresh}.
+
+\item[\texttt{ip\_always\_defrag}] se abilitato (prende un intero come valore
+ logico) tutti i pacchetti IP frammentati saranno riassemblati, anche in caso
+ in successivo immediato inoltro.\footnote{introdotto con il kernel 2.2.13,
+ nelle versioni precedenti questo comportamento poteva essere solo in fase
+ di compilazione del kernel con l'opzione
+ \texttt{CONFIG\_IP\_ALWAYS\_DEFRAG}.}
+
+\item[\texttt{}]
+\end{basedescript}
+
%%% Local Variables: