Documentate quasi tutte le opzioni dei socket TCP ed alcune sysctl
[gapil.git] / sockctrl.tex
index 18cada6e51c6bb9b0a4e9faffa384ac59eba370c..f90a45eb5cff9fff18e7f2aef8e1f99e7816b5b9 100644 (file)
@@ -2239,9 +2239,10 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
 
 \item[\const{SO\_SNDBUF}] questa opzione imposta la dimensione 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}).
+  di byte. Il valore di default ed il valore massimo che si possono
+  specificare come argomento per questa opzione sono impostabili
+  rispettivamente tramite gli opportuni valori di \func{sysctl} (vedi
+  sez.~\ref{sec:sock_sysctl}).
 
 \item[\const{SO\_RCVBUF}] questa opzione imposta la dimensione del buffer di
   ingresso del socket. Prende per \param{optval} un intero indicante il numero
@@ -2249,6 +2250,23 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
   come argomento per questa opzione sono impostabili tramiti gli opportuni
   valori di \func{sysctl} (vedi sez.~\ref{sec:sock_sysctl}).
 
+  Si tenga presente che nel caso di socket TCP, per entrambe le opzioni
+  \const{SO\_RCVBUF} e \const{SO\_SNDBUF}, il kernel alloca effettivamente una
+  quantità di memoria doppia rispetto a quanto richiesto con
+  \func{setsockopt}. Questo comporta che una successiva lettura con
+  \func{getsockopt} riporterà un valore diverso da quello impostato con
+  \func{setsockopt}.  Questo avviene perché TCP necessita dello spazio in più
+  per mantenere dati amministrativi e strutture interne, e solo una parte
+  viene usata come buffer per i dati, mentre il valore letto da
+  \func{getsockopt} e quello riportato nei vari parametri di
+  \textit{sysctl}\footnote{cioè \texttt{wmem\_max} e \texttt{rmem\_max} in
+    \texttt{/proc/sys/net/core} e \texttt{tcp\_wmem} e \texttt{tcp\_rmem} in
+    \texttt{/proc/sys/net/ipv4}, vedi sez.~\ref{sec:sock_sysctl}.} indica la
+  memoria effettivamente impiegata.  Si tenga presente inoltre che le
+  modifiche alle dimensioni dei buffer di ingresso e di uscita per poter
+  essere effettive devono essere impostate prima della chiamata alle funzioni
+  \func{listen} o \func{connect}.
+
 \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
@@ -2298,52 +2316,53 @@ approfondimento sul significato delle opzioni generiche pi
 
 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.
+resta attiva anche quando non viene effettuato alcun traffico su di essa; è
+allora possibile, in caso di una interruzione completa della rete, che la
+caduta della connessione non venga rilevata, dato che sulla stessa non passa
+comunque alcun traffico.
 
 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
+connessione è attiva.  L'opzione funziona soltanto con i socket che supportano
 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
+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 precoce 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 con l'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}.
+Qualora ci siano dei problemi di rete si possono invece verificare i due casi
+di terminazione precoce del server già illustrati in
+sez.~\ref{sec:TCP_conn_crash}. Il primo è quello in cui la macchina remota ha
+avuto un crollo del sistema ed è stata riavviata, per cui dopo il riavvio la
+connessione non esiste più.\footnote{si ricordi che un normale riavvio o il
+  crollo dell'applicazione non ha questo effetto, in quanto in tal caso si
+  passa sempre per la chiusura del processo, e questo, come illustrato in
+  sez.~\ref{sec:file_close}, comporta anche la regolare chiusura del socket
+  con l'invio di un segmento FIN all'altro capo della connessione.} 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 ed il socket verrà chiuso riportanto un errore di
+\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.
+  essere opportunamente modificati a livello di sistema (cioè per tutti i
+  socket) con gli opportuni parametri illustrati in sez.~\ref{sec:sock_sysctl}
+  ed a livello di singolo socket con le opzioni \texttt{TCP\_KEEP*} di
+  sez.~\ref{sec:sock_tcp_udp_options}.}  (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
@@ -2351,9 +2370,9 @@ principalmente sui server per evitare di mantenere impegnate le risorse che
 verrebbero 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.
+attesa di dati in ingresso su una connessione che non arriveranno mai o perché
+il client sull'altro capo non è più attivo o perché non è più in grado di
+comunicare con il server via rete.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -3048,11 +3067,11 @@ accessibili includendo detto file.\footnote{in realt
       numero massimo di ritrasmissioni del pacchetto SYN.\\
     \const{TCP\_LINGER2}      &$\bullet$&$\bullet$&         &\texttt{int}&
       tempo di vita in stato \texttt{FIN\_WAIT2}.\\
-    \const{TCP\_DEFER\_ACCEPT}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
+    \const{TCP\_DEFER\_ACCEPT}&$\bullet$&$\bullet$&         &\texttt{int}&
       ritorna da \func{accept} solo in presenza di dati.\\
     \const{TCP\_WINDOW\_CLAMP}&$\bullet$&$\bullet$&         &\texttt{int}&
       valore della \textit{advertised window}.\\
-    \const{TCP\_INFO}         &$\bullet$&?        &       &\struct{tcp\_info}& 
+    \const{TCP\_INFO}         &$\bullet$&        &       &\struct{tcp\_info}& 
       raccoglie informazioni sul socket.\\
     \const{TCP\_QUICKACK}     &$\bullet$&$\bullet$&$\bullet$&\texttt{int}&
       abilita la modalità \textit{quickack}.\\
@@ -3065,10 +3084,11 @@ accessibili includendo detto file.\footnote{in realt
   \label{tab:sock_opt_tcplevel}
 \end{table}
 
-Le descrizioni riportata in tab.~\ref{tab:sock_opt_tcplevel} sono estremamente
-sintetiche, una maggiore quantità di dettagli e la spiegazione delle singole
-opzioni è fornita nel seguente elenco:
-\begin{basedescript}{\desclabelwidth{3.0cm}\desclabelstyle{\nextlinelabel}}
+Le descrizioni delle varie opzioni riportate in
+tab.~\ref{tab:sock_opt_tcplevel} sono estremamente sintetiche, una maggiore
+quantità di dettagli e la spiegazione delle singole opzioni è fornita nel
+seguente elenco:
+\begin{basedescript}{\desclabelwidth{3.3cm}\desclabelstyle{\nextlinelabel}}
 
 \item[\const{TCP\_NODELAY}] il protocollo TCP prevede, per evitare la
   trasmissione di tanti pacchetti piccoli, che comporta un utilizzo non
@@ -3101,26 +3121,85 @@ opzioni 
   punto tutti i dati rimasti in coda saranno inviati in un solo pacchetto.
   Questa opzione viene usata per gestire direttamente il flusso dei dati
   mettendo un ``\textsl{tappo}'' al flusso di uscita, in modo ottimizzare a
-  mano il throughput.
-
-  Questa opzione non è disponibile su tutti i kernel unix-like e deve essere
-  evitata se si vuole avere codice portabile.
-
-\item[\const{TCP\_KEEPINTVL}] 
-
-\item[\const{TCP\_KEEPCNT}] 
-
-\item[\const{TCP\_SYNCNT}] 
-
-\item[\const{TCP\_LINGER2}] 
+  mano il throughput. È molto utile anche quando si effettua il trasferimento
+  di dati da un file con \func{sendfile} (vedi sez.~\ref{sec:file_sendfile}),
+  se si vuole inserire una intestazione prima della chiamata a questa
+  funzione. 
+
+  Si tenga presente che l'implementazione corrente di \const{TCP\_CORK} non
+  consente di bloccare l'invio dei pacchetti per più di 200 millisecondi,
+  passati i quali i dati accumulati in cosa sanno inviati comunque.  Questa
+  opzione non è disponibile su tutti i kernel unix-like e deve essere evitata
+  se si vuole scrivere codice portabile.
+
+\item[\const{TCP\_KEEPIDLE}] imposta l'intervallo di tempo, in secondi, che
+  deve trascorrere senza traffico sul socket prima che vengano inviati,
+  qualora si sia attivata su di esso l'opzione \const{SO\_KEEPALIVE}, i
+  messaggi di \textit{keep-alive} (si veda la trattazione relativa al
+  \textit{keep-alive} in sez.~\ref{sec:sock_options_main}).  Anche questa
+  opzione non è disponibile su tutti i kernel unix-like e deve essere evitata
+  se si vuole scrivere codice portabile.
+
+\item[\const{TCP\_KEEPINTVL}] imposta l'intervallo di tempo, in secondi, fra
+  due messaggi di \textit{keep-alive} successivi (si veda sempre quanto
+  illustrato in sez.~\ref{sec:sock_options_main}). Come la precedente non è
+  disponibile su tutti i kernel unix-like e deve essere evitata se si vuole
+  scrivere codice portabile.
+
+\item[\const{TCP\_KEEPCNT}] imposta il numero totale di messaggi di
+  \textit{keep-alive} da inviare prima di concludere che la connessione è
+  caduta (di nuovo vedi sez.~\ref{sec:sock_options_main}). Come la precedente
+  non è disponibile su tutti i kernel unix-like e deve essere evitata se si
+  vuole scrivere codice portabile.
+
+\item[\const{TCP\_SYNCNT}] imposta il numero di tentativi di ritrasmissione
+  dei segmenti SYN usati nel \itindex{three~way~handshake}\textit{three way
+    handshake} prima che il tentativo di connessione venga abortito (si
+  ricordi quanto accennato in sez.\ref{sec:TCP_func_connect}). Sovrascrive il
+  valore globale impostato con la \textit{sysctl} \texttt{tcp\_syn\_retries}
+  (vedi sez.~\ref{sec:sock_ipv4_sysctl}).  Non vengono accettati valori
+  maggiori di 255; anche questa opzione non è standard e deve essere evitata
+  se si vuole scrivere codice portabile.
+
+\item[\const{TCP\_LINGER2}] imposta, in numero di secondi, il tempo di
+  sussistenza dei socket terminati nello stato \texttt{FIN\_WAIT2} (si ricordi
+  quanto visto in sez.~\ref{sec:TCP_conn_term}).\footnote{si tenga ben
+    presente che questa opzione non ha nulla a che fare con la
+    \const{SO\_LINGER} che abbiamo visto in sez.~\ref{sec:sock_options_main}.}
+  Questa opzione consente di sovrascrivere il valore globale impostato con la
+  \textit{sysctl} \texttt{tcp\_fin\_timeout} (vedi
+  sez.~\ref{sec:sock_ipv4_sysctl}).  Anche questa opzione è da evitare se si
+  ha a cuore la portabilità del codice.
+
+\item[\const{TCP\_DEFER\_ACCEPT}] consente ad un socket in ascolto di
+  ritornare da \func{accept} soltanto quando sono presenti dati sullo stesso,
+  e non alla conclusione del \itindex{three~way~handshake} \textit{three way
+    handshake}. Prende un valore intero che indica il numero massimo di
+  secondi per cui il ritorno di \func{accept} viene rimandato; non deve essere
+  utilizzata in codice che vuole essere portabile.
+
+\item[\const{TCP\_WINDOW\_CLAMP}] limita alla dimensione specificata (in byte)
+  il valore dichiarato della \itindex{advertised~window} \textit{advertised
+    window} (vedi sez.\ref{sez:tcp_protocol_xxx}). Il kernel impone comunque
+  una dimensione minima pari a \texttt{SOCK\_MIN\_RCVBUF/2}. Questa opzione
+  non deve essere utilizzata in codice che vuole essere portabile.
+
+\item[\const{TCP\_INFO}] permette di ricevere una serie di informazioni
+  relative al socket che il kernel restituisce in una speciale struttura
+  \struct{tcp\_info}, la cui definizione è riportata in
+  fig.~\ref{fig:tcp_info_struct}.
 
-\item[\const{TCP\_DEFER\_ACCEPT}] 
-
-\item[\const{TCP\_WINDOW\_CLAMP}] 
-
-\item[\const{TCP\_INFO}] 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/tcp_info.h}
+  \end{minipage}
+  \caption{La struttura \structd{tcp\_info} contenente le informazioni sul
+    socket restituita dall'opzione \const{TCP\_INFO}.}
+  \label{fig:tcp_info_struct}
+\end{figure}
 
-\item[\const{TCP\_QUICKACK}] 
+\item[\const{TCP\_QUICKACK}] abilita la modalità speciale \textit{quickack}.
 
 \item[\const{TCP\_CONGESTION}] Introdotta con il kernel 2.6.13.
 
@@ -3505,14 +3584,13 @@ sistema sotto \texttt{/proc/net}, dove sono presenti dei file che non
 corrispondono a nessun nodo di \func{sysctl}.
 
 
-
 \subsection{I valori di controllo per i socket generici}
 \label{sec:sock_gen_sysctl}
 
 Nella directory \texttt{/proc/sys/net/core} sono presenti i file
-corrispondenti ai parametri generici validi per tutti i socket. Quelli
-descritti anche nella pagina di manuale, accessibile con \texttt{man 7 socket}
-sono i seguenti:
+corrispondenti ai parametri generici di \textit{sysctl} validi per tutti i
+socket.  Quelli descritti anche nella pagina di manuale, accessibile con
+\texttt{man 7 socket} sono i seguenti:
 
 \begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}}
 \item[\texttt{rmem\_default}] imposta la dimensione di default del buffer di
@@ -3605,7 +3683,7 @@ dello stesso (come ARP).
 I file che consentono di controllare le caratteristiche specifiche del
 protocollo IP in quanto tale, descritti anche nella pagina di manuale
 accessibile con \texttt{man 7 ip}, sono i seguenti:
-\begin{basedescript}{\desclabelwidth{3.2cm}\desclabelstyle{\nextlinelabel}}
+\begin{basedescript}{\desclabelwidth{3.5cm}\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ò
@@ -3666,9 +3744,89 @@ accessibile con \texttt{man 7 ip}, sono i seguenti:
 
 % \item[\texttt{neigh/*}] La directory contiene i valori 
 % TODO trattare neigh/* nella parte su arp, da capire dove sarà.
-
 \end{basedescript}
 
+I file di \texttt{/proc/sys/net/ipv4} che invece fanno riferimento alle
+caratteristiche specifiche del protocollo TCP, elencati anche nella rispettiva
+pagina di manuale (accessibile con \texttt{man 7 tcp}), sono i seguenti:
+\begin{basedescript}{\desclabelwidth{3.9cm}\desclabelstyle{\nextlinelabel}}
+\item[\texttt{tcp\_abort\_on\_overflow}] 
+\item[\texttt{tcp\_adv\_win\_scale}] 
+\item[\texttt{tcp\_app\_win}] 
+\item[\texttt{tcp\_bic\_low\_window}] 
+\item[\texttt{tcp\_bic\_fast\_convergence}] 
+\item[\texttt{tcp\_dsack}] 
+\item[\texttt{tcp\_ecn}] 
+\item[\texttt{tcp\_fack}] 
+
+\item[\texttt{tcp\_fin\_timeout}] specifica il numero di secondi (il default è
+  60\footnote{nei kernel della serie 2.2.x era invece di 120 secondi.}) da
+  passare in stato \texttt{FIN\_WAIT2} nell'attesa delle ricezione del
+  pacchetto FIN conclusivo, passati quali il socket viene comunque chiuso
+  forzatamente.  L'uso di questa opzione realizza quella che in sostanza è una
+  violazione delle specifiche del protocollo TCP, ma è utile per fronteggiare
+  alcuni attacchi di \itindex{Denial~of~Service~(DoS)} \textit{Denial of
+    Service}.
+
+
+\item[\texttt{tcp\_frto}] 
+\item[\texttt{tcp\_keepalive\_intvl}] 
+\item[\texttt{tcp\_keepalive\_probes}] 
+\item[\texttt{tcp\_keepalive\_time}] 
+\item[\texttt{tcp\_low\_latency}] 
+\item[\texttt{tcp\_max\_orphans}] 
+
+\item[\texttt{tcp\_max\_syn\_backlog}] un numero intero che indica la
+  lunghezza della coda delle connessioni incomplete, cioè delle connessioni
+  per le quali si è ricevuto un SYN di richiesta ma non l'ACK finale del
+  \itindex{three~way~handshake} \textit{three way handshake} (si riveda quanto
+  illustrato in sez.\ref{sec:TCP_func_listen}).
+
+  Quando questo valore è superato il kernel scarterà immediatamente ogni
+  ulteriore richiesta di connessione. Il valore di default (che è 256) viene
+  automaticamente portato a 1024 qualora nel sistema ci sia sufficiente
+  memoria (se maggiore di 128Mb) e ridotto a 128 qualora la memoria sia poca
+  (inferiore a 32Mb).\footnote{si raccomanda, qualora si voglia aumentare il
+    valore oltre 1024, di seguire la procedura citata nella pagina di manuale
+    di TCP , e modificare il valore della costante \texttt{TCP\_SYNQ\_HSIZE}
+    nel file \texttt{include/net/tcp.h} dei sorgenti del kernel, in modo che
+    sia $\mathtt{tcp\_max\_syn\_backlog} \ge \mathtt{16*TCP\_SYNQ\_HSIZE}$, e
+    poi ricompilare il kernel.}
+
+\item[\texttt{tcp\_max\_tw\_buckets}] 
+\item[\texttt{tcp\_mem}] 
+\item[\texttt{tcp\_orphan\_retries}] 
+\item[\texttt{tcp\_reordering}] 
+\item[\texttt{tcp\_retrans\_collapse}] 
+\item[\texttt{tcp\_retries1}] 
+
+\item[\texttt{tcp\_retries2}] imposta il numero di tentativi di ritrasmissione
+  (il default è 15) di un pacchetto inviato su una connessione già stabilita
+  per il quale non si sia ricevuto una risposta di ACK (si veda anche quanto
+  illustrato in sez.~\ref{sec:TCP_server_crash}).
+
+
+\item[\texttt{tcp\_rfc1337}] 
+\item[\texttt{tcp\_rmem}]
+\item[\texttt{tcp\_sack}] 
+\item[\texttt{tcp\_stdurg}] 
+\item[\texttt{tcp\_synack\_retries}] 
+\item[\texttt{tcp\_syncookies}] 
+
+\item[\texttt{tcp\_syn\_retries}] imposta il numero di tentativi (il default è
+  5) di ritrasmissione dei pacchetti SYN di inizio connessione del
+  \itindex{three~way~handshake} \textit{three way handshake} (si ricordi
+  quanto illustrato in sez.\ref{sec:TCP_func_connect}). Il valore non deve
+  superare 255. 
+
+\item[\texttt{tcp\_timestamps}] 
+\item[\texttt{tcp\_tw\_recycle}] 
+\item[\texttt{tcp\_tw\_reuse}] 
+\item[\texttt{tcp\_window\_scaling}] 
+\item[\texttt{tcp\_vegas\_cong\_avoid}] 
+\item[\texttt{tcp\_westwood}] 
+\item[\texttt{tcp\_wmem}] 
+\end{basedescript}