X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;ds=sidebyside;f=elemtcp.tex;h=ca1a94b3562ba63454d58d278a53beda70dc3ede;hb=ae0f5a752ec86bf15b78031f4b33664a8c0b515b;hp=5e5a69cd3c782f2cda80f1e40a864c79352e8d58;hpb=dfa5facee2cc3dd4d66f2397911526770df7cb22;p=gapil.git diff --git a/elemtcp.tex b/elemtcp.tex index 5e5a69c..ca1a94b 100644 --- a/elemtcp.tex +++ b/elemtcp.tex @@ -634,10 +634,10 @@ cio server per specificare la porta (e gli eventuali indirizzi locali) su cui poi ci si porrà in ascolto. -Il prototipo della funzione, definito in \texttt{sys/socket.h}, è il seguente: +Il prototipo della funzione è il seguente: -\begin{prototype}{int bind(int sockfd, const struct sockaddr *serv\_addr, - socklen\_t addrlen) } +\begin{prototype}{sys/socket.h} +{int bind(int sockfd, const struct sockaddr *serv\_addr, socklen\_t addrlen)} Il primo argomento è un file descriptor ottenuto da una precedente chiamata a \texttt{socket}, mentre il secondo e terzo argomento sono rispettivamente @@ -713,11 +713,10 @@ di effettuare una assegnazione del tipo: \label{sec:TCPel_func_connect} La funzione \texttt{connect} è usata da un client TCP per stabilire la -connessione con un server TCP, il prototipo della funzione, definito in -\texttt{sys/socket.h}, è il seguente: +connessione con un server TCP, il prototipo della funzione è il seguente: -\begin{prototype}{int connect(int sockfd, const struct sockaddr *serv\_addr, - socklen\_t addrlen) } +\begin{prototype}{sys/socket.h} +{int connect(int sockfd, const struct sockaddr *serv\_addr, socklen\_t addrlen)} Il primo argomento è un file descriptor ottenuto da una precedente chiamata a \texttt{socket}, mentre il secondo e terzo argomento sono rispettivamente @@ -819,9 +818,20 @@ necessario effettuare una \texttt{bind}. La funzione \texttt{listen} è usata per usare un socket in modalità passiva, cioè, come dice il nome, per metterlo in ascolto di eventuali connessioni; in sostanza l'effetto della funzione è di portare il socket dallo stato -\texttt{CLOSED} a quello \texttt{LISTEN}. +\texttt{CLOSED} a quello \texttt{LISTEN}. In genere si chiama la funzione in +un server dopo le chiamate a \texttt{socket} e \texttt{bind} e prima della +chiamata ad \texttt{accept}. Il prototipo della funzione come definito dalla +man page è: -\begin{prototype}{int listen(int sockfd, int backlog)} +\begin{prototype}{sys/socket.h}{int listen(int sockfd, int backlog)} + + La funzione pone il socket specificato da \texttt{sockfd} in modalità + passiva e predispone una coda per le connessioni in arrivo pari a + \texttt{backlog}. La funzione si può applicare solo a socket di tipo + \texttt{SOCK\_STREAM} o \texttt{SOCK\_SEQPACKET}. + + La funzione restituisce 0 in caso di successo e -1 in caso di errore. I + codici di errore restituiti in \texttt{errno} sono i seguenti: \begin{errlist} \item \texttt{EBADF} L'argomento \texttt{sockfd} non è un file descriptor valido. @@ -832,6 +842,66 @@ sostanza l'effetto della funzione \end{prototype} +Il parametro \texttt{backlog} indica il numero massimo di connessioni pendenti +accettate; se esso viene ecceduto il client riceverà una errore di tipo +\texttt{ECONNREFUSED}, o se il protocollo, come nel caso del TCP, supporta la +ritrasmissione, la richiesta sarà ignorata in modo che la connessione possa +essere ritentata. + +Per capire meglio il significato di tutto ciò occorre approfondire la modalità +con cui il kernel tratta le connessioni in arrivo. Per ogni socket in ascolto +infatti vengono mantenute due code: +\begin{enumerate} +\item Una coda delle connessioni incomplete (\textit{incomplete connection + queue} che contiene una entrata per ciascun SYN arrivato per il quale si + sta attendendo la conclusione del three-way handshake. Questi socket sono + tutti nello stato \texttt{SYN\_RECV}. +\item Una coda delle connessioni complete (\textit{complete connection queue} + che contiene una entrata per ciascuna connessione per le quali il three-way + handshake è stato completato ma ancora \texttt{accept} non è ritornata. +\end{enumerate} + +Lo schema di funzionamento è descritto in \nfig, quando arriva un SYN da un +client il server crea una nuova entrata nella coda delle connessioni +incomplete, e poi risponde con il SYN$+$ACK. La entrata resterà nella coda +delle connessioni incomplete fino al ricevimento dell'ACK dal client o fino ad +un timeout. Nel caso di completamento del three-way handshake l'entrata viene +sostata nella coda delle connessioni complete. Quando il processo chiama la +funzione \texttt{accept} (vedi \secref{sec:TCPel_func_accept}) la prima +entrata nella coda delle connessioni complete è passata al programma, o, se la +coda è vuota, il processo viene posto in attesa e risvegliato all'arrivo della +prima connessione completa. + +Storicamente il valore del parametro \texttt{backlog} era corrispondente al +massimo valore della somma del numero di entrate possibili per ciascuna di +dette code. Stevens riporta che BSD ha sempre applicato un fattore di 1.5 al +valore, e provvede una tabella con i risultati ottenuti con vari kernel, +compreso linux 2.0, che mostrano le differenze fra diverse implementazioni. + +Ma in linux il significato di questo valore è cambiato a partire dal kernel +2.2 per prevenire l'attacco chiamato \texttt{syn flood}. Questo si basa +sull'emissione da parte dell'attaccante di un grande numero di pacchetti SYN +indirizzati verso una porta forgiati con indirizzo IP fasullo \footnote{con la + tecnica che viene detta \textit{ip spoofing}} così che i SYN$+$ACK vanno +perduti la coda delle connessioni incomplete viene saturata, impedendo di +fatto le connessioni. + +Per ovviare a questo il significato del \texttt{backlog} è stato cambiato a +significare la lunghezza della coda delle connessioni complete. La lunghezza +della coda delle connessioni incomplete può essere ancora controllata usando +la \texttt{sysctl} o scrivendola direttamente in +\texttt{/proc/sys/net/ipv4/tcp\_max\_syn\_backlog}. Quando si attiva la +protezione dei syncookies però (con l'opzione da compilare nel kernel e da +attivare usando \texttt{/proc/sys/net/ipv4/tcp\_syncookies}) questo valore +viene ignorato e non esiste più un valore massimo. + +La scelta storica per il valore di questo parametro è di 5, e alcuni vecchi +kernel non supportavano neanche valori superiori, ma la situazione corrente è +molto cambiata dagli anni '80 e con server web che possono sopportare diversi +milioni di connessioni al giorno un tale valore non è più adeguato. Non esiste +comunque una risposta univoca + + \subsection{La funzione \texttt{accept}} \label{sec:TCPel_func_accept}