From 3ad06e8129067dccfa3fad74e7cf6c051231d150 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 24 Apr 2005 17:07:24 +0000 Subject: [PATCH] Aggiunti alcuni riferimenti, documentate le costanti IPPORT_RESERVED e IPPORT_USERRESERVED, finita la trattazione di SO_REUSEADDR e iniziata quella di SO_LINGER, inserita una nuova sezione sulle opzioni dei socket piu' significative, aggiunta quanche informazione sulle opzioni di IPv4. --- listati/hand_sigchild.c | 3 - listati/linger.h | 5 + prochand.tex | 10 +- session.tex | 14 +- signal.tex | 6 - sockctrl.tex | 443 ++++++++++++++++++++++++++-------------- tcpsock.tex | 41 ++-- 7 files changed, 333 insertions(+), 189 deletions(-) create mode 100644 listati/linger.h diff --git a/listati/hand_sigchild.c b/listati/hand_sigchild.c index f55168f..aa8d4d4 100644 --- a/listati/hand_sigchild.c +++ b/listati/hand_sigchild.c @@ -9,9 +9,6 @@ void HandSigCHLD(int sig) do { errno = 0; pid = waitpid(WAIT_ANY, &status, WNOHANG); - if (pid > 0) { - debug("child %d terminated with status %x\n", pid, status); - } } while (pid > 0); /* restore errno value */ errno = errno_save; diff --git a/listati/linger.h b/listati/linger.h new file mode 100644 index 0000000..fe9e9df --- /dev/null +++ b/listati/linger.h @@ -0,0 +1,5 @@ +struct linger +{ + int l_onoff; /* Nonzero to linger on close. */ + int l_linger; /* Time to linger (in seconds). */ +} diff --git a/prochand.tex b/prochand.tex index 9be38cc..6bdbb5a 100644 --- a/prochand.tex +++ b/prochand.tex @@ -681,7 +681,7 @@ eseguite alla chiusura di un processo sez.~\ref{sec:sig_sigchld}); \item se il processo è un leader di sessione ed il suo terminale di controllo è quello della sessione viene mandato un segnale di \const{SIGHUP} a tutti i - processi del gruppo di foreground e il terminale di controllo viene + processi del gruppo di \textit{foreground} e il terminale di controllo viene disconnesso (vedi sez.~\ref{sec:sess_ctrl_term}); \item se la conclusione di un processo rende orfano un \textit{process group} ciascun membro del gruppo viene bloccato, e poi gli vengono @@ -771,10 +771,10 @@ informazione, non pi completamente conclusa. Possiamo utilizzare il nostro programma di prova per analizzare anche questa -condizione: lanciamo il comando \cmd{forktest} in background, indicando al -processo padre di aspettare 10 secondi prima di uscire; in questo caso, usando -\cmd{ps} sullo stesso terminale (prima dello scadere dei 10 secondi) -otterremo: +condizione: lanciamo il comando \cmd{forktest} in \textit{background} (vedi +sez.~\ref{sec:sess_job_control}), indicando al processo padre di aspettare 10 +secondi prima di uscire; in questo caso, usando \cmd{ps} sullo stesso +terminale (prima dello scadere dei 10 secondi) otterremo: \footnotesize \begin{verbatim} diff --git a/session.tex b/session.tex index c042e91..ae8322e 100644 --- a/session.tex +++ b/session.tex @@ -60,11 +60,11 @@ sez.~\ref{sec:sess_login}). Siccome la shell è collegata ad un solo terminale, che viene usualmente chiamato \textsl{terminale di controllo}, (vedi sez.~\ref{sec:sess_ctrl_term}) -un solo comando alla volta (quello che viene detto in \textit{foreground}), -potrà scrivere e leggere dal terminale. La shell però può eseguire anche più -comandi in contemporanea, mandandoli in \textit{background} (aggiungendo una -\cmd{\&} alla fine del comando), nel qual caso essi saranno eseguiti senza -essere collegati al terminale. +un solo comando alla volta (quello che viene detto in \textit{foreground} o in +\textsl{primo piano}), potrà scrivere e leggere dal terminale. La shell però +può eseguire, aggiungendo una \cmd{\&} alla fine del comando, più programmi in +contemporanea, mandandoli in \textit{background} (o \textsl{sullo sfondo}), +nel qual caso essi saranno eseguiti senza essere collegati al terminale. Si noti come si sia parlato di comandi e non di programmi o processi; fra le funzionalità della shell infatti c'è anche quella di consentire di concatenare @@ -291,8 +291,8 @@ dal quale ricevono gli eventuali segnali da tastiera. A tale scopo lo standard POSIX.1 prevede che ad ogni sessione possa essere associato un terminale di controllo; in Linux questo viene realizzato -mantenendo fra gli attributi di ciascun processo anche qual è il suo terminale -di controllo. \footnote{Lo standard POSIX.1 non specifica nulla riguardo +mantenendo fra gli attributi di ciascun processo anche qual'è il suo terminale +di controllo.\footnote{Lo standard POSIX.1 non specifica nulla riguardo l'implementazione; in Linux anch'esso viene mantenuto nella solita struttura \struct{task\_struct}, nel campo \var{tty}.} In generale ogni processo eredita dal padre, insieme al \acr{pgid} e al \acr{sid} anche il terminale di diff --git a/signal.tex b/signal.tex index 2e24f36..df3727c 100644 --- a/signal.tex +++ b/signal.tex @@ -1397,12 +1397,6 @@ di sez.~\ref{sec:proc_termination}, invocando \cmd{forktest} con l'opzione gestore di \const{SIGCHLD}) potremo verificare che non si ha più la creazione di zombie\index{zombie}. -% è pertanto -% naturale usare un esempio che ci permette di concludere la trattazione della -% terminazione dei processi. -% In questo caso si è tratterà di illustrare un esempio relativo ad un -% gestore per che è previsto ritornare, - \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} diff --git a/sockctrl.tex b/sockctrl.tex index 1d7df38..7e8a5b6 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -2066,66 +2066,27 @@ 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: +Questo ci consentirà anche +di trattare approfonditamente alcune opzioni che, nonostante siano +classificate fra quelle generiche, hanno un significato effettivo solo per +alcuni tipi di socket.TCP/IP. L'elenco dettagliato del significato delle +opzioni generiche dei socket è allora il seguente: + + +Le descrizioni delle opzioni presenti in tab.~\ref{tab:sock_opt_socklevel} +sono estremamente sommarie, è perciò necessario fornire un po' più di +informazioni; alcune opzioni comunque hanno una notevole rilevanza nella +gestione dei socket, e pertanto il loro utilizzo sarà approfondito +separatamente in sez.~\ref{sec:sock_options_main}. Quello che segue pertanto è +soltanto un elenco più dettagliato di quanto scritto in +tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni: \begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}} -\item[\const{SO\_KEEPALIVE}] 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\_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 @@ -2205,9 +2166,10 @@ allora il seguente: 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\_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 @@ -2217,11 +2179,10 @@ allora il seguente: \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}); se si utilizza una stringa - nulla o un valore nullo per \param{optlen} si rimuove un precedente - collegamento. + 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 è @@ -2229,7 +2190,6 @@ allora il seguente: 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 @@ -2250,70 +2210,14 @@ allora il seguente: 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 + \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. - - Come Stevens sottolinea in \cite{UNP1} si distinguono quattro casi per - l'utilizzo di questa opzione; il primo è quello in cui un server è terminato - ma esistono ancora dei processi figli che mantengono attiva almeno una - connessione remota che utilizza l'indirizzo locale. Quando si riavvia il - server questo viene bloccato sulla chiamata a \func{bind} dato che la porta - è ancora utilizzata in una connessione esistente.\footnote{questa è una - delle domande più frequenti sui newsgroup dedicati allo sviluppo, in - quanto è piuttosto comune in questa situazione quando si sta sviluppando - un server che si ferma e si riavvia in continuazione.} Inoltre se si usa - il protocollo TCP questo può avvenire anche dopo che l'ultimo processo - figlio è terminato, dato che la connessione può restare attiva anche dopo la - chiusura del socket mantenendosi nello stato \texttt{TIME\_WAIT}. - - Usando \const{SO\_REUSEADDR} fra la chiamata a \func{socket} e quella a - \func{bind} si consente a quest'ultima di avere comunque successo anche se - la connessione è attiva (o nello stato \texttt{TIME\_WAIT}). È bene però - ricordare (si riveda quanto detto in sez.~\ref{sec:TCP_time_wait}) che la - presenza dello stato \texttt{TIME\_WAIT} ha una ragione, ed infatti se si - usa questa opzione esiste sempre una probabilità, anche se estremamente - remota,\footnote{perché ciò avvenga infatti non solo devono coincidere gli - indirizzi IP e le porte degli estremi della nuova connessione, ma anche i - numeri di sequenza dei pacchetti, e questo è estremamente improbabile.} - che eventuali pacchetti rimasti intrappolati in una precedente connessione - possano finire fra quelli di una nuova. - - Il secondo caso in cui viene usata questa opzione è quando si ha una - macchina cui sono assegnati diversi numeri IP (o come suol dirsi - \textit{multi-homed}) e si vuole porre in ascolto sulla stessa porta un - programma diverso (o una istanza diversa dello stesso programma) per - indirizzi IP diversi. Si ricordi infatti che è sempre possibile indicare a - \func{bind} di collegarsi solo su di un indirizzo specifico; in tal caso se - un altro programma cerca di riutilizzare la stessa porta (anche specificando - un indirizzo diverso) otterrà un errore a meno di non aver preventivamente - impostato \const{SO\_REUSEADDR}. Usando questa opzione diventa anche - possibile eseguire \func{bind} sull'indirizzo generico, e questo permetterà - il collegamento per tutti gli indirizzi (di quelli presenti) per i quali la - porta non risulti occupata da una precedente chiamata più specifica. Infine - si tenga presente che con il protocollo TCP non è mai possibile far partire - server che eseguano \func{bind} sullo stesso indirizzo e la stessa porta, - cioè ottenere quello che viene chiamato un \textit{completely duplicate - binding}. - - Il terzo impiego è simile al precedente e prevede l'uso di \func{bind} - all'interno dello stesso programma per associare indirizzi locali diversi a - socket diversi. In genere questo viene fatto per i socket UDP quando è - necessario ottenere l'indirizzo a cui sono rivolte le richieste del client - ed il sistema non supporta l'opzione \const{IP\_RECVDSTADDR};\footnote{nel - caso di Linux questa opzione è stata supportata per in certo periodo nello - sviluppo del kernel 2.1.x, ma è in seguito stata soppiantata dall'uso di - \const{IP\_PKTINFO} (vedi sez.~\ref{sec:sock_ipv4_options}).} in tale modo - si può sapere a quale socket corrisponde un certo indirizzo. Non ha senso - per socket TCP dato che su di essi si può sempre invocare \func{getsockname} - una volta che si è completata la connessione. - - Infine il quarto caso è quello in si vuole effettivamente ottenere un - \textit{completely duplicate binding} + 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 @@ -2353,7 +2257,14 @@ allora il seguente: valori di \func{sysctl} (vedi sez.~\ref{sec:sock_sysctl}). -\item[\const{SO\_LINGER}] +\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} @@ -2374,6 +2285,214 @@ allora il seguente: \end{basedescript} +\subsection{Le uso delle principali opzioni dei socket} +\label{sec:sock_options_main} + +L'elenco sintetico delle caratteristiche delle opzioni dei socket riportato in +sez.~\ref{sec:sock_generic_options} non è sufficientemente dettagliato per +permetterci di approfondire il significato di alcune di esse, che assumono +grande importanza nella programmazione dei socket. Per questo motivo +tratteremo ulteriormente l'uso di alcune di esse in questa sezione. + +\index{\texttt{SO\_KEEPALIVE} (costante)|(} +La prima opzione da approfondire è \const{SO\_KEEPALIVE}, che come accennato +permette di controllare automaticamente lo stato di una connessione. Una +connessione infatti può restare attiva anche se non viene effettuato alcun +traffico su di essa, ma in certi casi però può essere utile controllarne lo +stato per accorgersi di eventuali problemi. + +Per questo, se si imposta questa opzione, è cura del kernel inviare degli +appositi messaggi sulla rete (detti appunto \textit{keep-alive}) per +verificare se la connessione è attiva. L'opzione funziona soltanto con socket +che supportino le connessioni (non ha senso per socket UDP ad esempio), ed +utilizza per \param{optval} un intero usato come valore logico. + +L'opzione si applica principalmente ai socket TCP. Con le impostazioni di +default (che sono riprese da BSD) Linux emette un messaggio di +\textit{keep-alive} verso l'altro capo della connessione se questa è rimasta +senza traffico per più di due ore. Se è tutto a posto il messaggio viene +ricevuto e verrà emesso un segmento ACK di risposta, alla cui ricezione +ripartirà un'altro ciclo di attesa per altre due ore di inattività; tutto ciò +viene effettuato dal kernel e le applicazioni non riceveranno nessun dato. + +In caso di problemi invece si possono avere i due casi già illustrati in +sez.~\ref{sec:TCP_conn_crash} per il caso di terminazione prococe del server: +il primo è quello in cui la macchina remota è caduta ed è stata riavviata, per +cui dopo il riavvio la connessione non viene più riconosciuta,\footnote{si + ricordi che un normale riavvio non ha questo effetto, in quanto si passa per + la chiusura del processo, che chiude anche il socket inviando un segmento + FIN all'altro capo della connessione.} e si otterrà come risposta un RST. In +tal caso il socket viene chiuso dopo aver impostato un errore +\errcode{ECONNRESET}. + +Se invece non viene ricevuta nessuna risposta (indice che la macchina non è +più raggiungibile) l'emissione dei messaggi viene ripetuta ad intervalli di 75 +secondi ad un massimo di 9 volte\footnote{entrambi questi valori possono + essere opportunamente modificati con gli opportuni parametri illustrati in + sez.~\ref{sec:sock_sysctl}, si tenga presente che però questo vale a livello + di kernel ed i valori saranno applicati a \textsl{tutti} i socket.} (per un +totale di 11 minuti e 15 secondi) dopo di che, se non si è ricevuta nessuna +risposta, il socket viene chiuso dopo aver impostato un errore di +\errcode{ETIMEDOUT}. Se invece si riceve in risposta ad uno di questi messaggi +un pacchetto ICMP di destinazione irraggiungibile, verrà restituito l'errore +corrispondente. + +In generale questa opzione serve per individuare una caduta della +connessione,\footnote{il crash di un processo di nuovo comporta la chiusura di + tutti i file che aveva aperti e la relativa emissione degli opportuni + segmenti FIN nel caso dei socket.} e viene usata sui server per evitare di +mantenere impegnate le risorse dedicate a trattare delle connessioni in realtà +terminate. Abilitandola le connessioni effettivamente terminate vengono +chiuse ed una \func{select} potrà rilevare la conclusione delle stesse e +ricevere il relativo errore. Si tenga però presente che non si ha la certezza +assoluta che un errore di \errcode{ETIMEDOUT} corrisponda ad una reale +conclusione della connessione, il problema potrebbe essere dovuto ad un +problema di routing che perduri per un tempo maggiore di quello impiegato nei +vari tentativi di ritrasmissione del \textit{keep-alive}. +\index{\texttt{SO\_KEEPALIVE} (costante)|)} + + +\index{\texttt{SO\_REUSEADDR} (costante)|(} +La seconda opzione da approfondire è \const{SO\_REUSEADDR}. Come Stevens +sottolinea in \cite{UNP1} si distinguono quattro casi per l'utilizzo di questa +opzione; il primo è quello in cui un server è terminato ma esistono ancora dei +processi figli che mantengono attiva almeno una connessione remota che +utilizza l'indirizzo locale. Quando si riavvia il server questo viene bloccato +sulla chiamata a \func{bind} dato che la porta è ancora utilizzata in una +connessione esistente.\footnote{questa è una delle domande più frequenti sui + newsgroup dedicati allo sviluppo, in quanto è piuttosto comune in questa + situazione quando si sta sviluppando un server che si ferma e si riavvia in + continuazione.} Inoltre se si usa il protocollo TCP questo può avvenire +anche dopo che l'ultimo processo figlio è terminato, dato che la connessione +può restare attiva anche dopo la chiusura del socket mantenendosi nello stato +\texttt{TIME\_WAIT}. + +Usando \const{SO\_REUSEADDR} fra la chiamata a \func{socket} e quella a +\func{bind} si consente a quest'ultima di avere comunque successo anche se la +connessione è attiva (o nello stato \texttt{TIME\_WAIT}). È bene però +ricordare (si riveda quanto detto in sez.~\ref{sec:TCP_time_wait}) che la +presenza dello stato \texttt{TIME\_WAIT} ha una ragione, ed infatti se si usa +questa opzione esiste sempre una probabilità, anche se estremamente +remota,\footnote{perché ciò avvenga infatti non solo devono coincidere gli + indirizzi IP e le porte degli estremi della nuova connessione, ma anche i + numeri di sequenza dei pacchetti, e questo è estremamente improbabile.} che +eventuali pacchetti rimasti intrappolati in una precedente connessione possano +finire fra quelli di una nuova. + +Il secondo caso in cui viene usata questa opzione è quando si ha una macchina +cui sono assegnati diversi numeri IP (o come suol dirsi \textit{multi-homed}) +e si vuole porre in ascolto sulla stessa porta un programma diverso (o una +istanza diversa dello stesso programma) per indirizzi IP diversi. Si ricordi +infatti che è sempre possibile indicare a \func{bind} di collegarsi solo su di +un indirizzo specifico; in tal caso se un altro programma cerca di +riutilizzare la stessa porta (anche specificando un indirizzo diverso) otterrà +un errore a meno di non aver preventivamente impostato \const{SO\_REUSEADDR}. +Usando questa opzione diventa anche possibile eseguire \func{bind} +sull'indirizzo generico, e questo permetterà il collegamento per tutti gli +indirizzi (di quelli presenti) per i quali la porta non risulti occupata da +una precedente chiamata più specifica. Infine si tenga presente che con il +protocollo TCP non è mai possibile far partire server che eseguano \func{bind} +sullo stesso indirizzo e la stessa porta, cioè ottenere quello che viene +chiamato un \textit{completely duplicate binding}. + +Il terzo impiego è simile al precedente e prevede l'uso di \func{bind} +all'interno dello stesso programma per associare indirizzi locali diversi a +socket diversi. In genere questo viene fatto per i socket UDP quando è +necessario ottenere l'indirizzo a cui sono rivolte le richieste del client ed +il sistema non supporta l'opzione \const{IP\_RECVDSTADDR};\footnote{nel caso + di Linux questa opzione è stata supportata per in certo periodo nello + sviluppo del kernel 2.1.x, ma è in seguito stata soppiantata dall'uso di + \const{IP\_PKTINFO} (vedi sez.~\ref{sec:sock_ipv4_options}).} in tale modo +si può sapere a quale socket corrisponde un certo indirizzo. Non ha senso per +socket TCP dato che su di essi si può sempre invocare \func{getsockname} una +volta che si è completata la connessione. + +Infine il quarto caso è quello in si vuole effettivamente ottenere un +\textit{completely duplicate binding}, quando cioè si vuole eseguire +\func{bind} su un indirizzo ed una porta che sono già \textsl{legati} ad un +altro socket. Questo ovviamente non ha senso per il normale traffico di rete, +in cui i pacchetti vengono scambiati direttamente fra due applicazioni; ma +quando un sistema supporta il traffico in multicast, in cui una applicazione +invia i pacchetti a molte altre (vedi sez.~\ref{sec:multicast_xxx}), allora ha +senso che su una macchina i pacchetti provenienti dal traffico in multicast +possano essere ricevuti da più applicazioni\footnote{l'esempio classico di + traffico in multicast è quello di uno streaming di dati (audio, video, + ecc.), l'uso del multicast consente in tal caso di trasmettere un solo + pacchetto, che potrà essere ricevuto da tutti i possibili destinatari + (invece di inviarne un duplicato a ciascuno); in questo caso è perfettamente + logico aspettarsi che sulla stessa macchina più utenti possano lanciare un + programma che permetta loro di ricevere gli stessi dati.} o da diverse +istanze della stessa applicazione. + +In questo caso utilizzando \const{SO\_REUSEADDR} si consente ad una +applicazione eseguire \func{bind} sulla stessa porta ed indirizzo usata da +un'altra, così che anche essa possa ricevere gli stessi pacchetti (chiaramente +la cosa non ha alcun senso per i socket TCP, ed infatti in questo tipo di +applicazione è normale l'uso del protovollo UDP). La regola è che quando si +hanno più applicazioni che hanno eseguito \func{bind} sulla stessa porta, di +tutti pacchetti destinati ad un indirizzo di broadcast o di multicast viene +inviata una copia a ciascuna applicazione. Non è definito invece cosa accade +qualora il pacchetto sia destinato ad un indirizzo normale (unicast). + +Essendo questo un caso particolare in alcuni sistemi (come BSD) è stata +introdotta una opzione ulteriore, \const{SO\_REUSEPORT} che richiede che detta +opzione sia specificata per tutti i socket per i quali si vuole eseguire il +\textit{completely duplicate binding}. Nel caso di Linux questa opzione non +esiste, ma il comportamento di \const{SO\_REUSEADDR} è analogo, sarà cioè +possibile effettuare un \textit{completely duplicate binding} ed ottenere il +successo di \func{bind} su un socket legato allo stesso indirizzo e porta solo +se il primo programma che ha eseguito \func{bind} su di essi ha impostato +questa opzione.\footnote{Questa restrizione permette di evitare il cosiddetto + \textit{port stealing}, in cui un programma, usando \const{SO\_REUSEADDR}, + può collegarsi ad una porta già in uso e ricevere i pacchetti destinati ad + un altro programma; con questa caratteristica ciò è possibile soltanto se il + primo programma a consentirlo, avendo usato fin dall'inizio + \const{SO\_REUSEADDR}.} +\index{\texttt{SO\_REUSEADDR} (costante)|)} + + +\index{\texttt{SO\_LINGER} (costante)|(} La terza opzione da approfondire è +\const{SO\_LINGER}; essa, come il nome suggerisce, consente di +\textsl{indugiare} nella chiusura di un socket. Il comportamento standard sia +di \func{close} che \func{shutdown} è quello di terminare immediatamente dopo +la chiamata, mentre il procedimento di chiusura della connessione e l'invio +sulla rete di tutti i dati ancora presenti nei buffer viene gestito in +sottofondo dal kernel. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \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} permette di modificare (ed eventualmente +ripristinare) questo comportamento in base ai valori passati nei campi della +stuttura \struct{linger}. Fintanto che il valore del campo \var{l\_onoff} di +\struct{linger} è nullo la modalità che viene impostata (qualunque sia il +valore di \var{l\_linger}) è quella standard appena illustrata. + +Se però si utilizza un valore di \var{l\_onoff} diverso da zero per +l'impostazione di \const{SO\_LINGER} il comportamento dipende dal valore di +\var{l\_linger}; se quest'ultimo è nullo l'uso delle funzioni \func{close} e +\func{shutdown} provoca la terminazione immediata della connessione: nel caso +di TCP cioè non viene eseguito il procedimento di chiusura illustrato in +sez.~\ref{sec:TCP_conn_term}, ma viene inviato un segmento di RST che termina +immediatamente la connessione. Se invece \var{l\_linger} ha un valore diverso +da zero sia \func{close} che \func{shutdown} si bloccano e non ritornano +fintanto che non si sia concluso il procedimento di chiusura della +connessione, o non siano passati il numero di secondi specificati da +\var{l\_linger}. +\index{\texttt{SO\_LINGER} (costante)|)} + + + + + \subsection{Le opzioni per il protocollo IPv4} \label{sec:sock_ipv4_options} @@ -2396,41 +2515,45 @@ opzioni in tab.~\ref{tab:sock_opt_iplevel}. \hline \hline \const{IP\_OPTIONS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Imposta o riceve le opzioni di IP.\\ \const{IP\_PKTINFO}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Passa un messaggio di informazione.\\ \const{IP\_RECVTOS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Passa un messaggio col campo TOS.\\ \const{IP\_RECVTTL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Passa un messaggio col campo TTL.\\ \const{IP\_RECVOPTS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Passa un messaggio con le opzioni IP.\\ \const{IP\_RETOPTS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Passa un messaggio con le opzioni IP non + trattate.\\ \const{IP\_TOS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Imposta il valore del campo TOS.\\ \const{IP\_TTL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Imposta il valore del campo TTL.\\ \const{IP\_HDRINCL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Passa l'intestazione di IP nei dati.\\ \const{IP\_RECVERR}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Abilita la gestione degli errori.\\ \const{IP\_MTU\_DISCOVER}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Imposta il Path MTU Discovery.\\ \const{IP\_MTU}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Legge il valore attuale della MTU.\\ \const{IP\_ROUTER\_ALERT}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Imposta l'opzione \textit{IP router alert} sui + pacchetti.\\ \const{IP\_MULTICAST\_TTL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ + Imposta il TTL per i pacchetti multicast.\\ \const{IP\_MULTICAST\_LOOP}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ - \const{IP\_ADD\_MEMBERSHIP}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& - .\\ - \const{IP\_DROP\_MEMBERSHIP}&$\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}.} @@ -2438,6 +2561,24 @@ opzioni in tab.~\ref{tab:sock_opt_iplevel}. \end{table} +Le descrizioni di tab.~\ref{tab:sock_opt_iplevel} sono estremamente succinte, +una maggiore quantità di dettagli su queste opzioni è fornito nel seguente +elenco: +\begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}} +\item[\const{IP\_MULTICAST\_LOOP}] L'opzione consente di decidere se i dati + che si inviano su un socket usato con il multicast vengano ricevuti anche + sulla stessa macchina da cui li si stanno inviando. Prende per + \param{optval} un intero usato come valore logico. + + In generale se si vuole che eventuali client possano ricevere i dati che si + inviano occorre che questa funzionalità sia abilitata (come avviene di + default). Qualora però non si voglia generare traffico per dati che già sono + disponibili l'uso di questa opzione permette di disabilitare questo tipo di + traffico. + +\end{basedescript} + + diff --git a/tcpsock.tex b/tcpsock.tex index 90dbaf7..03fb502 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -461,17 +461,17 @@ dall'\href{http://www.ietf.org/rfc/rfc1700.txt}{RFC~1700} che contiene l'elenco delle porte assegnate dalla IANA (la \textit{Internet Assigned Number Authority}) ma l'elenco viene costantemente aggiornato e pubblicato su internet (una versione aggiornata si può trovare all'indirizzo -\texttt{ftp://ftp.isi.edu/in-notes/iana/assignements/port-numbers}); inoltre +\href{ftp://ftp.isi.edu/in-notes/iana/assignements/port-number} +{\texttt{ftp://ftp.isi.edu/in-notes/iana/assignements/port-numbers}}); inoltre in un sistema unix-like un analogo elenco viene mantenuto nel file \file{/etc/services}, con la corrispondenza fra i vari numeri di porta ed il nome simbolico del servizio. I numeri sono divisi in tre intervalli: -\begin{enumerate} -\item \textsl{le porte conosciute}. I numeri da 0 a 1023. Queste sono - controllate e assegnate dalla IANA. Se è possibile la stessa porta è - assegnata allo stesso servizio sia su UDP che su TCP (ad esempio la porta 22 - è assegnata a SSH su entrambi i protocolli, anche se viene usata solo dal - TCP). +\begin{enumerate*} +\item \textsl{le porte note}. I numeri da 0 a 1023. Queste sono controllate e + assegnate dalla IANA. Se è possibile la stessa porta è assegnata allo stesso + servizio sia su UDP che su TCP (ad esempio la porta 22 è assegnata a SSH su + entrambi i protocolli, anche se viene usata solo dal TCP). \item \textsl{le porte registrate}. I numeri da 1024 a 49151. Queste porte non sono controllate dalla IANA, che però registra ed elenca chi usa queste @@ -483,29 +483,36 @@ nome simbolico del servizio. I numeri sono divisi in tre intervalli: \item \textsl{le porte private} o \textsl{dinamiche}. I numeri da 49152 a 65535. La IANA non dice nulla riguardo a queste porte che pertanto sono i candidati naturali ad essere usate come porte effimere. -\end{enumerate} +\end{enumerate*} In realtà rispetto a quanto indicato nell'\href{http://www.ietf.org/rfc/rfc1700.txt}{RFC~1700} i vari sistemi hanno fatto scelte diverse per le porte effimere, in particolare in -fig.~\ref{fig:TCP_port_alloc} sono riportate quelle di BSD e Linux. Nel caso -di Linux poi la scelta fra i due intervalli possibili viene fatta -dinamicamente a seconda della memoria a disposizione del kernel per gestire le -relative tabelle. +fig.~\ref{fig:TCP_port_alloc} sono riportate quelle di BSD e Linux. \begin{figure}[!htb] \centering - \includegraphics[width=15cm]{img/port_alloc} + \includegraphics[width=13cm]{img/port_alloc} \caption{Allocazione dei numeri di porta.} \label{fig:TCP_port_alloc} \end{figure} I sistemi Unix hanno inoltre il concetto di \textsl{porte riservate} (che corrispondono alle porte con numero minore di 1024 e coincidono quindi con le -porte conosciute). La loro caratteristica è che possono essere assegnate a un -socket solo da un processo con i privilegi di amministratore, per far si che -solo l'amministratore possa allocare queste porte per far partire i relativi -servizi. +\textsl{porte note}). La loro caratteristica è che possono essere assegnate a +un socket solo da un processo con i privilegi di amministratore, per far sì +che solo l'amministratore possa allocare queste porte per far partire i +relativi servizi. + +Le \textsl{glibc} definiscono (in \texttt{netinet/in.h}) +\const{IPPORT\_RESERVED} e \const{IPPORT\_USERRESERVED}, in cui la prima (che +vale 1024) indica il limite superiore delle porte riservate, e la seconda (che +vale 5000) il limite inferiore delle porte a disposizione degli utenti. La +convenzione vorrebbe che le porte \textsl{effimere} siano allocate fra questi +due valori. Nel caso di Linux questo è vero solo in uno dei due casi di +fig.~\ref{fig:TCP_port_alloc}, e la scelta fra i due possibili intervalli +viene fatta dinamicamente dal kernel a seconda della memoria disponibile per +la gestione delle relative tabelle. Si tenga conto poi che ci sono alcuni client, in particolare \cmd{rsh} e \cmd{rlogin}, che richiedono una connessione su una porta riservata anche dal -- 2.30.2