X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=sockctrl.tex;h=4bc3bc4d90e2ef92526840e4501814b8b0dc208e;hp=594e608642fe5c383f1e9e121dd54749fc3e0837;hb=66e83c068629844f84fe4a0d44b382f756c9ef32;hpb=866f3cf8f2fe10ea9c7b5c4b10faf37fce74b1aa diff --git a/sockctrl.tex b/sockctrl.tex index 594e608..4bc3bc4 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -1,6 +1,6 @@ %% 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", @@ -34,6 +34,7 @@ porte o altre propriet \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 @@ -428,7 +429,7 @@ tab.~\ref{tab:DNS_address_class}.\footnote{esisteva in realt \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 @@ -607,6 +608,7 @@ Restituisce una stringa corrispondente ad un errore di risoluzione. \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}|)} @@ -614,11 +616,12 @@ argomento (che si presume sia dato da \var{h\_errno}). \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)} @@ -678,10 +681,10 @@ Con l'uso di \func{gethostbyname} normalmente si ottengono solo gli indirizzi 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} @@ -714,11 +717,11 @@ suoi risultati. 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 @@ -1146,7 +1149,7 @@ aperto riporta la posizione di lettura alla prima voce del file, in questo 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. @@ -1330,7 +1333,7 @@ bit della maschera. \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 @@ -1462,12 +1465,13 @@ lista illustrata in fig.~\ref{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 \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 @@ -1488,7 +1492,7 @@ senza il quale si esce immediatamente stampando il relativo codice di errore. 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. @@ -1688,17 +1692,14 @@ indicano il nome della macchina a cui collegarsi ed il relativo servizio su 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 @@ -1707,40 +1708,46 @@ chiamata (\texttt{\small 10}) a \func{getaddrinfo}. Di quest'ultima si 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}) @@ -1755,11 +1762,11 @@ dell'indirizzo numerico, e pu \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 è @@ -1768,55 +1775,37 @@ nel file \file{sockbind.c} dei sorgenti allegati alla guida). Come si pu 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. - -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. - -\begin{figure}[!htb] - \footnotesize \centering - \begin{minipage}[c]{15cm} - \includecodesample{listati/sockbind.c} - \end{minipage} - \normalsize - \caption{Il codice della funzione \func{sockbind}.} - \label{fig:sockbind_code} -\end{figure} +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. 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 -riportata in fig.~\ref{fig:TCP_echod_third}. In questo caso il socket su cui -porsi in ascolto viene ottenuto (\texttt{\small 15--18}) da \func{sockbind} -che si cura anche della eventuale risoluzione di un indirizzo specifico sul -quale si voglia far ascoltare il server. +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 @@ -1828,22 +1817,566 @@ quale si voglia far ascoltare il server. \label{fig:TCP_echod_third} \end{figure} +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 +riportata in fig.~\ref{fig:TCP_echod_third}. In questo caso il socket su cui +porsi in ascolto viene ottenuto (\texttt{\small 15--18}) da \func{sockbind} +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:TCP_sock_options} +\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. + + +Dato che le descrizioni di tab.~\ref{tab:sock_opt_socklevel} sono estremamente +sommarie, vale la pena entrare in dettagli maggiori; questo ci consentirà +anche di trattare i vari casi particolari, dato che nonostante queste opzioni +siano indicate al livello generico, alcune di esse han senso solo per alcuni +tipi di socket. L'elenco dettagliato del significato di ciascuna di esse è +allora il seguente: +\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}} +\item[\const{SO\_KEEPALIVE}] una connessione può restare attiva se non viene + effettuato alcun traffico su di essa; 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}. + + +\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 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 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}); se si utilizza una stringa + nulla o un valore nullo per \param{optlen} si rimuove 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 \texttt{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 + \texttt{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; 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. + + 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 risulti libera. 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 diversi a socket + diversi. Vale in questo caso quanto detto in precedenza, l'unica differenza + è che in questo caso le diverse chiamate a \func{bind} sono eseguite + all'interno dello stesso programma. + + +\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 come \param{optval} un intero usato come + valore logico. + +\item[\const{SO\_BROADCAST}] + + +\item[\const{SO\_SNDBUF}] + + +\item[\const{SO\_RCVBUF}] + + +\item[\const{SO\_LINGER}] +\item[\const{SO\_PRIORITY}] + +\item[\const{SO\_ERROR}] + +\end{basedescript} + -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} +\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.