Correzioni rimaste indietro ed espansione funzioni del resolver.
authorSimone Piccardi <piccardi@gnulinux.it>
Mon, 7 Nov 2016 20:02:45 +0000 (20:02 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Mon, 7 Nov 2016 20:02:45 +0000 (20:02 +0000)
listati/poll_echod.c
listati/resolv_newoption.c [new file with mode: 0644]
listati/resolv_option.c
listati/select_echod.c
prochand.tex
session.tex
sockctrl.tex
system.tex
tcpsock.tex

index e2e2a9612211c061ddb7aee75f2316b2901e8e55..87eeb9f084ed65040a9c77fd186f41206aa4d74b 100644 (file)
@@ -1,15 +1,13 @@
-    /* initialize all needed variables */
+...
     poll_set = (struct pollfd *) malloc(n * sizeof(struct pollfd));
     max_fd = list_fd;                 /* maximum now is listening socket */
-    for (i=0; i<n; i++) {
+    for (i=0; i<n; i++) {             /* initialize poll set */
        poll_set[i].fd = -1;
        poll_set[i].events = POLLRDNORM;
     }
-    poll_set[max_fd].fd = list_fd;
-    /* main loop, wait for connection and data inside a select */
-    while (1) {    
-       while ( ((n = poll(poll_set, max_fd + 1, -1)) < 0) 
-               && (errno == EINTR));         /* wait for data or connection */
+    poll_set[max_fd].fd = list_fd;    
+    while (1) {   /* main loop, wait for connection and data inside a poll */
+       while ( ((n=poll(poll_set, max_fd + 1, -1)) < 0) && (errno == EINTR));
        if (n < 0) {                          /* on real error exit */
            PrintErr("poll error");
            exit(1);
@@ -53,4 +51,4 @@
            }
        }
     }
-    exit(0);     /* normal exit, never reached */
+...
diff --git a/listati/resolv_newoption.c b/listati/resolv_newoption.c
new file mode 100644 (file)
index 0000000..244808f
--- /dev/null
@@ -0,0 +1,2 @@
+struct __res_state;
+typedef struct __res_state *res_state;
index ebe8f92572154ecd3c3bafb968ae1b2b9f28d2de..b90f8b9d8202e3ca6d3c63423fc94c73a4976e0c 100644 (file)
@@ -1 +1 @@
-       extern struct state _res;
+extern struct __res_state _res;
index d06b14ea503d7a5b0ada8077284c8af060826780..7687310de7cdd4e19fe27fb04119483fb085a900 100644 (file)
@@ -2,12 +2,10 @@
     memset(fd_open, 0, FD_SETSIZE);   /* clear array of open files */
     max_fd = list_fd;                 /* maximum now is listening socket */
     fd_open[max_fd] = 1;
-    /* main loop, wait for connection and data inside a select */
-    while (1) {  
-       FD_ZERO(&fset);               /* clear fd_set */
-       for (i = list_fd; i <= max_fd; i++) { /* initialize fd_set */
+    while (1) {   /* main loop, wait for connection and data inside a select */
+       FD_ZERO(&fset);                       /* clear fd_set */
+       for (i = list_fd; i <= max_fd; i++)   /* initialize fd_set */
            if (fd_open[i] != 0) FD_SET(i, &fset); 
-       }
        while ( ((n = select(max_fd + 1, &fset, NULL, NULL, NULL)) < 0) 
                && (errno == EINTR));         /* wait for data or connection */
        if (n < 0) {                          /* on real error exit */
            fd_open[fd] = 1;                  /* set new connection socket */
            if (max_fd < fd) max_fd = fd;     /* if needed set new maximum */
        }
-       /* loop on open connections */
-       i = list_fd;                  /* first socket to look */
-       while (n != 0) {              /* loop until active */
-           i++;                      /* start after listening socket */
+       i = list_fd;      /* first socket to look */
+       while (n != 0) {  /* loop on open connections */
+           i++;                             /* start after listening socket */
            if (fd_open[i] == 0) continue;   /* closed, go next */
            if (FD_ISSET(i, &fset)) {        /* if active process it*/
                n--;                         /* decrease active */
index 13ce5572a189046cfcfe3da7826976103c60350d..27361879e79dadd931019f4f2b42d469e6e8131f 100644 (file)
@@ -4241,6 +4241,10 @@ elenco, che illustra quelle attualmente disponibili:\footnote{si fa
 % http://lwn.net/Articles/531498/
 
 
+% TODO trattare le funzioni di protezione della memoria pkey_alloc, pkey_free,
+% pkey_mprotect, introdotte con il kernel 4.8, vedi
+% http://lwn.net/Articles/689395/ e Documentation/x86/protection-keys.txt 
+
 %TODO trattare kcmp aggiunta con il kernel 3.5, vedi
 % https://lwn.net/Articles/478111/
 
index 6561859ff0a46c3d7e5673f78fb286443b60898c..aa5a3b3b1e24ccd039997a8280ceb6b4affd7dfa 100644 (file)
@@ -2490,6 +2490,7 @@ Da fare.
 
 Qui vanno spiegati i terminali virtuali, \file{/dev/pty} e compagnia.
 % vedi man pts
+% vedi 
 
 
 \subsection{Allocazione dei terminali virtuali}
@@ -2500,6 +2501,8 @@ Qui vanno le cose su \func{openpty} e compagnia.
 % TODO le ioctl dei terminali (man tty_ioctl)
 % e http://www.net-security.org/article.php?id=83
 % TODO trattare \func{posix\_openpt}
+% vedi http://lwn.net/Articles/688809/,
+% http://man7.org/linux/man-pages/man3/ptsname.3.html
 
 
 % TODO materiale sulle seriali
index 44bb3a1f04b4feee4d6165be4eb7682ebf03a681..6ce42016041f73a4752eb096d2627fc4f5f5aae6 100644 (file)
@@ -35,18 +35,17 @@ porte o altre proprietà del sistema.
 \subsection{La struttura del \textit{resolver}}
 \label{sec:sock_resolver}
 
-\itindbeg{resolver}
-La risoluzione dei nomi è associata tradizionalmente al servizio del
-\textit{Domain Name Service} che permette di identificare le macchine su
-internet invece che per numero IP attraverso il relativo \textsl{nome a
-  dominio}.\footnote{non staremo ad entrare nei dettagli della definizione di
-  cosa è un nome a dominio, dandolo per noto, una introduzione alla
-  problematica si trova in \cite{AGL} (cap.~9) mentre per una trattazione
-  approfondita di tutte le problematiche relative al DNS si può fare
-  riferimento a \cite{DNSbind}.} In realtà per DNS si intendono spesso i
-server che forniscono su internet questo servizio, mentre nel nostro caso
-affronteremo la problematica dal lato client, di un qualunque programma che
-necessita di compiere questa operazione.
+\itindbeg{resolver} La risoluzione dei nomi è associata tradizionalmente al
+servizio del \itindex{Domain~Name~Service} \textit{Domain Name Service} che
+permette di identificare le macchine su internet invece che per numero IP
+attraverso il relativo \textsl{nome a dominio}.\footnote{non staremo ad
+  entrare nei dettagli della definizione di cosa è un nome a dominio, dandolo
+  per noto, una introduzione alla problematica si trova in \cite{AGL} (cap.~9)
+  mentre per una trattazione approfondita di tutte le problematiche relative
+  al DNS si può fare riferimento a \cite{DNSbind}.} In realtà per DNS si
+intendono spesso i server che forniscono su internet questo servizio, mentre
+nel nostro caso affronteremo la problematica dal lato client, di un qualunque
+programma che necessita di compiere questa operazione.
 
 \begin{figure}[!htb]
   \centering \includegraphics[width=11cm]{img/resolver}
@@ -106,32 +105,34 @@ NIS,\footnote{il \textit{Network Information Service} è un servizio, creato da
   \textit{netgroup}) varie macchine, centralizzando i servizi di definizione
   di utenti e gruppi e di autenticazione, oggi è sempre più spesso sostituito
   da LDAP.} o come quelli dei protocolli e dei servizi che sono mantenuti nei
-file statici \conffile{/etc/protocols} e \conffile{/etc/services}.  Molte di
-queste informazioni non si trovano su un DNS, ma in una rete locale può essere
-molto utile centralizzare il mantenimento di alcune di esse su opportuni
-server.  Inoltre l'uso di diversi supporti possibili per le stesse
+file statici \conffile{/etc/protocols} e \conffile{/etc/services}.  
+
+Molte di queste informazioni non si trovano su un DNS, ma in una rete locale
+può essere molto utile centralizzare il mantenimento di alcune di esse su
+opportuni server.  Inoltre l'uso di diversi supporti possibili per le stesse
 informazioni (ad esempio il nome delle macchine può essere mantenuto sia
 tramite \conffile{/etc/hosts}, che con il DNS, che con NIS) comporta il
-problema dell'ordine in cui questi vengono interrogati.\footnote{con le
-  implementazioni classiche i vari supporti erano introdotti modificando
-  direttamente le funzioni di libreria, prevedendo un ordine di interrogazione
-  predefinito e non modificabile (a meno di una ricompilazione delle librerie
-  stesse).}
+problema dell'ordine in cui questi vengono interrogati. Con le implementazioni
+classiche i vari supporti erano introdotti modificando direttamente le
+funzioni di libreria, prevedendo un ordine di interrogazione predefinito e non
+modificabile (a meno di una ricompilazione delle librerie stesse).
+
+\itindbeg{Name~Service~Switch~(NSS)} 
 
-\itindbeg{Name~Service~Switch~(NSS)}
 Per risolvere questa serie di problemi la risoluzione dei nomi a dominio
-eseguirà dal \textit{resolver} è stata inclusa all'interno di un meccanismo
+eseguità dal \textit{resolver} è stata inclusa all'interno di un meccanismo
 generico per la risoluzione di corrispondenze fra nomi ed informazioni ad essi
-associate chiamato \textit{Name Service Switch}\footnote{il sistema è stato
-  introdotto la prima volta nelle librerie standard di Solaris, le \acr{glibc}
-  hanno ripreso lo stesso schema, si tenga presente che questo sistema non
-  esiste per altre librerie standard come le \acr{libc5} o le \acr{uclib}.}
-cui abbiamo accennato anche in sez.~\ref{sec:sys_user_group} per quanto
-riguarda la gestione dei dati associati a utenti e gruppi.  Il \textit{Name
-  Service Switch} (cui spesso si fa riferimento con l'acronimo NSS) è un
-sistema di librerie dinamiche che permette di definire in maniera generica sia
-i supporti su cui mantenere i dati di corrispondenza fra nomi e valori
-numerici, sia l'ordine in cui effettuare le ricerche sui vari supporti
+associate chiamato \textit{Name Service Switch} cui abbiamo accennato anche in
+sez.~\ref{sec:sys_user_group} per quanto riguarda la gestione dei dati
+associati a utenti e gruppi. Il sistema è stato introdotto la prima volta
+nelle librerie standard di Solaris e le \acr{glibc} hanno ripreso lo stesso
+schema; si tenga presente che questo sistema non esiste per altre librerie
+standard come le \acr{libc5} o le \acr{uclib}.
+
+Il \textit{Name Service Switch} (cui spesso si fa riferimento con l'acronimo
+NSS) è un sistema di librerie dinamiche che permette di definire in maniera
+generica sia i supporti su cui mantenere i dati di corrispondenza fra nomi e
+valori numerici, sia l'ordine in cui effettuare le ricerche sui vari supporti
 disponibili. Il sistema prevede una serie di possibili classi di
 corrispondenza, quelle attualmente definite sono riportate in
 tab.~\ref{tab:sys_NSS_classes}.
@@ -176,14 +177,11 @@ tab.~\ref{tab:sys_NSS_classes}.
 % TODO rivedere meglio la tabella
 
 Il sistema del \textit{Name Service Switch} è controllato dal contenuto del
-file \conffile{/etc/nsswitch.conf}; questo contiene una riga\footnote{seguendo
-  una convezione comune per i file di configurazione le righe vuote vengono
-  ignorate e tutto quello che segue un carattere ``\texttt{\#}'' viene
-  considerato un commento.} di configurazione per ciascuna di queste classi,
-che viene inizia col nome di tab.~\ref{tab:sys_NSS_classes} seguito da un
-carattere ``\texttt{:}'' e prosegue con la lista dei \textsl{servizi} su cui
-le relative informazioni sono raggiungibili, scritti nell'ordine in cui si
-vuole siano interrogati.
+file \conffile{/etc/nsswitch.conf}; questo contiene una riga di configurazione
+per ciascuna di queste classi, che viene inizia col nome di
+tab.~\ref{tab:sys_NSS_classes} seguito da un carattere ``\texttt{:}'' e
+prosegue con la lista dei \textsl{servizi} su cui le relative informazioni
+sono raggiungibili, scritti nell'ordine in cui si vuole siano interrogati.
 
 Ogni servizio è specificato a sua volta da un nome, come \texttt{file},
 \texttt{dns}, \texttt{db}, ecc.  che identifica la libreria dinamica che
@@ -194,12 +192,13 @@ implementa le funzioni.
 
 In ogni caso, qualunque sia la modalità con cui ricevono i dati o il supporto
 su cui vengono mantenuti, e che si usino o meno funzionalità aggiuntive
-fornire dal sistema del \textit{Name Service Switch}, dal punto di vista di un
+fornite dal sistema del \textit{Name Service Switch}, dal punto di vista di un
 programma che deve effettuare la risoluzione di un nome a dominio, tutto
 quello che conta sono le funzioni classiche che il \textit{resolver} mette a
-disposizione,\footnote{è cura della implementazione fattane nelle \acr{glibc}
-  tenere conto della presenza del \textit{Name Service Switch}.} e sono queste
-quelle che tratteremo nelle sezioni successive.
+disposizione (è cura delle \acr{glibc} tenere conto della presenza del
+\textit{Name Service Switch}) e sono queste quelle che tratteremo nelle
+sezioni successive.  
+
 \itindend{Name~Service~Switch~(NSS)}
 
 
@@ -207,14 +206,15 @@ quelle che tratteremo nelle sezioni successive.
 \label{sec:sock_resolver_functions}
 
 Prima di trattare le funzioni usate normalmente nella risoluzione dei nomi a
-dominio conviene trattare in maniera più dettagliata il meccanismo principale
-da esse utilizzato e cioè quello del servizio DNS. Come accennato questo,
-benché in teoria sia solo uno dei possibili supporti su cui mantenere le
-informazioni, in pratica costituisce il meccanismo principale con cui vengono
-risolti i nomi a dominio.  Per questo motivo esistono una serie di funzioni di
-libreria che servono specificamente ad eseguire delle interrogazioni verso un
-server DNS, funzioni che poi vengono utilizzate per realizzare le funzioni
-generiche di libreria usate anche dal sistema del \textit{resolver}.
+dominio conviene trattare in maniera più dettagliata il servizio DNS. Come
+accennato questo, benché esso in teoria sia solo uno dei possibili supporti su
+cui mantenere le informazioni, in pratica costituisce il meccanismo principale
+con cui vengono risolti i nomi a dominio. Inolte esso può fornire anche
+ulteriori informazioni oltre relative alla risoluzione dei nomi a dominio.
+Per questo motivo esistono una serie di funzioni di libreria che servono
+specificamente ad eseguire delle interrogazioni verso un server DNS, funzioni
+che poi vengono utilizzate anche per realizzare le funzioni generiche di
+libreria usate dal sistema del \textit{resolver}.
 
 Il sistema del DNS è in sostanza di un database distribuito organizzato in
 maniera gerarchica, i dati vengono mantenuti in tanti server distinti ciascuno
@@ -235,33 +235,36 @@ per un suo dominio di secondo livello ad un altro server, il quale a sua volta
 potrà delegare la risoluzione di un eventuale sotto-dominio di terzo livello ad
 un altro server ancora.
 
-In realtà un server DNS è in grado di fare altro rispetto alla risoluzione di
-un nome a dominio in un indirizzo IP; ciascuna voce nel database viene
-chiamata \textit{resource record}, e può contenere diverse informazioni. In
-genere i \textit{resource record} vengono classificati per la \textsl{classe
-  di indirizzi} cui i dati contenuti fanno riferimento, e per il \textsl{tipo}
-di questi ultimi.\footnote{ritroveremo classi di indirizzi e tipi di record
-  più avanti in tab.~\ref{tab:DNS_address_class} e
-  tab.~\ref{tab:DNS_record_type}.}  Oggigiorno i dati mantenuti nei server DNS
+Come accennato un server DNS è in grado di fare molto altro rispetto alla
+risoluzione di un nome a dominio in un indirizzo IP: ciascuna voce nel
+database viene chiamata \textit{resource record}, e può contenere diverse
+informazioni. In genere i \textit{resource record} vengono classificati per la
+\textsl{classe di indirizzi} cui i dati contenuti fanno riferimento, e per il
+\textsl{tipo} di questi ultimi (ritroveremo classi di indirizzi e tipi di
+record più avanti in tab.~\ref{tab:DNS_address_class} e
+tab.~\ref{tab:DNS_record_type}).  Oggigiorno i dati mantenuti nei server DNS
 sono quasi esclusivamente relativi ad indirizzi internet, per cui in pratica
 viene utilizzata soltanto una classe di indirizzi; invece le corrispondenze
 fra un nome a dominio ed un indirizzo IP sono solo uno fra i vari tipi di
 informazione che un server DNS fornisce normalmente.
 
 L'esistenza di vari tipi di informazioni è un altro dei motivi per cui il
-\textit{resolver} prevede, rispetto a quelle relative alla semplice
-risoluzione dei nomi, un insieme di funzioni specifiche dedicate
-all'interrogazione di un server DNS; la prima di queste funzioni è
-\funcd{res\_init}, il cui prototipo è:
-\begin{functions}
-  \headdecl{netinet/in.h} \headdecl{arpa/nameser.h} \headdecl{resolv.h}
-  \funcdecl{int res\_init(void)}
-
-Inizializza il sistema del \textit{resolver}.
+\textit{resolver} prevede, oltre a quelle relative alla semplice risoluzione
+dei nomi, un insieme di funzioni specifiche dedicate all'interrogazione di un
+server DNS, tutte nella forma \texttt{res\_}\textsl{\texttt{nome}}.
+Tradizionalmente la prima di queste funzioni è \funcd{res\_init}, il cui
+prototipo è:
 
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
-  errore.}
-\end{functions}
+\begin{funcproto}{
+\fhead{netinet/in.h} 
+\fhead{arpa/nameser.h} 
+\fhead{resolv.h}
+\fdecl{int res\_init(void)}
+\fdesc{Inizializza il sistema del \textit{resolver}.} 
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore.
+}
+\end{funcproto}
 
 La funzione legge il contenuto dei file di configurazione (i già citati
 \file{resolv.conf} e \file{host.conf}) per impostare il dominio di default,
@@ -273,20 +276,48 @@ ambiente \envvar{LOCALDOMAIN}). In genere non è necessario eseguire questa
 funzione direttamente in quanto viene automaticamente chiamata la prima volta
 che si esegue una delle altre.
 
-Le impostazioni e lo stato del \textit{resolver} vengono mantenuti in una
-serie di variabili raggruppate nei campi di una apposita struttura \var{\_res}
-usata da tutte queste funzioni. Essa viene definita in \headfiled{resolv.h} ed
-è utilizzata internamente alle funzioni essendo definita come variabile
-globale; questo consente anche di accedervi direttamente all'interno di un
-qualunque programma, una volta che la sia opportunamente dichiarata come:
+Le impostazioni e lo stato del \textit{resolver} inizializzati da
+\func{res\_init} vengono mantenuti in una serie di variabili raggruppate nei
+campi di una apposita struttura \var{\_res} usata da tutte queste
+funzioni. Essa viene definita in \headfiled{resolv.h} ed è utilizzata
+internamente alle funzioni essendo definita come variabile globale; questo
+consente anche di accedervi direttamente all'interno di un qualunque
+programma, una volta che la sia opportunamente dichiarata come:
 \includecodesnip{listati/resolv_option.c}
 
-Tutti i campi della struttura sono ad uso interno, e vengono usualmente
-inizializzati da \func{res\_init} in base al contenuto dei file di
+Dato che l'uso di una variabile globale rende tutte le funzioni classiche non
+rientranti, con l'uscita di BIND 8.2 è stata introdotta una nuova interfaccia
+in cui tutte le nuove funzioni (il cui nome è ottenuto apponendo una
+``\texttt{n}'' al nome di quella tradizionale nella forma
+\texttt{res\_n\textsl{nome}}). Tutte le nuove funzioni prendono un primo
+argomento aggiuntivo, \param{statep}, che punti ad una struttura dello stesso
+tipo, che verrà usato per mantenere lo stato del \textit{resolver} e potrà
+essere usata senza problemi anche con programmi \textit{multithread}.  Anche
+in questo caso per poterlo utilizzare occorrerà una opportuna dichiarazione
+del tipo di dato con:
+\includecodesnip{listati/resolv_newoption.c}
+e la nuova funzione che utilizzata per inizializzare il \textit{resolver} (che
+come la precedente viene chiamata automaticamente dalle altre funzioni) è
+\funcd{res\_ninit} il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{netinet/in.h} 
+\fhead{arpa/nameser.h} 
+\fhead{resolv.h}
+\fdecl{int res\_ninit(res\_state statep)}
+\fdesc{Inizializza il sistema del \textit{resolver}.} 
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore.
+}
+\end{funcproto}
+
+Indipendentemente da quale versione delle funzioni si usino, tutti i campi
+della struttura sono ad uso interno, e vengono usualmente inizializzate da
+\func{res\_init} o \func{res\_ninit} in base al contenuto dei file di
 configurazione e ad una serie di valori di default. L'unico campo che può
 essere utile modificare è \var{\_res.options}, una maschera binaria che
 contiene una serie di bit di opzione che permettono di controllare il
-comportamento del \textit{resolver}. 
+comportamento del \textit{resolver}.
 
 \begin{table}[htb]
   \centering
@@ -359,34 +390,37 @@ di ambiente come abbiamo visto per \envvar{LOCALDOMAIN}. In particolare con
 controlla quante volte viene ripetuto il tentativo di connettersi ad un server
 DNS prima di dichiarare fallimento; il valore di default è 4, un valore nullo
 significa bloccare l'uso del DNS. Infine con \envvar{RES\_TIMEOUT} si
-soprassiede il valore del campo \var{retrans},\footnote{preimpostato al valore
-  della omonima costante \const{RES\_TIMEOUT} di \headfile{resolv.h}.} che è
-il valore preso come base (in numero di secondi) per definire la scadenza di
-una richiesta, ciascun tentativo di richiesta fallito viene ripetuto
-raddoppiando il tempo di scadenza per il numero massimo di volte stabilito da
+soprassiede il valore del campo \var{retrans} (preimpostato al valore della
+omonima costante \const{RES\_TIMEOUT} di \headfile{resolv.h}) che è il valore
+preso come base (in numero di secondi) per definire la scadenza di una
+richiesta, ciascun tentativo di richiesta fallito viene ripetuto raddoppiando
+il tempo di scadenza per il numero massimo di volte stabilito da
 \texttt{RES\_RETRY}.
 
-La funzione di interrogazione principale è \funcd{res\_query}, che serve ad
-eseguire una richiesta ad un server DNS per un nome a dominio
-\textsl{completamente specificato} (quello che si chiama
-\itindex{Fully~Qualified~Domain~Name~(FQDN)} FQDN, \textit{Fully Qualified
-  Domain Name}); il suo prototipo è:
-
-\begin{functions}
-\headdecl{netinet/in.h}
-\headdecl{arpa/nameser.h}
-\headdecl{resolv.h}
-\funcdecl{int res\_query(const char *dname, int class, int type,
+La funzione di interrogazione principale è \funcd{res\_query}
+(\funcd{res\_nquery} per la nuova interfaccia), che serve ad eseguire una
+richiesta ad un server DNS per un nome a dominio \textsl{completamente
+  specificato} (quello che si chiama
+\itindex{Fully~Qualified~Domain~Name~(FQDN)} FQDN, \textit{Fully Qualified 
+  Domain Name}); il loro prototipo è:
+
+\begin{funcproto}{
+\fhead{netinet/in.h} 
+\fhead{arpa/nameser.h} 
+\fhead{resolv.h}
+\fdecl{int res\_query(const char *dname, int class, int type,
               unsigned char *answer, int anslen)}
+\fdecl{int res\_nquery(res\_state statep, const char *dname, int class, int
+  type, \\
+  \phantom{int res\_nquery(}unsigned char *answer, int anslen)}
+\fdesc{Esegue una interrogazione al DNS.} 
+}
+{Le funzioni ritornano un valore positivo pari alla lunghezza dei dati scritti
+  nel buffer \param{answer} in caso di successo e $-1$ per un errore.
+}
+\end{funcproto}
 
-  Esegue una interrogazione al DNS.
-
-\bodydesc{La funzione restituisce un valore positivo pari alla lunghezza dei
-    dati scritti nel buffer \param{answer} in caso di successo e -1 in caso di
-    errore.}
-\end{functions}
-
-La funzione esegue una interrogazione ad un server DNS relativa al nome da
+Le funzioni eseguono una interrogazione ad un server DNS relativa al nome da
 risolvere passato nella stringa indirizzata da \param{dname}, inoltre deve
 essere specificata la classe di indirizzi in cui eseguire la ricerca con
 \param{class}, ed il tipo di \textit{resource record} che si vuole ottenere
@@ -394,34 +428,38 @@ con \param{type}. Il risultato della ricerca verrà scritto nel buffer di
 lunghezza \param{anslen} puntato da \param{answer} che si sarà opportunamente
 allocato in precedenza.
 
-
-Una seconda funzione di ricerca, analoga a \func{res\_query}, che prende gli
-stessi argomenti, ma che esegue l'interrogazione con le funzionalità
+Una seconda funzione di ricerca analoga a \func{res\_query}, che prende gli
+stessi argomenti ma che esegue l'interrogazione con le funzionalità
 addizionali previste dalle due opzioni \const{RES\_DEFNAMES} e
-\const{RES\_DNSRCH}, è \funcd{res\_search}, il cui prototipo è:
-\begin{functions}
-\headdecl{netinet/in.h}
-\headdecl{arpa/nameser.h}
-\headdecl{resolv.h}
-\funcdecl{int res\_search(const char *dname, int class, int type,
-              unsigned char *answer, int anslen)}
-
-  Esegue una interrogazione al DNS.
-  
-  \bodydesc{La funzione restituisce un valore positivo pari alla lunghezza dei
-    dati scritti nel buffer \param{answer} in caso di successo e -1 in caso di
-    errore.}
-\end{functions}
+\const{RES\_DNSRCH}, è \funcd{res\_search} (\funcd{res\_nsearch} per la nuova
+interfaccia), il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{netinet/in.h} 
+\fhead{arpa/nameser.h} 
+\fhead{resolv.h}
+\fdecl{int res\_search(const char *dname, int class, int type,
+  unsigned char *answer, \\
+  \phantom{int res\_search}int anslen)}
+\fdecl{int res\_nsearch(res\_state statep, const char *dname, int class, 
+  int type, \\
+  \phantom{int res\_nsearch(}unsigned char *answer, int anslen)}
+\fdesc{Esegue una interrogazione al DNS.} 
+}
+{Le funzioni ritornano un valore positivo pari alla lunghezza dei dati scritti
+  nel buffer \param{answer} in caso di successo e $-1$ per un errore.
+}
+\end{funcproto}
 
 In sostanza la funzione ripete una serie di chiamate a \func{res\_query}
-aggiungendo al nome contenuto nella stringa \param{dname} il dominio di
-default da cercare, fermandosi non appena trova un risultato.  Il risultato di
-entrambe le funzioni viene scritto nel formato opportuno (che sarà diverso a
-seconda del tipo di record richiesto) nel buffer di ritorno; sarà compito del
-programma (o di altre funzioni) estrarre i relativi dati, esistono una serie
-di funzioni interne usate per la scansione di questi dati, per chi fosse
-interessato una trattazione dettagliata è riportata nel quattordicesimo
-capitolo di \cite{DNSbind}.
+(\func{res\_nquery}) aggiungendo al nome contenuto nella stringa \param{dname}
+il dominio di default da cercare, fermandosi non appena trova un risultato.
+Il risultato di entrambe le funzioni viene scritto nel formato opportuno (che
+sarà diverso a seconda del tipo di record richiesto) nel buffer di ritorno;
+sarà compito del programma (o di altre funzioni) estrarre i relativi dati,
+esistono una serie di funzioni interne usate per la scansione di questi dati,
+per chi fosse interessato una trattazione dettagliata è riportata nel
+quattordicesimo capitolo di \cite{DNSbind}.
 
 Le classi di indirizzi supportate da un server DNS sono tre, ma di queste in
 pratica oggi viene utilizzata soltanto quella degli indirizzi internet; le
index 8593a42d4d67c1cf7be29c727d2a31eb4a0e016a..8e64ed513b109b61b1c12bc8290e7b4ab2b49202 100644 (file)
@@ -3226,7 +3226,7 @@ che errori relativi alla stessa linea non vengano ripetuti.
 % LocalWords:  newlen ENOTDIR EINVAL ENOMEM linux array oldvalue paging stack
 % LocalWords:  TCP shell Documentation ostype hostname osrelease version mount
 % LocalWords:  const source filesystemtype mountflags ENODEV ENOTBLK block read
-% LocalWords:  device EBUSY only EACCES NODEV ENXIO major RTSIG syscall PID NSS
+% LocalWords:  device EBUSY only EACCES NODEV ENXIO major RTSIG syscall PID 
 % LocalWords:  number EMFILE dummy ENAMETOOLONG ENOENT ELOOP virtual devfs MGC
 % LocalWords:  magic MSK RDONLY NOSUID suid sgid NOEXEC SYNCHRONOUS REMOUNT MNT
 % LocalWords:  MANDLOCK mandatory locking WRITE APPEND append IMMUTABLE NOATIME
index d6b5a945f216475483d1b44356e1004d708a5aa8..8a7b5e794a5c8ceae62757c8b360e13320c8c3a7 100644 (file)
@@ -3414,8 +3414,8 @@ disponibile coi sorgenti allegati nel file \texttt{select\_echod.c}.
     \includecodesample{listati/select_echod.c}
   \end{minipage} 
   \normalsize
-  \caption{La sezione principale del codice della nuova versione di server
-    \textit{echo} basati sull'uso della funzione \func{select}.}
+  \caption{La sezione principale della nuova versione di server
+    \textit{echo} basato sull'uso della funzione \func{select}.}
   \label{fig:TCP_SelectEchod}
 \end{figure}
 
@@ -3427,7 +3427,7 @@ tabella dei socket connessi mantenuta nel vettore \var{fd\_open} dimensionato
 al valore di \const{FD\_SETSIZE}, ed una variabile \var{max\_fd} per
 registrare il valore più alto dei file descriptor aperti.
 
-Prima di entrare nel ciclo principale (\texttt{\small 6--56}) la nostra
+Prima di entrare nel ciclo principale (\texttt{\small 5--53}) la nostra
 tabella viene inizializzata (\texttt{\small 2}) a zero (valore che
 utilizzeremo come indicazione del fatto che il relativo file descriptor non è
 aperto), mentre il valore massimo (\texttt{\small 3}) per i file descriptor
@@ -3435,23 +3435,23 @@ aperti viene impostato a quello del socket in ascolto, in quanto esso è
 l'unico file aperto, oltre i tre standard, e pertanto avrà il valore più alto,
 che verrà anche (\texttt{\small 4}) inserito nella tabella.
 
-La prima sezione (\texttt{\small 7--10}) del ciclo principale esegue la
+La prima sezione (\texttt{\small 6--8}) del ciclo principale esegue la
 costruzione del \textit{file descriptor set} \var{fset} in base ai socket
 connessi in un certo momento; all'inizio ci sarà soltanto il socket in ascolto
 ma nel prosieguo delle operazioni verranno utilizzati anche tutti i socket
 connessi registrati nella tabella \var{fd\_open}.  Dato che la chiamata di
 \func{select} modifica il valore del \textit{file descriptor set} è necessario
-ripetere (\texttt{\small 7}) ogni volta il suo azzeramento per poi procedere
-con il ciclo (\texttt{\small 8--10}) in cui si impostano i socket trovati
+ripetere (\texttt{\small 6}) ogni volta il suo azzeramento per poi procedere
+con il ciclo (\texttt{\small 7--8}) in cui si impostano i socket trovati
 attivi.
 
 Per far questo si usa la caratteristica dei file descriptor, descritta in
 sez.~\ref{sec:file_open_close}, per cui il kernel associa sempre ad ogni nuovo
 file il file descriptor con il valore più basso disponibile. Questo fa sì che
-si possa eseguire il ciclo (\texttt{\small 8}) a partire da un valore minimo,
+si possa eseguire il ciclo (\texttt{\small 7}) a partire da un valore minimo,
 che sarà sempre quello del socket in ascolto, mantenuto in \var{list\_fd},
 fino al valore massimo di \var{max\_fd} che dovremo aver cura di tenere
-aggiornato.  Dopo di che basterà controllare (\texttt{\small 9}) nella nostra
+aggiornato.  Dopo di che basterà controllare (\texttt{\small 8}) nella nostra
 tabella se il file descriptor è in uso o meno,\footnote{si tenga presente che
   benché il kernel assegni sempre il primo valore libero, si potranno sempre
   avere dei \textsl{buchi} nella nostra tabella dato che nelle operazioni i
@@ -3462,64 +3462,65 @@ Una volta inizializzato con i socket aperti il nostro \textit{file descriptor
   set} potremo chiamare \func{select} per fargli osservare lo stato degli
 stessi (in lettura, presumendo che la scrittura sia sempre consentita). Come
 per il precedente esempio di sez.~\ref{sec:TCP_child_hand}, essendo questa
-l'unica funzione che può bloccarsi, ed essere interrotta da un segnale, la
-eseguiremo (\texttt{\small 11--12}) all'interno di un ciclo di \code{while}
+l'unica funzione che può bloccarsi ed essere interrotta da un segnale, la
+eseguiremo (\texttt{\small 9--10}) all'interno di un ciclo di \code{while},
 che la ripete indefinitamente qualora esca con un errore di \errcode{EINTR}.
-Nel caso invece di un errore normale si provvede (\texttt{\small 13--16}) ad
-uscire stampando un messaggio di errore.
-
-Se invece la funzione ritorna normalmente avremo in \var{n} il numero di
-socket da controllare. Nello specifico si danno due possibili casi diversi per
-cui \func{select} può essere ritornata: o si è ricevuta una nuova connessione
-ed è pronto il socket in ascolto, sul quale si può eseguire \func{accept}, o
-c'è attività su uno dei socket connessi, sui quali si può eseguire
-\func{read}.
-
-Il primo caso viene trattato immediatamente (\texttt{\small 17--26}): si
-controlla (\texttt{\small 17}) che il socket in ascolto sia fra quelli attivi,
-nel qual caso anzitutto (\texttt{\small 18}) se ne decrementa il numero in
-\var{n}. Poi, inizializzata (\texttt{\small 19}) la lunghezza della struttura
-degli indirizzi, si esegue \func{accept} per ottenere il nuovo socket connesso
-controllando che non ci siano errori (\texttt{\small 20--23}). In questo caso
-non c'è più la necessità di controllare per interruzioni dovute a segnali, in
-quanto siamo sicuri che \func{accept} non si bloccherà. Per completare la
-trattazione occorre a questo punto aggiungere (\texttt{\small 24}) il nuovo
-file descriptor alla tabella di quelli connessi, ed inoltre, se è il caso,
-aggiornare (\texttt{\small 25}) il valore massimo in \var{max\_fd}.
+Nel caso invece di un errore normale si provvede (\texttt{\small 11--14}) ad
+uscire dal programma stampando un messaggio di errore.
+
+Infine quando la funzione ritorna normalmente avremo in \var{n} il numero di
+socket da controllare. Nello specifico si danno due casi per cui \func{select}
+può ritornare: o si è ricevuta una nuova connessione ed è pronto il socket in
+ascolto, sul quale si può eseguire \func{accept}, o c'è attività su uno dei
+socket connessi, sui quali si può eseguire \func{read}.
+
+Il primo caso viene trattato immediatamente (\texttt{\small 15--24}): si
+controlla (\texttt{\small 15}) che il socket in ascolto sia fra quelli attivi,
+nel qual caso anzitutto (\texttt{\small 16}) se ne decrementa il numero
+mantenuto nella variabile \var{n}. Poi, inizializzata (\texttt{\small 17}) la
+lunghezza della struttura degli indirizzi, si esegue \func{accept} per
+ottenere il nuovo socket connesso, controllando che non ci siano errori
+(\texttt{\small 18--21}). In questo caso non c'è più la necessità di
+controllare per interruzioni dovute a segnali, in quanto siamo sicuri che
+\func{accept} non si bloccherà. Per completare la trattazione occorre a questo
+punto aggiungere (\texttt{\small 22}) il nuovo file descriptor alla tabella di
+quelli connessi, ed inoltre, se è il caso, aggiornare (\texttt{\small 23}) il
+valore massimo in \var{max\_fd}.
 
 Una volta controllato l'arrivo di nuove connessioni si passa a verificare se
 ci sono dati sui socket connessi, per questo si ripete un ciclo
-(\texttt{\small 29--55}) fintanto che il numero di socket attivi \var{n} resta
-diverso da zero; in questo modo se l'unico socket con attività era quello
-connesso, avendo opportunamente decrementato il contatore, il ciclo verrà
-saltato e si ritornerà immediatamente, ripetuta l'inizializzazione del
-\textit{file descriptor set} con i nuovi valori nella tabella, alla chiamata
-di \func{accept}. 
+(\texttt{\small 26--52}) fintanto che il numero di socket attivi indicato
+dalla variabile \var{n} resta diverso da zero. In questo modo, se l'unico
+socket con attività era quello connesso, avendola opportunamente decrementata
+in precedenza, essa risulterà nulla, pertanto il ciclo di verifica verrà
+saltato e si ritornerà all'inzizio del ciclo principale, ripetendo, dopo
+l'inizializzazione del \textit{file descriptor set} con i nuovi valori nella
+tabella, la chiamata di \func{select}.
 
 Se il socket attivo non è quello in ascolto, o ce ne sono comunque anche
 altri, il valore di \var{n} non sarà nullo ed il controllo sarà
-eseguito. Prima di entrare nel ciclo comunque si inizializza (\texttt{\small
-  28}) il valore della variabile \var{i}, che useremo come indice nella
-tabella, \var{fd\_open} al valore minimo, corrispondente al file descriptor
-del socket in ascolto.
+eseguito. Prima di entrare nel ciclo di veridica comunque si inizializza
+(\texttt{\small 25}) il valore della variabile \var{i}, che useremo come
+indice nella tabella \var{fd\_open}, al valore minimo, corrispondente al file
+descriptor del socket in ascolto.
 
-Il primo passo (\texttt{\small 30}) nella verifica è incrementare il valore
+Il primo passo (\texttt{\small 27}) nella verifica è incrementare il valore
 dell'indice \var{i} per posizionarsi sul primo valore possibile per un file
 descriptor associato ad un eventuale socket connesso, dopo di che si controlla
-(\texttt{\small 31}) se questo è nella tabella dei socket connessi, chiedendo
+(\texttt{\small 28}) se questo è nella tabella dei socket connessi, chiedendo
 la ripetizione del ciclo in caso contrario. Altrimenti si passa a verificare
-(\texttt{\small 32}) se il file descriptor corrisponde ad uno di quelli
-attivi, e nel caso si esegue (\texttt{\small 33}) una lettura, uscendo con un
-messaggio in caso di errore (\texttt{\small 34--38}).
-
-Se (\texttt{\small 39}) il numero di byte letti \var{nread} è nullo si è in
-presenza di un \textit{end-of-file}, indice che una connessione che si è
-chiusa, che deve essere trattato (\texttt{\small 39--48}) opportunamente.  Il
-primo passo è chiudere (\texttt{\small 40}) anche il proprio capo del socket e
-rimuovere (\texttt{\small 41}) il file descriptor dalla tabella di quelli
-aperti, inoltre occorre verificare (\texttt{\small 42}) se il file descriptor
+(\texttt{\small 29}) se il file descriptor corrisponde ad uno di quelli
+attivi, e nel caso si esegue (\texttt{\small 30}) una lettura, uscendo con un
+messaggio in caso di errore (\texttt{\small 31--35}).
+
+Se (\texttt{\small 36}) il numero di byte letti \var{nread} è nullo si è in
+presenza di una \textit{end-of-file}, indice che una connessione che si è
+chiusa, che deve essere trattata (\texttt{\small 36--45}) opportunamente.  Il
+primo passo è chiudere (\texttt{\small 37}) anche il proprio capo del socket e
+rimuovere (\texttt{\small 38}) il file descriptor dalla tabella di quelli
+aperti, inoltre occorre verificare (\texttt{\small 39}) se il file descriptor
 chiuso è quello con il valore più alto, nel qual caso occorre trovare
-(\texttt{\small 42--46}) il nuovo massimo, altrimenti (\texttt{\small 47}) si
+(\texttt{\small 39--43}) il nuovo massimo, altrimenti (\texttt{\small 44}) si
 può ripetere il ciclo da capo per esaminare (se ne restano) ulteriori file
 descriptor attivi.
 
@@ -3527,15 +3528,15 @@ Se però è stato chiuso il file descriptor più alto, dato che la scansione dei
 file descriptor attivi viene fatta a partire dal valore più basso, questo
 significa che siamo anche arrivati alla fine della scansione, per questo
 possiamo utilizzare direttamente il valore dell'indice \var{i} con un ciclo
-all'indietro (\texttt{\small 43}) che trova il primo valore per cui la tabella
-presenta un file descriptor aperto, e lo imposta (\texttt{\small 44}) come
-nuovo massimo, per poi tornare (\texttt{\small 44}) al ciclo principale con un
+all'indietro (\texttt{\small 40}) che trova il primo valore per cui la tabella
+presenta un file descriptor aperto, e lo imposta (\texttt{\small 41}) come
+nuovo massimo, per poi tornare (\texttt{\small 42}) al ciclo principale con un
 \code{break}, e rieseguire \func{select}.
 
 Se infine si sono effettivamente letti dei dati dal socket (ultimo caso
-rimasto) si potrà invocare immediatamente (\texttt{\small 49})
+rimasto) si potrà invocare immediatamente (\texttt{\small 46})
 \func{FullWrite} per riscriverli indietro sul socket stesso, avendo cura di
-uscire con un messaggio in caso di errore (\texttt{\small 50--53}). Si noti
+uscire con un messaggio in caso di errore (\texttt{\small 47--50}). Si noti
 che nel ciclo si esegue una sola lettura, contrariamente a quanto fatto con la
 precedente versione (si riveda il codice di fig.~\ref{fig:TCP_ServEcho_second})
 in cui si continuava a leggere fintanto che non si riceveva un
@@ -3623,8 +3624,8 @@ struttura del programma resta sostanzialmente la stessa.
     \includecodesample{listati/poll_echod.c}
   \end{minipage} 
   \normalsize
-  \caption{La sezione principale del codice della nuova versione di server
-    \textit{echo} basati sull'uso della funzione \func{poll}.}
+  \caption{La sezione principale della nuova versione di server
+    \textit{echo} basato sull'uso della funzione \func{poll}.}
   \label{fig:TCP_PollEchod}
 \end{figure}
 
@@ -3646,8 +3647,8 @@ l'opzione \texttt{-n} ed ha un valore di default di 256.
 Dopo di che si preimposta (\texttt{\small 3}) il valore \var{max\_fd} del file
 descriptor aperto con valore più alto a quello del socket in ascolto (al
 momento l'unico), e si provvede (\texttt{\small 4--7}) ad inizializzare le
-strutture, disabilitando (\texttt{\small 5}) l'osservazione con un valore
-negativo del campo \var{fd} ma predisponendo (\texttt{\small 6}) il campo
+strutture, disabilitando l'osservazione (\texttt{\small 5}) con un valore
+negativo del campo \var{fd}, ma predisponendo (\texttt{\small 6}) il campo
 \var{events} per l'osservazione dei dati normali con \const{POLLRDNORM}.
 Infine (\texttt{\small 8}) si attiva l'osservazione del socket in ascolto
 inizializzando la corrispondente struttura. Questo metodo comporta, in
@@ -3657,59 +3658,59 @@ che non vengono mai utilizzate in quanto la prima è sempre quella relativa al
 socket in ascolto.
 
 Una volta completata l'inizializzazione tutto il lavoro viene svolto
-all'interno del ciclo principale \texttt{\small 10--55}) che ha una struttura
+all'interno del ciclo principale \texttt{\small 9--53}) che ha una struttura
 sostanzialmente identica a quello usato per il precedente esempio basato su
-\func{select}. La prima istruzione (\texttt{\small 11--12}) è quella di
-eseguire \func{poll} all'interno di un ciclo che la ripete qualora venisse
-interrotta da un segnale, da cui si esce soltanto quando la funzione ritorna,
-restituendo nella variabile \var{n} il numero di file descriptor trovati
-attivi.  Qualora invece si sia ottenuto un errore si procede (\texttt{\small
-  13--16}) alla terminazione immediata del processo provvedendo a stampare una
-descrizione dello stesso.
+\func{select}. La prima istruzione (\texttt{\small 10}) è quella di eseguire
+\func{poll} all'interno di un ciclo che la ripete qualora venisse interrotta
+da un segnale, da cui si esce soltanto quando la funzione ritorna restituendo
+nella variabile \var{n} il numero di file descriptor trovati attivi.  Qualora
+invece si sia ottenuto un errore si procede (\texttt{\small 11--14}) alla
+terminazione immediata del processo provvedendo a stampare una descrizione
+dello stesso.
 
 Una volta ottenuta dell'attività su un file descriptor si hanno di nuovo due
-possibilità. La prima possibilità è che ci sia attività sul socket in ascolto,
-indice di una nuova connessione, nel qual caso si controlla (\texttt{\small
-  17}) se il campo \var{revents} della relativa struttura è attivo; se è così
-si provvede (\texttt{\small 18}) a decrementare la variabile \var{n} (che
-assume il significato di numero di file descriptor attivi rimasti da
-controllare) per poi (\texttt{\small 19--23}) effettuare la chiamata ad
-\func{accept}, terminando il processo in caso di errore. Se la chiamata ad
-\func{accept} ha successo si procede attivando (\texttt{\small 24}) la
-struttura relativa al nuovo file descriptor da essa ottenuto, modificando
-(\texttt{\small 24}) infine quando necessario il valore massimo dei file
-descriptor aperti mantenuto in \var{max\_fd}.
+possibilità. La prima è che ci sia attività sul socket in ascolto, indice di
+una nuova connessione, nel qual caso si controlla (\texttt{\small 17}) se il
+campo \var{revents} della relativa struttura è attivo; se è così si provvede
+(\texttt{\small 16}) a decrementare la variabile \var{n} (che assume il
+significato di numero di file descriptor attivi rimasti da controllare) per
+poi (\texttt{\small 17--21}) effettuare la chiamata ad \func{accept},
+terminando il processo in caso di errore. Se la chiamata ad \func{accept} ha
+successo si procede attivando (\texttt{\small 22}) la struttura relativa al
+nuovo file descriptor da essa ottenuto, modificando (\texttt{\small 23})
+infine quando necessario il valore massimo dei file descriptor aperti
+mantenuto in \var{max\_fd}.
 
 La seconda possibilità è che vi sia dell'attività su uno dei socket aperti in
-precedenza, nel qual caso si inizializza (\texttt{\small 27}) l'indice \var{i}
+precedenza, nel qual caso si inizializza (\texttt{\small 25}) l'indice \var{i}
 del vettore delle strutture \struct{pollfd} al valore del socket in ascolto,
 dato che gli ulteriori socket aperti avranno comunque un valore superiore.  Il
-ciclo (\texttt{\small 28--54}) prosegue fintanto che il numero di file
+ciclo (\texttt{\small 26--52}) prosegue fintanto che il numero di file
 descriptor attivi, mantenuto nella variabile \var{n}, è diverso da zero. Se
 pertanto ci sono ancora socket attivi da individuare si comincia con
-l'incrementare (\texttt{\small 30}) l'indice e controllare (\texttt{\small
-  31}) se corrisponde ad un file descriptor in uso analizzando il valore del
+l'incrementare (\texttt{\small 27}) l'indice e controllare (\texttt{\small
+  28}) se corrisponde ad un file descriptor in uso analizzando il valore del
 campo \var{fd} della relativa struttura e chiudendo immediatamente il ciclo
 qualora non lo sia. Se invece il file descriptor è in uso si verifica
-(\texttt{\small 31}) se c'è stata attività controllando il campo
-\var{revents}. 
+(\texttt{\small 29}) se c'è stata attività controllando il campo
+\var{revents}.
 
 Di nuovo se non si verifica la presenza di attività il ciclo si chiude subito,
-altrimenti si provvederà (\texttt{\small 32}) a decrementare il numero \var{n}
-di file descriptor attivi da controllare e ad eseguire (\texttt{\small 33}) la
-lettura, ed in caso di errore (\texttt{\small 34--37}) al solito lo si
+altrimenti si provvederà (\texttt{\small 30}) a decrementare il numero \var{n}
+di file descriptor attivi da controllare e ad eseguire (\texttt{\small 31}) la
+lettura, ed in caso di errore (\texttt{\small 32--35}) al solito lo si
 notificherà uscendo immediatamente. Qualora invece si ottenga una condizione
-di \textit{end-of-file} (\texttt{\small 38--47}) si provvederà a chiudere
-(\texttt{\small 39}) anche il nostro capo del socket e a marcarlo
-(\texttt{\small 40}) nella struttura ad esso associata come inutilizzato.
-Infine dovrà essere ricalcolato (\texttt{\small 41--45}) un eventuale nuovo
-valore di \var{max\_fd}. L'ultimo passo è (\texttt{\small 46}) chiudere il
+di \textit{end-of-file} (\texttt{\small 36--45}) si provvederà a chiudere
+(\texttt{\small 37}) anche il nostro capo del socket e a marcarlo
+(\texttt{\small 38}) come inutilizzato nella struttura ad esso associata.
+Infine dovrà essere ricalcolato (\texttt{\small 39--43}) un eventuale nuovo
+valore di \var{max\_fd}. L'ultimo passo è chiudere (\texttt{\small 44}) il
 ciclo in quanto in questo caso non c'è più niente da riscrivere all'indietro
 sul socket.
 
-Se invece si sono letti dei dati si provvede (\texttt{\small 48}) ad
+Se invece si sono letti dei dati si provvede (\texttt{\small 46}) ad
 effettuarne la riscrittura all'indietro, con il solito controllo ed eventuale
-uscita e notifica in caso di errore (\texttt{\small 49--52}).
+uscita e notifica in caso di errore (\texttt{\small 47--51}).
 
 Come si può notare la logica del programma è identica a quella vista in
 fig.~\ref{fig:TCP_SelectEchod} per l'analogo server basato su \func{select};
@@ -3719,10 +3720,10 @@ dai dati in ingresso. Si applicano comunque anche a questo server le
 considerazioni finali di sez.~\ref{sec:TCP_serv_select}.
 
 
-\subsection{\textit{I/O multiplexing} con \textit{epoll}}
-\label{sec:TCP_serv_epoll}
+%\subsection{\textit{I/O multiplexing} con \textit{epoll}}
+%\label{sec:TCP_serv_epoll}
 
-Da fare.
+%Da fare.
 
 % TODO fare esempio con epoll