X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=elemtcp.tex;h=67157706e24aefc1b3dbaa54fcf4f44caf5918fe;hp=effafc390a905613132ba6fac9bc933a45a56072;hb=3498a6fc0fd13e07cacdea210cb99126d5052fbc;hpb=e20a546af590a50e7ac47f68f6c7d4648bb4f31a diff --git a/elemtcp.tex b/elemtcp.tex index effafc3..6715770 100644 --- a/elemtcp.tex +++ b/elemtcp.tex @@ -44,7 +44,7 @@ creazione di una connessione \func{connect}, attraverso un procedimento che viene chiamato \textsl{apertura attiva}, dall'inglese \textit{active open}. La chiamata di \func{connect} blocca il processo e causa l'invio da parte del client di un - segmento SYN\footnote{Si ricordi che il segmento è l'unità elementare di + segmento SYN,\footnote{Si ricordi che il segmento è l'unità elementare di dati trasmessa dal protocollo TCP al livello superiore; tutti i segmenti hanno un header che contiene le informazioni che servono allo \textit{stack TCP} (così viene di solito chiamata la parte del kernel che @@ -52,7 +52,7 @@ creazione di una connessione ci sono una serie di flag usati per gestire la connessione, come SYN, ACK, URG, FIN, alcuni di essi, come SYN (che sta per \textit{syncronize}) corrispondono a funzioni particolari del protocollo e danno il nome al - segmento, (per maggiori dettagli vedere \capref{cha:tcp_protocol})}, in + segmento, (per maggiori dettagli vedere \capref{cha:tcp_protocol}).} in sostanza viene inviato al server un pacchetto IP che contiene solo gli header IP e TCP (con il numero di sequenza iniziale e il flag SYN) e le opzioni di TCP. @@ -60,8 +60,8 @@ creazione di una connessione \item il server deve dare ricevuto (l'\textit{acknowledge}) del SYN del client, inoltre anche il server deve inviare il suo SYN al client (e trasmettere il suo numero di sequenza iniziale) questo viene fatto - ritrasmettendo un singolo segmento in cui entrambi i flag SYN ACK e sono - settati. + ritrasmettendo un singolo segmento in cui sono impostati entrambi i flag SYN + ACK. \item una volta che il client ha ricevuto l'acknowledge dal server la funzione \func{connect} ritorna, l'ultimo passo è dare dare il ricevuto del SYN del @@ -70,9 +70,9 @@ creazione di una connessione \end{enumerate} Il procedimento viene chiamato \textit{three way handshake} dato che per -realizzarlo devono essere scambiati tre segmenti. In \nfig\ si è -rappresentata graficamente la sequenza di scambio dei segmenti che stabilisce -la connessione. +realizzarlo devono essere scambiati tre segmenti. In \figref{fig:TCPel_TWH} +si è rappresentata graficamente la sequenza di scambio dei segmenti che +stabilisce la connessione. % Una analogia citata da R. Stevens per la connessione TCP è quella con il % sistema del telefono. La funzione \texttt{socket} può essere considerata @@ -91,22 +91,22 @@ la connessione. \end{figure} Si è accennato in precedenza ai \textsl{numeri di sequenza} (che sono anche -riportati in \curfig); per gestire una connessione affidabile infatti il -protocollo TCP prevede nell'header la presenza di un numero a 32 bit (chiamato -appunto \textit{sequence number}) che identifica a quale byte nella sequenza -del flusso corrisponde il primo byte della sezione dati contenuta nel -segmento. +riportati in \figref{fig:TCPel_TWH}); per gestire una connessione affidabile +infatti il protocollo TCP prevede nell'header la presenza di un numero a 32 +bit (chiamato appunto \textit{sequence number}) che identifica a quale byte +nella sequenza del flusso corrisponde il primo byte della sezione dati +contenuta nel segmento. Il numero di sequenza di ciascun segmento viene calcolato a partire da un \textsl{numero di sequenza iniziale} generato in maniera casuale del kernel all'inizio della connessione e trasmesso con il SYN; l'acknowledgement di -ciascun segmento viene effettuato dall'altro capo della connessione settando +ciascun segmento viene effettuato dall'altro capo della connessione impostando il flag ACK e restituendo nell'apposito campo dell'header un \textit{acknowledge number}) pari al numero di sequenza che il ricevente si aspetta di ricevere con il pacchetto successivo; dato che il primo pacchetto SYN consuma un byte, nel \textit{three way handshake} il numero di acknowledge è sempre pari al numero di sequenza iniziale incrementato di uno; lo stesso -varrà anche (vedi \nfig) per l'acknowledgement di un FIN. +varrà anche (vedi \figref{fig:TCPel_close}) per l'acknowledgement di un FIN. \subsection{Le opzioni TCP.} \label{sec:TCPel_TCP_opt} @@ -128,20 +128,20 @@ regolare la connessione. Normalmente vengono usate le seguenti opzioni: \textsl{finestra annunciata} (\textit{advertized window}) con la quale ciascun capo della comunicazione dichiara quanto spazio disponibile ha in memoria per i dati. Questo è un numero a 16 bit dell'header, che così può - indicare un massimo di 65535 byte (anche se Linux usa come massimo 32767 - per evitare problemi con alcuni stack bacati che usano l'aritmetica con - segno per implementare lo stack TCP); ma alcuni tipi di connessione come - quelle ad alta velocità (sopra i 45Mbits/sec) e quelle che hanno grandi - ritardi nel cammino dei pacchetti (come i satelliti) richiedono una finestra - più grande per poter ottenere il massimo dalla trasmissione, per questo - esiste questa opzione che indica un fattore di scala da applicare al valore - della finestra annunciata\footnote{essendo una nuova opzione per garantire - la compatibilità con delle vecchie implementazioni del protocollo la - procedura che la attiva prevede come negoziazione che l'altro capo della - connessione riconosca esplicitamente l'opzione inserendola anche lui nel - suo SYN di risposta dell'apertura della connessione} per la connessione - corrente (espresso come numero di bit cui shiftare a sinistra il valore - della finestra annunciata inserito nel pacchetto). + indicare un massimo di 65535 byte (anche se Linux usa come massimo 32767 per + evitare problemi con alcuni stack bacati che usano l'aritmetica con segno + per implementare lo stack TCP); ma alcuni tipi di connessione come quelle ad + alta velocità (sopra i 45Mbits/sec) e quelle che hanno grandi ritardi nel + cammino dei pacchetti (come i satelliti) richiedono una finestra più grande + per poter ottenere il massimo dalla trasmissione, per questo esiste questa + opzione che indica un fattore di scala da applicare al valore della finestra + annunciata\footnote{essendo una nuova opzione per garantire la compatibilità + con delle vecchie implementazioni del protocollo la procedura che la + attiva prevede come negoziazione che l'altro capo della connessione + riconosca esplicitamente l'opzione inserendola anche lui nel suo SYN di + risposta dell'apertura della connessione.} per la connessione corrente + (espresso come numero di bit cui shiftare a sinistra il valore della + finestra annunciata inserito nel pacchetto). \item \textit{timestamp option}, è anche questa una nuova opzione necessaria per le connessioni ad alta velocità per evitare possibili corruzioni di dati @@ -192,8 +192,8 @@ normalmente i segmenti scambiati sono quattro. Questo non giacché in alcune situazioni il FIN del passo 1) è inviato insieme a dei dati. Inoltre è possibile che i segmenti inviati nei passi 2 e 3 dal capo che effettua la chiusura passiva, siano accorpati in un singolo segmento. In -\nfig\ si è rappresentato graficamente lo sequenza di scambio dei segmenti che -stabilisce la connessione. +\figref{fig:TCPel_close} si è rappresentato graficamente lo sequenza di +scambio dei segmenti che stabilisce la connessione. \begin{figure}[htb] \centering @@ -234,10 +234,11 @@ quali Le operazioni del TCP nella creazione e conclusione di una connessione sono specificate attraverso il diagramma di transizione degli stati riportato in -\nfig. TCP prevede l'esistenza di 11 diversi stati per un socket ed un insieme -di regole per le transizioni da uno stato all'altro basate sullo stato -corrente e sul tipo di segmento ricevuto; i nomi degli stati sono gli stessi -che vengono riportati del comando \cmd{netstat} nel campo \textit{State}. +\figref{fig:TPCel_conn_example}. TCP prevede l'esistenza di 11 diversi stati +per un socket ed un insieme di regole per le transizioni da uno stato +all'altro basate sullo stato corrente e sul tipo di segmento ricevuto; i nomi +degli stati sono gli stessi che vengono riportati del comando \cmd{netstat} +nel campo \textit{State}. Una descrizione completa del funzionamento del protocollo va al di là degli obiettivi di questo libro; un approfondimento sugli aspetti principali si @@ -263,9 +264,9 @@ attiva) la transizione l'applicazione riceve un FIN nello stato \texttt{ESTABLISHED} (chiusura passiva) la transizione è verso lo stato \texttt{CLOSE\_WAIT}. -In \nfig\ è riportato lo schema dello scambio dei pacchetti che avviene per -una un esempio di connessione, insieme ai vari stati che il protocollo viene -ad assumere per i due lati, server e client. +In \figref{fig:TPCel_conn_example} è riportato lo schema dello scambio dei +pacchetti che avviene per una un esempio di connessione, insieme ai vari stati +che il protocollo viene ad assumere per i due lati, server e client. \begin{figure}[htb] \centering @@ -312,18 +313,18 @@ dati rispondono meglio alle esigenze che devono essere affrontate. \subsection{Lo stato \texttt{TIME\_WAIT}} \label{sec:TCPel_time_wait} -Come riportato da Stevens (FIXME citare) lo stato \texttt{TIME\_WAIT} è +Come riportato da Stevens in \cite{UNP1} lo stato \texttt{TIME\_WAIT} è probabilmente uno degli aspetti meno compresi del protocollo TCP, è infatti comune trovare nei newsgroup domande su come sia possibile evitare che un'applicazione resti in questo stato lasciando attiva una connessione ormai conclusa; la risposta è che non deve essere fatto, ed il motivo cercheremo di spiegarlo adesso. -Come si è visto nell'esempio precedente (vedi \curfig) \texttt{TIME\_WAIT} è -lo stato finale in cui il capo di una connessione che esegue la chiusura -attiva resta prima di passare alla chiusura definitiva della connessione. Il -tempo in cui l'applicazione resta in questo stato deve essere due volte la MSL -(\textit{Maximum Segment Lifetime}). +Come si è visto nell'esempio precedente (vedi \figref{fig:TPCel_conn_example}) +\texttt{TIME\_WAIT} è lo stato finale in cui il capo di una connessione che +esegue la chiusura attiva resta prima di passare alla chiusura definitiva +della connessione. Il tempo in cui l'applicazione resta in questo stato deve +essere due volte la MSL (\textit{Maximum Segment Lifetime}). La MSL è la stima del massimo periodo di tempo che un pacchetto IP può vivere sulla rete; questo tempo è limitato perché ogni pacchetto IP può essere @@ -354,13 +355,14 @@ riferimento solo alla prima; ma capisce il perché della scelta di un tempo pari al doppio della MSL come durata di questo stato. -Il primo dei due motivi precedenti si può capire tornando a \curfig: assumendo -che l'ultimo ACK della sequenza (quello del capo che ha eseguito la chiusura -attiva) vanga perso, chi esegue la chiusura passiva non ricevendo risposta -rimanderà un ulteriore FIN, per questo motivo chi esegue la chiusura attiva -deve mantenere lo stato della connessione per essere in grado di reinviare -l'ACK e chiuderla correttamente. Se non fosse così la risposta sarebbe un RST -(un altro tipo si segmento) che verrebbe interpretato come un errore. +Il primo dei due motivi precedenti si può capire tornando a +\figref{fig:TPCel_conn_example}: assumendo che l'ultimo ACK della sequenza +(quello del capo che ha eseguito la chiusura attiva) vanga perso, chi esegue +la chiusura passiva non ricevendo risposta rimanderà un ulteriore FIN, per +questo motivo chi esegue la chiusura attiva deve mantenere lo stato della +connessione per essere in grado di reinviare l'ACK e chiuderla correttamente. +Se non fosse così la risposta sarebbe un RST (un altro tipo si segmento) che +verrebbe interpretato come un errore. Se il TCP deve poter chiudere in maniera pulita entrambe le direzioni della connessione allora deve essere in grado di affrontare la perdita di uno @@ -469,10 +471,11 @@ in tre intervalli: \end{enumerate} In realtà rispetto a quanto indicato nell'RFC~1700 i vari sistemi hanno fatto -scelte diverse per le porte effimere, in particolare in \nfig\ sono riportate -quelle di BSD, Solaris 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. +scelte diverse per le porte effimere, in particolare in +\figref{fig:TCPel_port_alloc} sono riportate quelle di BSD, Solaris 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. \begin{figure}[!htb] \centering @@ -606,12 +609,12 @@ l'uso dei socket TCP gi della funzione \func{socket} che è già stata esaminata in dettaglio in \secref{sec:sock_socket}. -In \nfig\ abbiamo un tipico schema di funzionamento di un'applicazione -client-server che usa i socket TCP: prima il server viene avviato ed in -seguito il client si connette, in questo caso, a differenza di quanto accadeva -con gli esempi elementari del \capref{cha:network} si assume che sia il -client ad effettuare delle richieste a cui il server risponde, il client -notifica poi di avere concluso inviando un end-of-file a cui il server +In \figref{fig:TCPel_cliserv_func} abbiamo un tipico schema di funzionamento +di un'applicazione client-server che usa i socket TCP: prima il server viene +avviato ed in seguito il client si connette, in questo caso, a differenza di +quanto accadeva con gli esempi elementari del \capref{cha:network} si assume +che sia il client ad effettuare delle richieste a cui il server risponde, il +client notifica poi di avere concluso inviando un end-of-file a cui il server risponderà anche lui chiudendo la connessione per aspettarne una nuova. \begin{figure}[!htb] @@ -640,17 +643,17 @@ ci si porr a \func{socket}, mentre il secondo e terzo argomento sono rispettivamente l'indirizzo (locale) del socket e la dimensione della struttura che lo contiene, secondo quanto già trattato in \secref{sec:sock_sockaddr}. - - La funzione restituisce zero in caso di successo e -1 per un errore; in caso - di errore la variabile \var{errno} viene settata secondo i seguenti - codici di errore: + + \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + errore; in caso di errore la variabile \var{errno} viene impostata secondo + i seguenti codici di errore: \begin{errlist} - \item \macro{EBADF} il file descriptor non è valido. - \item \macro{EINVAL} il socket ha già un indirizzo assegnato. - \item \macro{ENOTSOCK} il file descriptor non è associato ad un socket. - \item \macro{EACCESS} si è cercato di usare una porta riservata senza + \item[\macro{EBADF}] il file descriptor non è valido. + \item[\macro{EINVAL}] il socket ha già un indirizzo assegnato. + \item[\macro{ENOTSOCK}] il file descriptor non è associato ad un socket. + \item[\macro{EACCESS}] si è cercato di usare una porta riservata senza sufficienti privilegi. - \end{errlist} + \end{errlist}} \end{prototype} Con il TCP la chiamata \func{bind} permette di specificare l'indirizzo, la @@ -662,7 +665,7 @@ per il server\footnote{un'eccezione a tutto ci In questo caso viene fatta assegnare dal kernel una porta effimera che poi viene registrata presso il \textit{portmapper}; quest'ultimo è un altro demone che deve essere contattato dai client per ottenere la porta effimera - su cui si trova il server} che in genere viene identificato dalla porta su + su cui si trova il server.} che in genere viene identificato dalla porta su cui risponde. Con \func{bind} si può assegnare un IP specifico ad un socket, purché questo @@ -686,7 +689,7 @@ un'assegnazione immediata del tipo: \footnotesize \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} - serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ + serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ \end{lstlisting} \normalsize @@ -703,12 +706,13 @@ consente l'uso di una struttura costante come operando a destra in una assegnazione. Per questo nell'header \file{netinet/in.h} è definita una variabile -\type{in6addr\_any} (dichiarata come \type{extern}, ed inizializzata dal +\type{in6addr\_any} (dichiarata come \ctyp{extern}, ed inizializzata dal sistema al valore \macro{IN6ADRR\_ANY\_INIT}) che permette di effettuare una assegnazione del tipo: + \footnotesize \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} - serv_add.sin6_addr = in6addr_any; /* connect from anywhere */ + serv_add.sin6_addr = in6addr_any; /* connect from anywhere */ \end{lstlisting} \normalsize @@ -725,30 +729,30 @@ connessione con un server TCP, il prototipo della funzione a \func{socket}, mentre il secondo e terzo argomento sono rispettivamente l'indirizzo e la dimensione della struttura che contiene l'indirizzo del socket, già descritta in \secref{sec:sock_sockaddr}. - - La funzione restituisce zero in caso di successo e -1 per un errore, in caso - di errore la variabile \var{errno} viene settata secondo i seguenti - codici di errore: + + \bodydesc{La funzione restituisce zero in caso di successo e -1 per un + errore, in caso di errore la variabile \var{errno} viene impostata secondo + i seguenti codici di errore: \begin{errlist} - \item \macro{EISCONN} il socket è già connesso. - \item \macro{ECONNREFUSED} non c'è nessuno in ascolto sull'indirizzo remoto. - \item \macro{ETIMEDOUT} si è avuto timeout durante il tentativo di + \item[\macro{ECONNREFUSED}] non c'è nessuno in ascolto sull'indirizzo remoto. + \item[\macro{ETIMEDOUT}] si è avuto timeout durante il tentativo di connessione. - \item \macro{ENETUNREACH} la rete non è raggiungibile. - \item \macro{EADDRINUSE} l'indirizzo locale è in uso. - \item \macro{EINPROGRESS} il socket è non bloccante e la connessione non - può essere conclusa immediatamente. - \item \macro{EALREADY} il socket è non bloccante e un tentativo precedente - di connessione non si è ancora concluso. - \item \macro{EAGAIN} non ci sono più porte locali libere. - \item \macro{EAFNOSUPPORT} l'indirizzo non ha una famiglia di indirizzi + \item[\macro{ENETUNREACH}] la rete non è raggiungibile. + \item[\macro{EINPROGRESS}] il socket è non bloccante (vedi + \secref{sec:file_noblocking}) e la connessione non può essere conclusa + immediatamente. + \item[\macro{EALREADY}] il socket è non bloccante (vedi + \secref{sec:file_noblocking}) e un tentativo precedente di connessione non + si è ancora concluso. + \item[\macro{EAGAIN}] non ci sono più porte locali libere. + \item[\macro{EAFNOSUPPORT}] l'indirizzo non ha una famiglia di indirizzi corretta nel relativo campo. - \item \macro{EACCESS, EPERM} si è tentato di eseguire una connessione ad un + \item[\macro{EACCESS, EPERM}] si è tentato di eseguire una connessione ad un indirizzo broadcast senza che il socket fosse stato abilitato per il broadcast. \end{errlist} altri errori possibili sono: \macro{EFAULT}, \macro{EBADF}, - \macro{ENOTSOCK}. + \macro{ENOTSOCK}, \macro{EISCONN} e \macro{EADDRINUSE}.} \end{prototype} La struttura dell'indirizzo deve essere inizializzata con l'indirizzo IP e il @@ -770,11 +774,11 @@ seguenti: invece ripete l'emissione del SYN ad intervalli di 30 secondi per un numero di volte che può essere stabilito dall'utente sia con una opportuna \func{sysctl} che attraverso il filesystem \file{/proc} scrivendo il valore - voluto in \file{/proc/sys/net/ipv4/tcp\_syn\_retries}. Il valore di default + voluto in \file{/proc/sys/net/ipv4/tcp\_syn\_retries}. Il valore predefinito per la ripetizione dell'invio è di 5 volte, che comporta un timeout dopo circa 180 secondi. % -% Le informazioni su tutte le opzioni settabili via /proc stanno in +% Le informazioni su tutte le opzioni impostabili via /proc stanno in % Linux/Documentation/networking/ip-sysctl.txt % \item Il client riceve come risposta al SYN un RST significa che non c'è @@ -822,22 +826,22 @@ sostanza l'effetto della funzione \texttt{CLOSED} a quello \texttt{LISTEN}. In genere si chiama la funzione in un server dopo le chiamate a \func{socket} e \func{bind} e prima della chiamata ad \func{accept}. Il prototipo della funzione come definito dalla -man page è: +pagina di manuale è: \begin{prototype}{sys/socket.h}{int listen(int sockfd, int backlog)} La funzione pone il socket specificato da \var{sockfd} in modalità passiva e predispone una coda per le connessioni in arrivo di lunghezza pari a \var{backlog}. La funzione si può applicare solo a socket di tipo \macro{SOCK\_STREAM} o \macro{SOCK\_SEQPACKET}. - - La funzione restituisce 0 in caso di successo e -1 in caso di errore. I - codici di errore restituiti in \var{errno} sono i seguenti: + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + errore. I codici di errore restituiti in \var{errno} sono i seguenti: \begin{errlist} - \item \macro{EBADF} l'argomento \var{sockfd} non è un file descriptor + \item[\macro{EBADF}] l'argomento \var{sockfd} non è un file descriptor valido. - \item \macro{ENOTSOCK} l'argomento \var{sockfd} non è un socket. - \item \macro{EOPNOTSUPP} il socket è di un tipo che non supporta questa + \item[\macro{ENOTSOCK}] l'argomento \var{sockfd} non è un socket. + \item[\macro{EOPNOTSUPP}] il socket è di un tipo che non supporta questa operazione. - \end{errlist} + \end{errlist}} \end{prototype} @@ -861,16 +865,16 @@ infatti vengono mantenute due code: Questi socket sono tutti nello stato \texttt{ESTABLISHED}. \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 \func{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. +Lo schema di funzionamento è descritto in \figref{fig:TCPel_xxx}, 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 \func{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 \var{backlog} era corrispondente al massimo valore della somma del numero di entrate possibili per ciascuna di @@ -878,11 +882,11 @@ 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. -In Linux il significato di questo valore è cambiato a partire dal kernel -2.2 per prevenire l'attacco chiamato \textit{syn flood}. Questo si basa +In Linux il significato di questo valore è cambiato a partire dal kernel 2.2 +per prevenire l'attacco chiamato \textit{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 + tecnica che viene detta \textit{ip spoofing}.} così che i SYN$+$ACK vanno perduti e la coda delle connessioni incomplete viene saturata, impedendo di fatto ulteriori connessioni. @@ -936,27 +940,28 @@ effettuare la comunicazione. Se non ci sono connessioni completate il processo viene messo in attesa. Il prototipo della funzione è il seguente: \begin{prototype}{sys/socket.h} {int accept(int sockfd, struct sockaddr *addr, socklen\_t *addrlen)} - La funzione estrae la prima connessione relativa al socket \var{sockfd} + Estrae la prima connessione relativa al socket \var{sockfd} in attesa sulla coda delle connessioni complete, che associa ad nuovo socket con le stesse caratteristiche di \var{sockfd} (restituito dalla funzione stessa). Il socket originale non viene toccato. Nella struttura \var{addr} e nella variabile \var{addrlen} vengono restituiti indirizzo e relativa lunghezza del client che si è connesso. - La funzione restituisce un numero di socket descriptor positivo in caso di - successo e -1 in caso di errore, nel qual caso la variabile \var{errno} - viene settata ai seguenti valori: + \bodydesc{La funzione restituisce un numero di socket descriptor positivo in + caso di successo e -1 in caso di errore, nel qual caso la variabile + \var{errno} viene impostata ai seguenti valori: \begin{errlist} - \item \macro{EBADF} l'argomento \var{sockfd} non è un file descriptor + \item[\macro{EBADF}] l'argomento \var{sockfd} non è un file descriptor valido. - \item \macro{ENOTSOCK} l'argomento \var{sockfd} non è un socket. - \item \macro{EOPNOTSUPP} il socket è di un tipo che non supporta questa + \item[\macro{ENOTSOCK}] l'argomento \var{sockfd} non è un socket. + \item[\macro{EOPNOTSUPP}] il socket è di un tipo che non supporta questa operazione. - \item \macro{EAGAIN} o \macro{EWOULDBLOCK} il socket è stato settato come - non bloccante, e non ci sono connessioni in attesa di essere accettate. - \item \macro{EPERM} Le regole del firewall non consentono la connessione. - \item \macro{ENOBUFS, ENOMEM} . Questo spesso significa che l'allocazione + \item[\macro{EAGAIN} o \macro{EWOULDBLOCK}] il socket è stato impostato come + non bloccante (vedi \secref{sec:file_noblocking}), e non ci sono + connessioni in attesa di essere accettate. + \item[\macro{EPERM}] Le regole del firewall non consentono la connessione. + \item[\macro{ENOBUFS, ENOMEM}] questo spesso significa che l'allocazione della memoria è limitata dai limiti sui buffer dei socket, non dalla memoria di sistema. \end{errlist} @@ -964,7 +969,7 @@ viene messo in attesa. Il prototipo della funzione socket come: \macro{EMFILE}, \macro{EINVAL}, \macro{ENOSR}, \macro{ENOBUFS}, \macro{EFAULT}, \macro{EPERM}, \macro{ECONNABORTED}, \macro{ESOCKTNOSUPPORT}, \macro{EPROTONOSUPPORT}, \macro{ETIMEDOUT}, - \macro{ERESTARTSYS}. + \macro{ERESTARTSYS}.} \end{prototype} La funzione può essere usata solo con socket che supportino la connessione @@ -997,14 +1002,14 @@ Se la funzione ha successo restituisce il descrittore di un nuovo socket creato dal kernel (detto \textit{connected socket}) a cui viene associata la prima connessione completa (estratta dalla relativa coda, vedi \secref{sec:TCPel_func_listen}) che il client TCP ha effettuato verso il -socket \var{sockfd}. Quest'ultimo (detto \textit{listening socket}) è -quello creato all'inizio e messo in ascolto con \func{listen}, e non viene -toccato dalla funzione. -Se non ci sono connessioni pendenti da accettare la funzione mette in attesa -il processo\footnote{a meno che non si sia settato il socket per essere - non-bloccante, nel qual caso ritorna con l'errore \func{EAGAIN}, - torneremo su questa modalità di operazione in \secref{sec:xxx_sock_noblock}} -fintanto che non ne arriva una. +socket \var{sockfd}. Quest'ultimo (detto \textit{listening socket}) è quello +creato all'inizio e messo in ascolto con \func{listen}, e non viene toccato +dalla funzione. Se non ci sono connessioni pendenti da accettare la funzione +mette in attesa il processo\footnote{a meno che non si sia imopstato il socket + per essere non bloccante (vedi \secref{sec:file_noblocking}), nel qual caso + ritorna con l'errore \macro{EAGAIN}. Torneremo su questa modalità di + operazione in \secref{sec:xxx_sock_noblock}.} fintanto che non ne arriva +una. Il meccanismo di funzionamento di \func{accept} è essenziale per capire il funzionamento di un server: in generale infatti c'è sempre un solo socket in @@ -1071,9 +1076,9 @@ concorrente abbiamo riscritto il server \texttt{daytime} dell'esempio precedente in forma concorrente, inserendo anche una opzione per la stampa degli indirizzi delle connessioni ricevute. -In \nfig\ è mostrato un estratto del codice, in cui si sono tralasciati il -trattamento delle opzioni e le parti rimaste invariate rispetto al precedente -esempio. Al solito il sorgente completo del server +In \figref{fig:TCPel_serv_code} è mostrato un estratto del codice, in cui si +sono tralasciati il trattamento delle opzioni e le parti rimaste invariate +rispetto al precedente esempio. Al solito il sorgente completo del server \file{ElemDaytimeTCPCuncServ.c} è allegato nella directory dei sorgenti. \begin{figure}[!htb] @@ -1185,19 +1190,21 @@ certo socket; la prima restituisce l'indirizzo locale, la seconda quello remoto. \begin{prototype}{sys/socket.h} -{int getsockname(int sockfd, struct sockaddr * name, socklen\_t * namelen)} + {int getsockname(int sockfd, struct sockaddr * name, socklen\_t * namelen)} + Legge l'indirizzo locale del socket \param{sockfd} nella struttura + \param{name}. - La funzione restituisce 0 in caso di successo e -1 in caso di errore. I - codici di errore restituiti in \var{errno} sono i seguenti: +\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + errore. I codici di errore restituiti in \var{errno} sono i seguenti: \begin{errlist} - \item \macro{EBADF} l'argomento \var{sockfd} non è un file descriptor + \item[\macro{EBADF}] l'argomento \var{sockfd} non è un file descriptor valido. - \item \macro{ENOTSOCK} l'argomento \var{sockfd} non è un socket. - \item \macro{ENOBUFS} non ci sono risorse sufficienti nel sistema per + \item[\macro{ENOTSOCK}] l'argomento \var{sockfd} non è un socket. + \item[\macro{ENOBUFS}] non ci sono risorse sufficienti nel sistema per eseguire l'operazione. - \item \macro{EFAULT} l'argomento \var{name} punta al di fuori dello + \item[\macro{EFAULT}] l'argomento \var{name} punta al di fuori dello spazio di indirizzi del processo. - \end{errlist} + \end{errlist}} \end{prototype} La funzione \func{getsockname} si usa tutte le volte che si vuole avere @@ -1213,20 +1220,22 @@ chiamata dopo il completamento di una connessione sul socket restituito da quella connessione. \begin{prototype}{sys/socket.h} -{int getpeername(int sockfd, struct sockaddr * name, socklen\_t * namelen)} - - La funzione restituisce 0 in caso di successo e -1 in caso di errore. I - codici di errore restituiti in \var{errno} sono i seguenti: + {int getpeername(int sockfd, struct sockaddr * name, socklen\_t * namelen)} + Legge l'indirizzo remoto del socket \param{sockfd} nella struttura + \param{name}. + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + errore. I codici di errore restituiti in \var{errno} sono i seguenti: \begin{errlist} - \item \macro{EBADF} l'argomento \var{sockfd} non è un file descriptor + \item[\macro{EBADF}] l'argomento \var{sockfd} non è un file descriptor valido. - \item \macro{ENOTSOCK} l'argomento \var{sockfd} non è un socket. - \item \macro{ENOTCONN} il socket non è connesso. - \item \macro{ENOBUFS} non ci sono risorse sufficienti nel sistema per + \item[\macro{ENOTSOCK}] l'argomento \var{sockfd} non è un socket. + \item[\macro{ENOTCONN}] il socket non è connesso. + \item[\macro{ENOBUFS}] non ci sono risorse sufficienti nel sistema per eseguire l'operazione. - \item \macro{EFAULT} l'argomento \var{name} punta al di fuori dello + \item[\macro{EFAULT}] l'argomento \var{name} punta al di fuori dello spazio di indirizzi del processo. - \end{errlist} + \end{errlist}} \end{prototype} @@ -1256,10 +1265,15 @@ connesso (\cmd{inetd} ad esempio fa sempre in modo che i file descriptor 0, 1 e 2 corrispondano al socket connesso) quest'ultimo potrà usare la funzione \func{getpeername} per determinare l'indirizzo remoto del client. -Infine è da chiarire (si legga la man page) che come per \func{accept} il -terzo parametro che è specificato dallo standard POSIX 1003.1g come di tipo -\type{socklen\_t *} in realtà deve sempre corrispondere ad un \type{int *} -come prima dello standard perché tutte le implementazioni dei socket BSD fanno -questa assunzione. +Infine è da chiarire (si legga la pagina di manuale) che, come per +\func{accept}, il terzo parametro, che è specificato dallo standard POSIX.1g +come di tipo \code{socklen\_t *} in realtà deve sempre corrispondere ad un +\ctyp{int *} come prima dello standard perché tutte le implementazioni dei +socket BSD fanno questa assunzione. + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "gapil" +%%% End: