From: Simone Piccardi Date: Mon, 3 Apr 2017 13:02:16 +0000 (+0000) Subject: Correzioni e revisione di ieri. X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=b613eaf32bee556b7f2cd436fd37c89adfff8ca1 Correzioni e revisione di ieri. --- diff --git a/listati/mygetaddr.c b/listati/mygetaddr.c index 718b229..c940168 100644 --- a/listati/mygetaddr.c +++ b/listati/mygetaddr.c @@ -12,13 +12,13 @@ ptr = res; /* init list pointer */ printf("Canonical name %s\n", ptr->ai_canonname); /* print cname */ while (ptr != NULL) { /* loop on list */ - if (ptr->ai_family == PF_INET) { /* if IPv4 */ + if (ptr->ai_family == AF_INET) { /* if IPv4 */ printf("IPv4 address: \n"); addr = (struct sockaddr_in *) ptr->ai_addr; /* address */ port = ntohs(addr->sin_port); /* port */ string = inet_ntop(addr->sin_family, &addr->sin_addr, buffer, sizeof(buffer)); - } else if (ptr->ai_family == PF_INET6) { /* if IPv6 */ + } else if (ptr->ai_family == AF_INET6) { /* if IPv6 */ printf("IPv6 address: \n"); addr6 = (struct sockaddr_in6 *) ptr->ai_addr; /* address */ port = ntohs(addr6->sin6_port); /* port */ diff --git a/sockctrl.tex b/sockctrl.tex index 0364dd7..1b8ee7b 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -653,7 +653,7 @@ per \var{errno}, ma che usano il valore di \var{h\_errno}; la prima è } \end{funcbox}} -La funzione è l'analoga di \func{perror} e stampa sullo standard error un +La funzione è l'analoga di \func{perror} e stampa sullo \textit{standard error} un messaggio di errore corrispondente al valore corrente di \var{h\_errno}, a cui viene anteposta la stringa \param{string} passata come argomento. La seconda funzione è \funcd{hstrerror} ed il suo prototipo è: @@ -951,14 +951,17 @@ In questo caso l'argomento \param{addr} dovrà essere il puntatore ad una appropriata struttura contenente il valore dell'indirizzo IP (o IPv6) che si vuole risolvere. L'uso del tipo \texttt{char *} per questo argomento è storico, il dato dovrà essere fornito in una struttura \struct{in\_addr} per -un indirizzo IPv4 ed una struttura \struct{in6\_addr} per un indirizzo IPv6; -si ricordi che, come illustrato in fig.~\ref{fig:sock_sa_ipv4_struct}, che -mentre \struct{in\_addr} in realtà corrisponde ad un numero intero, da -esprimere comunque in \textit{network order}, non altrettanto avviene per -\struct{in6\_addr}, pertanto è sempre opportuno inizializzare questi indirizzi -con \func{inet\_pton} (vedi -sez.~\ref{sec:sock_conv_func_gen}). Nell'argomento \param{len} se ne dovrà poi -specificare la dimensione (rispettivamente 4 o 16), infine l'argomento +un indirizzo IPv4 ed una struttura \struct{in6\_addr} per un indirizzo IPv6. + +Si ricordi inoltre, come illustrato in fig.~\ref{fig:sock_sa_ipv4_struct}, che +mentre \struct{in\_addr} corrisponde in realtà ad un oridinario numero intero +a 32 bit (da esprimere comunque in \textit{network order}) non altrettanto +avviene per \struct{in6\_addr}, pertanto è sempre opportuno inizializzare +questi indirizzi con \func{inet\_pton} (vedi +sez.~\ref{sec:sock_conv_func_gen}). + +Nell'argomento \param{len} se ne dovrà poi specificare la dimensione +(rispettivamente 4 o 16), infine l'argomento \param{type} deve indicare il tipo di indirizzo, e dovrà essere o \const{AF\_INET} o \const{AF\_INET6}. @@ -994,23 +997,52 @@ quelli già illustrati in per \func{gethostbyname\_r} e \func{gethostbyname2\_r} e devono essere usati allo stesso modo. Infine lo standard POSIX prevede la presenza della funzione -\funcm{gethostent}, che dovrebbe ritornare la voce successiva nel database dei -nomi a dominio, ma questo ha senso solo per la lettura dei dati da un file -come \conffile{/etc/hosts} e non per i risultati del DNS. Nel caso della -\acr{glibc} questa viene usata allora solo per la lettura di quest'ultimo, -come avviene in altri sistemi, ed ignora le voci relative ad indirizzi -IPv6. Dato che i risultati si possono ottenere in modo generico con le -funzioni già illustrate, non la tratteremo esplicitamente, come non tratteremo -la sua variante rientrante \funcm{gethostent\_r}. - -Per risolvere il problema dell'uso da parte delle due funzioni -\func{gethostbyname} e \func{gethostbyaddr} di memoria statica che può essere -sovrascritta fra due chiamate successive, e per avere sempre la possibilità di -indicare esplicitamente il tipo di indirizzi voluto (cosa che non è possibile -con \func{gethostbyname}), seguendo -l'\href{http://www.ietf.org/rfc/rfc2553.txt}{RFC~2553} vennero introdotte due -nuove funzioni di risoluzione,\footnote{le funzioni sono presenti nelle - \acr{glibc} versione 2.1.96, ma essendo considerate deprecate (vedi +\funcd{gethostent}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{netdb.h} +\fdecl{struct hostent *gethostent(void)} +\fdesc{Ottiene la voce successiva nel database dei nomi a dominio.} +} + +{La funzione ritorna l'indirizzo ad una struttura \struct{hostent} in caso di + successo e \val{NULL} per un errore.} +\end{funcproto} + +La funzione dovrebbe ritornare (come puntatore alla solita struttura +\struct{hostent} allocata internamente) la voce successiva nel database dei +nomi a dominio, ma questo ha un significato soltato quando è relativo alla +lettura dei dati da un file come \conffile{/etc/hosts} e non per i risultati +del DNS. Nel caso della \acr{glibc} questa viene usata allora solo per la +lettura delle voci presenti in quest'ultimo, come avviene anche in altri +sistemi unix-like, ed inoltre ignora le voci relative ad indirizzi IPv6. + +Della stessa funzione le \acr{glibc} forniscono anche una versione rientrante +\funcd{gethostent\_r}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{netdb.h} +\fdecl{struct hostent *gethostent\_r(struct hostent *ret, char *buf, size\_t buflen,\\ +\phantom{struct hostent *gethostent\_r(}struct hostent **result, int *h\_errnop);} +\fdesc{Ottiene la voce successiva nel database dei nomi a dominio.} +} + +{La funzione ritorna $0$ in caso di successo e un valore non nullo per un errore.} +\end{funcproto} + +La funzione ha lo stesso effetto di \func{gethostent}; gli argomenti servono a +restituire i risultati in maniera rientrante e vanno usati secondo le modalità +già illustrate per \func{gethostbyname\_r} e \func{gethostbyname2\_r}. + +Dati i limiti delle funzioni \func{gethostbyname} e \func{gethostbyaddr} con +l'uso di memoria statica che può essere sovrascritta fra due chiamate +successive, e per avere sempre la possibilità di indicare esplicitamente il +tipo di indirizzi voluto (cosa che non è possibile con \func{gethostbyname}), +è stata successivamente proposta, +nell'\href{http://www.ietf.org/rfc/rfc2553.txt}{RFC~2553} un diversa +interfaccia con l'introduzione due nuove funzioni di +risoluzione,\footnote{dette funzioni sono presenti nelle \acr{glibc} versione + 2.1.96, ma essendo considerate deprecate (vedi sez.~\ref{sec:sock_advanced_name_services}) sono state rimosse nelle versioni successive.} \funcd{getipnodebyname} e \funcd{getipnodebyaddr}, i cui prototipi sono: @@ -1086,7 +1118,6 @@ la necessità di disallocare esplicitamente la memoria occupata dai risultati una volta che questi non siano più necessari; a tale scopo viene fornita la funzione \funcd{freehostent}, il cui prototipo è: - \begin{funcproto}{ \fhead{netdb.h} \fhead{sys/types.h} @@ -1107,10 +1138,10 @@ Infine per concludere la nostra panoramica sulle funzioni di risoluzione dei nomi dobbiamo citare le funzioni che permettono di interrogare gli altri servizi di risoluzione dei nomi illustrati in sez.~\ref{sec:sock_resolver}; in generale infatti ci sono una serie di funzioni nella forma -\texttt{getXXXbyname} e \texttt{getXXXbyaddr} (dove \texttt{XXX} indica il -servizio) per ciascuna delle informazioni di rete mantenute dal \textit{Name - Service Switch} che permettono rispettivamente di trovare una corrispondenza -cercando per nome o per numero. +\texttt{get\textsl{XXX}byname} e \texttt{get\textsl{XXX}byaddr} (dove +\texttt{\textsl{XXX}} indica il servizio) per ciascuna delle informazioni di +rete mantenute dal \textit{Name Service Switch} che permettono rispettivamente +di trovare una corrispondenza cercando per nome o per numero. L'elenco di queste funzioni è riportato nelle colonne finali di tab.~\ref{tab:name_resolution_functions}, dove le si sono suddivise rispetto @@ -1159,27 +1190,30 @@ ecc.) da associare alle rispettive porte. Le due funzioni da utilizzare per questo sono \funcd{getservbyname} e \funcd{getservbyport}, che permettono rispettivamente di ottenere il numero di porta associato ad un servizio dato il nome e viceversa; i loro prototipi sono: -\begin{functions} - \headdecl{netdb.h} - \funcdecl{struct servent *getservbyname(const char *name, const char *proto)} - \funcdecl{struct servent *getservbyport(int port, const char *proto)} - - Risolvono il nome di un servizio nel rispettivo numero di porta e viceversa. - - \bodydesc{Ritornano il puntatore ad una struttura \struct{servent} con i - risultati in caso di successo, o \val{NULL} in caso di errore.} -\end{functions} + + + +\begin{funcproto}{ +\fhead{netdb.h} +\fdecl{struct servent *getservbyname(const char *name, const char *proto)} +\fdecl{struct servent *getservbyport(int port, const char *proto)} +\fdesc{Risolvono il nome di un servizio nel rispettivo numero di porta e viceversa.} +} + +{Le funzioni ritornano il puntatore ad una struttura \struct{servent} con i + risultati in caso di successo e \val{NULL} per un errore.} +\end{funcproto} Entrambe le funzioni prendono come ultimo argomento una stringa \param{proto} -che indica il protocollo per il quale si intende effettuare la -ricerca,\footnote{le informazioni mantenute in \conffile{/etc/services} - infatti sono relative sia alle porte usate su UDP che su TCP, occorre quindi - specificare a quale dei due protocolli si fa riferimento.} che nel caso si -IP può avere come valori possibili solo \texttt{udp} o -\texttt{tcp};\footnote{in teoria si potrebbe avere un qualunque protocollo fra - quelli citati in \conffile{/etc/protocols}, posto che lo stesso supporti il - concetto di \textsl{porta}, in pratica questi due sono gli unici presenti.} -se si specifica un puntatore nullo la ricerca sarà eseguita su un protocollo +che indica il protocollo per il quale si intende effettuare la ricerca (le +informazioni mantenute in \conffile{/etc/services} infatti sono relative sia +alle porte usate su UDP che su TCP, occorre quindi specificare a quale dei due +protocolli si fa riferimento) che nel caso di IP può avere come valori +possibili solo \texttt{udp} o \texttt{tcp};\footnote{in teoria si potrebbe + avere un qualunque protocollo fra quelli citati in + \conffile{/etc/protocols}, posto che lo stesso supporti il concetto di + \textsl{porta}, in pratica questi due sono gli unici presenti.} se si +specifica un puntatore nullo la ricerca sarà eseguita su un protocollo qualsiasi. Il primo argomento è il nome del servizio per \func{getservbyname}, @@ -1226,22 +1260,21 @@ tab.~\ref{tab:sys_passwd_func} per le informazioni relative ai dati degli utenti e dei gruppi. Nel caso specifico dei servizi avremo allora le tre funzioni \funcd{setservent}, \funcd{getservent} e \funcd{endservent} i cui prototipi sono: -\begin{functions} - \headdecl{netdb.h} - \funcdecl{void setservent(int stayopen)} - Apre il file \conffile{/etc/services} e si posiziona al suo inizio. - - \funcdecl{struct servent *getservent(void)} - Legge la voce successiva nel file \conffile{/etc/services}. - \funcdecl{void endservent(void)} - Chiude il file \conffile{/etc/services}. +\begin{funcproto}{ +\fhead{netdb.h} +\fdecl{struct servent *getservent(void)} +\fdesc{Legge la voce successiva nel file \conffile{/etc/services}.} +\fdecl{void setservent(int stayopen)} +\fdesc{Apre il file \conffile{/etc/services} e si posiziona al suo inizio.} +\fdecl{void endservent(void)} +\fdesc{Chiude il file \conffile{/etc/services}.} +} - \bodydesc{Le due funzioni \func{setservent} e \func{endservent} non - restituiscono nulla, \func{getservent} restituisce il puntatore ad una - struttura \struct{servent} in caso di successo e \val{NULL} in caso di - errore o fine del file.} -\end{functions} +{Le due funzioni \func{setservent} e \func{endservent} non ritornano nulla, + \func{getservent} restituisce il puntatore ad una struttura \struct{servent} + in caso di successo e \val{NULL} per un errore o fine del file.} +\end{funcproto} La prima funzione, \func{getservent}, legge una singola voce a partire dalla posizione corrente in \conffile{/etc/services}, pertanto si può eseguire una @@ -1250,22 +1283,7 @@ aperto provvede automaticamente ad aprirlo, nel qual caso leggerà la prima voce. La seconda funzione, \func{setservent}, permette di aprire il file \conffile{/etc/services} per una successiva lettura, ma se il file è già stato aperto riporta la posizione di lettura alla prima voce del file, in questo -modo si può far ricominciare da capo una lettura sequenziale. L'argomento -\param{stayopen}, se diverso da zero, fa sì che il file resti aperto anche fra -diverse chiamate a \func{getservbyname} e \func{getservbyport}.\footnote{di - default dopo una chiamata a queste funzioni il file viene chiuso, cosicché - una successiva chiamata a \func{getservent} riparte dall'inizio.} La terza -funzione, \func{endservent}, provvede semplicemente a chiudere il file. - -Queste tre funzioni per la lettura sequenziale di nuovo sono presenti per -ciascuno dei vari tipi di informazione relative alle reti di -tab.~\ref{tab:name_resolution_functions}; questo significa che esistono -altrettante funzioni nella forma \texttt{setXXXent}, \texttt{getXXXent} e -\texttt{endXXXent}, analoghe alle precedenti per la risoluzione dei servizi, -che abbiamo riportato in tab.~\ref{tab:name_sequential_read}. Essendo, a -parte il tipo di informazione che viene trattato, sostanzialmente identiche -nel funzionamento e di scarso utilizzo, non staremo a trattarle una per una, -rimandando alle rispettive pagine di manuale. +modo si può far ricominciare da capo una lettura sequenziale. \begin{table}[!htb] \centering @@ -1286,6 +1304,23 @@ rimandando alle rispettive pagine di manuale. \label{tab:name_sequential_read} \end{table} +L'argomento \param{stayopen} di \func{setservent}, se diverso da zero, fa sì +che il file resti aperto anche fra diverse chiamate a \func{getservbyname} e +\func{getservbyport}; di default dopo una chiamata a queste funzioni il file +viene chiuso, cosicché una successiva chiamata a \func{getservent} riparte +dall'inizio. La terza funzione, \func{endservent}, provvede semplicemente a +chiudere il file. + +Queste tre funzioni per la lettura sequenziale di nuovo sono presenti per +ciascuno dei vari tipi di informazione relative alle reti di +tab.~\ref{tab:name_resolution_functions}; questo significa che esistono +altrettante funzioni nella forma \texttt{setXXXent}, \texttt{getXXXent} e +\texttt{endXXXent}, analoghe alle precedenti per la risoluzione dei servizi, +che abbiamo riportato in tab.~\ref{tab:name_sequential_read}. Essendo, a +parte il tipo di informazione che viene trattato, sostanzialmente identiche +nel funzionamento e di scarso utilizzo, non staremo a trattarle una per una, +rimandando alle rispettive pagine di manuale. + \subsection{Le funzioni avanzate per la risoluzione dei nomi} \label{sec:sock_advanced_name_services} @@ -1295,10 +1330,10 @@ risoluzione di nomi ed indirizzi IP, ma abbiamo già visto come esse soffrano di vari inconvenienti come il fatto che usano informazioni statiche, e non prevedono la possibilità di avere diverse classi di indirizzi. Anche se sono state create delle estensioni o metodi diversi che permettono di risolvere -alcuni di questi inconvenienti,\footnote{rimane ad esempio il problema - generico che si deve sapere in anticipo quale tipo di indirizzi IP (IPv4 o - IPv6) corrispondono ad un certo nome a dominio.} comunque esse non -forniscono una interfaccia sufficientemente generica. +alcuni di questi inconvenienti, comunque esse non forniscono una interfaccia +sufficientemente generica.\footnote{rimane ad esempio il problema generico che + si deve sapere in anticipo quale tipo di indirizzi IP (IPv4 o IPv6) + corrispondono ad un certo nome a dominio.} Inoltre in genere quando si ha a che fare con i socket non esiste soltanto il problema della risoluzione del nome che identifica la macchina, ma anche @@ -1308,26 +1343,27 @@ funzioni \func{gethostbyaddr}, \func{gethostbyname}, \var{getipnodebyname} e \var{getipnodebyaddr} ed è stata introdotta una interfaccia completamente nuova. -La prima funzione di questa interfaccia è \funcd{getaddrinfo},\footnote{la - funzione è definita, insieme a \func{getnameinfo} che vedremo più avanti, - nell'\href{http://www.ietf.org/rfc/rfc2553.txt}{RFC~2553}.} che combina le +La prima funzione di questa interfaccia è \funcd{getaddrinfo}, che combina le funzionalità delle precedenti \func{getipnodebyname}, \func{getipnodebyaddr}, \func{getservbyname} e \func{getservbyport}, consentendo di ottenere contemporaneamente sia la risoluzione di un indirizzo simbolico che del nome -di un servizio; il suo prototipo è: -\begin{functions} - \headdecl{netdb.h} - \headdecl{sys/socket.h} - \headdecl{netdb.h} +di un servizio; la funzione è stata introdotta, insieme a \func{getnameinfo} +che vedremo più avanti, +nell'\href{http://www.ietf.org/rfc/rfc2553.txt}{RFC~2553} ed il suo prototipo è: - \funcdecl{int getaddrinfo(const char *node, const char *service, const - struct addrinfo *hints, struct addrinfo **res)} - Esegue una risoluzione di un nome a dominio e di un nome di servizio. +\begin{funcproto}{ +\fhead{netdb.h} +\fhead{sys/socket.h} +\fdecl{int getaddrinfo(const char *node, const char *service, const + struct addrinfo *hints, \\ +\phantom{int getaddrinfo(}struct addrinfo **res)} +\fdesc{Esegue una risoluzione di un nome a dominio e di un nome di servizio.} +} - \bodydesc{La funzione restituisce 0 in caso di successo o un codice di - errore diverso da zero in caso di fallimento.} -\end{functions} +{La funzione ritorna $0$ in caso di successo e un codice di errore diverso da + zero per un errore.} +\end{funcproto} La funzione prende come primo argomento il nome della macchina che si vuole risolvere, specificato tramite la stringa \param{node}. Questo argomento, @@ -1358,7 +1394,7 @@ puntatore iniziale ad una \textit{linked list} di strutture di tipo \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{0.80\textwidth} + \begin{minipage}[c]{0.90\textwidth} \includestruct{listati/addrinfo.h} \end{minipage} \caption{La struttura \structd{addrinfo} usata nella nuova interfaccia POSIX @@ -1370,7 +1406,7 @@ Come illustrato la struttura \struct{addrinfo}, la cui definizione è riportata in fig.~\ref{fig:sock_addrinfo_struct}, viene usata sia in ingresso, per passare dei valori di controllo alla funzione, che in uscita, per ricevere i risultati. La definizione è ripresa direttamente dal file \headfiled{netdb.h} -in questa struttura viene dichiarata, la pagina di manuale riporta +in cui questa struttura viene dichiarata, la pagina di manuale riporta \type{size\_t} come tipo di dato per il campo \var{ai\_addrlen}, qui viene usata quanto previsto dallo standard POSIX, in cui viene utilizzato \type{socklen\_t}; i due tipi di dati sono comunque equivalenti. @@ -1384,14 +1420,14 @@ usati per impostare una selezione (impostandone il valore nella struttura puntata da \param{hints}), mentre in uscita indicano il tipo di risultato contenuto nella struttura. -Tutti i campi seguenti vengono usati soltanto in uscita; il campo -\var{ai\_addrlen} indica la dimensione della struttura degli indirizzi -ottenuta come risultato, il cui contenuto sarà memorizzato nella struttura -\struct{sockaddr} posta all'indirizzo puntato dal campo \var{ai\_addr}. Il -campo \var{ai\_canonname} è un puntatore alla stringa contenente il nome -canonico della macchina, ed infine, quando la funzione restituisce più di un -risultato, \var{ai\_next} è un puntatore alla successiva struttura -\struct{addrinfo} della lista. +Tutti i campi seguenti vengono usati soltanto in uscita e devono essere nulli +o \val{NULL} in ingresso; il campo \var{ai\_addrlen} indica la dimensione +della struttura degli indirizzi ottenuta come risultato, il cui contenuto sarà +memorizzato nella struttura \struct{sockaddr} posta all'indirizzo puntato dal +campo \var{ai\_addr}. Il campo \var{ai\_canonname} è un puntatore alla stringa +contenente il nome canonico della macchina, ed infine, quando la funzione +restituisce più di un risultato, \var{ai\_next} è un puntatore alla successiva +struttura \struct{addrinfo} della lista. Ovviamente non è necessario dare dei suggerimenti in ingresso, ed usando \val{NULL} come valore per l'argomento \param{hints} si possono compiere @@ -1403,9 +1439,9 @@ quale siano stati opportunamente impostati i valori dei campi I due campi \var{ai\_family} e \var{ai\_socktype} prendono gli stessi valori degli analoghi argomenti della funzione \func{socket}; in particolare per \var{ai\_family} si possono usare i valori di tab.~\ref{tab:net_pf_names} ma -sono presi in considerazione solo \const{PF\_INET} e \const{PF\_INET6}, mentre +sono presi in considerazione solo \const{AF\_INET} e \const{AF\_INET6}, mentre se non si vuole specificare nessuna famiglia di indirizzi si può usare il -valore \const{PF\_UNSPEC}. Allo stesso modo per \var{ai\_socktype} si possono +valore \const{AF\_UNSPEC}. Allo stesso modo per \var{ai\_socktype} si possono usare i valori illustrati in sez.~\ref{sec:sock_type} per indicare per quale tipo di socket si vuole risolvere il servizio indicato, anche se i soli significativi sono \const{SOCK\_STREAM} e \const{SOCK\_DGRAM}; in questo caso, @@ -1422,22 +1458,15 @@ nella selezione. \begin{table}[!htb] \centering \footnotesize - \begin{tabular}[c]{|l|p{10cm}|} + \begin{tabular}[c]{|l|p{8cm}|} \hline \textbf{Costante} & \textbf{Significato} \\ \hline \hline - \constd{AI\_PASSIVE} & Viene utilizzato per ottenere un indirizzo in - formato adatto per una successiva chiamata a - \func{bind}. Se specificato quando si è usato - \val{NULL} come valore per \param{node} gli - indirizzi restituiti saranno inizializzati al - valore generico (\const{INADDR\_ANY} per IPv4 e - \const{IN6ADDR\_ANY\_INIT} per IPv6), altrimenti - verrà usato l'indirizzo dell'interfaccia di - \textit{loopback}. Se invece non è impostato gli - indirizzi verranno restituiti in formato adatto ad - una chiamata a \func{connect} o \func{sendto}.\\ + \const{AI\_ADDRCONFIG} & Stesso significato dell'analoga di + tab.~\ref{tab:sock_getipnodebyname_flags}.\\ + \const{AI\_ALL} & Stesso significato dell'analoga di + tab.~\ref{tab:sock_getipnodebyname_flags}.\\ \constd{AI\_CANONNAME} & Richiede la restituzione del nome canonico della macchina, che verrà salvato in una stringa il cui indirizzo sarà restituito nel campo @@ -1452,12 +1481,35 @@ nella selezione. tab.~\ref{tab:addrinfo_error_code}), in questo modo si evita ogni chiamata alle funzioni di risoluzione.\\ + \constd{AI\_NUMERICSERVICE}& Analogo di \const{AI\_NUMERICHOST} per la + risoluzione di un servizio, con + \param{service} che deve essere espresso in forma + numerica.\\ + \constd{AI\_PASSIVE} & Viene utilizzato per ottenere un indirizzo in + formato adatto per una successiva chiamata a + \func{bind}. Se specificato quando si è usato + \val{NULL} come valore per \param{node} gli + indirizzi restituiti saranno inizializzati al + valore generico (\const{INADDR\_ANY} per IPv4 e + \const{IN6ADDR\_ANY\_INIT} per IPv6), altrimenti + verrà usato l'indirizzo dell'interfaccia di + \textit{loopback}. Se invece non è impostato gli + indirizzi verranno restituiti in formato adatto ad + una chiamata a \func{connect} o \func{sendto}.\\ \const{AI\_V4MAPPED} & Stesso significato dell'analoga di - tab.~\ref{tab:sock_getipnodebyname_flags}.\\ - \const{AI\_ALL} & Stesso significato dell'analoga di - tab.~\ref{tab:sock_getipnodebyname_flags}.\\ - \const{AI\_ADDRCONFIG} & Stesso significato dell'analoga di - tab.~\ref{tab:sock_getipnodebyname_flags}.\\ + tab.~\ref{tab:sock_getipnodebyname_flags}.\\ + \hline + \const{AI\_CANONIDN} & Se il nome canonico richiesto con + \const{AI\_CANONNAME} è codificato con questo + flag la codifica viene convertita in forma + leggibile nella localizzazione corrente.\\ + \const{AI\_IDN} & Se specificato il nome viene convertito, se + necessario, nella codifica IDN, usando la + localizzazione corrente.\\ + \const{AI\_IDN\_ALLOW\_UNASSIGNED} & attiva il controllo + \texttt{IDNA\_ALLOW\_UNASSIGNED}.\\ + \const{AI\_AI\_IDN\_USE\_STD3\_ASCII\_RULES} & attiva il controllo + \texttt{IDNA\_USE\_STD3\_ASCII\_RULES}\\ \hline \end{tabular} \caption{Costanti associate ai bit del campo \var{ai\_flags} della struttura @@ -1465,14 +1517,30 @@ nella selezione. \label{tab:ai_flags_values} \end{table} - -Infine l'ultimo campo è \var{ai\_flags}; che deve essere impostato come una -maschera binaria; i bit di questa variabile infatti vengono usati per dare -delle indicazioni sul tipo di risoluzione voluta, ed hanno valori analoghi a -quelli visti in sez.~\ref{sec:sock_name_services} per \func{getipnodebyname}; -il valore di \var{ai\_flags} può essere impostata con un OR aritmetico delle -costanti di tab.~\ref{tab:ai_flags_values}, ciascuna delle quali identifica un -bit della maschera. +% TODO mettere riferimento a IDNA_ALLOW_UNASSIGNED e IDNA_USE_STD3_ASCII_RULES + +Infine gli ultimi dettagli si controllano con il campo \var{ai\_flags}; che +deve essere impostato come una maschera binaria; i bit di questa variabile +infatti vengono usati per dare delle indicazioni sul tipo di risoluzione +voluta, ed hanno valori analoghi a quelli visti in +sez.~\ref{sec:sock_name_services} per \func{getipnodebyname}; il valore di +\var{ai\_flags} può essere impostata con un OR aritmetico delle costanti di +tab.~\ref{tab:ai_flags_values}, ciascuna delle quali identifica un bit della +maschera. + +Nella seconda parte della tabella si sono riportati i valori delle costanti +aggiunte a partire dalle \acr{glibc} 2.3.4 per gestire la +internazionalizazione dei nomi a dominio (IDN o \textit{Internationalized + Domain Names}) secondo quanto specificato +nell'\href{http://www.ietf.org/rfc/rfc3490.txt}{RFC~3490} (potendo cioè usare +codifiche di caratteri che consentono l'espressione di nomi a dominio in +qualunque lingua). + +Come accennato passando un valore \val{NULL} per l'argomento \param{hints} si +effettua una risuluzione generica, equivalente ad aver impostato un valore +nullo per \var{ai\_family} e \var{ai\_socktype}, un valore \const{AF\_UNSPEC} +per \var{ai\_family} e il valore \code{(AI\_V4MAPPED|AI\_ADDRCONFIG)} per +\var{ai\_flags}. La funzione restituisce un valore nullo in caso di successo, o un codice in caso di errore. I valori usati come codice di errore sono riportati in @@ -1490,11 +1558,21 @@ corrispondente è riportato tramite \var{errno}. \textbf{Costante} & \textbf{Significato} \\ \hline \hline + \constd{EAI\_ADDRFAMILY}& La richiesta non ha nessun indirizzo di rete + per la famiglia di indirizzi specificata. \\ + \constd{EAI\_AGAIN} & Il DNS ha restituito un errore di risoluzione + temporaneo, si può ritentare in seguito. \\ + \constd{EAI\_BADFLAGS}& Il campo \var{ai\_flags} contiene dei valori non + validi per i flag o si è richiesto + \const{AI\_CANONNAME} con \param{name} nullo. \\ + \constd{EAI\_FAIL} & Il DNS ha restituito un errore di risoluzione + permanente. \\ \constd{EAI\_FAMILY} & La famiglia di indirizzi richiesta non è supportata. \\ - \constd{EAI\_SOCKTYPE}& Il tipo di socket richiesto non è supportato. \\ - \constd{EAI\_BADFLAGS}& Il campo \var{ai\_flags} contiene dei valori non - validi. \\ + \constd{EAI\_MEMORY} & È stato impossibile allocare la memoria necessaria + alle operazioni. \\ + \constd{EAI\_NODATA} & La macchina specificata esiste, ma non ha nessun + indirizzo di rete definito. \\ \constd{EAI\_NONAME} & Il nome a dominio o il servizio non sono noti, viene usato questo errore anche quando si specifica il valore \val{NULL} per entrambi gli argomenti @@ -1502,16 +1580,7 @@ corrispondente è riportato tramite \var{errno}. \constd{EAI\_SERVICE} & Il servizio richiesto non è disponibile per il tipo di socket richiesto, anche se può esistere per altri tipi di socket. \\ - \constd{EAI\_ADDRFAMILY}& La rete richiesta non ha nessun indirizzo di rete - per la famiglia di indirizzi specificata. \\ - \constd{EAI\_NODATA} & La macchina specificata esiste, ma non ha nessun - indirizzo di rete definito. \\ - \constd{EAI\_MEMORY} & È stato impossibile allocare la memoria necessaria - alle operazioni. \\ - \constd{EAI\_FAIL} & Il DNS ha restituito un errore di risoluzione - permanente. \\ - \constd{EAI\_AGAIN} & Il DNS ha restituito un errore di risoluzione - temporaneo, si può ritentare in seguito. \\ + \constd{EAI\_SOCKTYPE}& Il tipo di socket richiesto non è supportato. \\ \constd{EAI\_SYSTEM} & C'è stato un errore di sistema, si può controllare \var{errno} per i dettagli. \\ % \hline @@ -1529,35 +1598,36 @@ corrispondente è riportato tramite \var{errno}. \end{table} Come per i codici di errore di \func{gethostbyname} anche in questo caso è -fornita una apposita funzione, analoga di \func{strerror}, che consente di -utilizzarli direttamente per stampare a video un messaggio esplicativo; la -funzione è \funcd{gai\_strerror} ed il suo prototipo è: -\begin{functions} - \headdecl{netdb.h} - - \funcdecl{const char *gai\_strerror(int errcode)} +fornita una apposita funzione, simile a \func{strerror}, che consente di +utilizzare direttamente il codice restituito dalla funzione per stampare a +video un messaggio esplicativo; la funzione è \funcd{gai\_strerror} ed il suo +prototipo è: - Fornisce il messaggio corrispondente ad un errore di \func{getaddrinfo}. +\begin{funcproto}{ +\fhead{netdb.h} +\fdecl{const char *gai\_strerror(int errcode)} +\fdesc{Fornisce il messaggio corrispondente ad un errore di \func{getaddrinfo}.} +} - \bodydesc{La funzione restituisce il puntatore alla stringa contenente il - messaggio di errore.} -\end{functions} +{La funzione ritorna il puntatore alla stringa contenente il messaggio di + errore.} +\end{funcproto} La funzione restituisce un puntatore alla stringa contenente il messaggio corrispondente dal codice di errore \param{errcode} ottenuto come valore di ritorno di \func{getaddrinfo}. La stringa è allocata staticamente, ma essendo -costante, ed accessibile in sola lettura, questo non comporta nessun problema -di rientranza della funzione. +costante ed accessibile in sola lettura, la funzione è rientrante. Dato che ad un certo nome a dominio possono corrispondere più indirizzi IP (sia IPv4 che IPv6), e che un certo servizio può essere fornito su protocolli e tipi di socket diversi, in generale, a meno di non aver eseguito una selezione specifica attraverso l'uso di \param{hints}, si otterrà una diversa -struttura \struct{addrinfo} per ciascuna possibilità. Ad esempio se si -richiede la risoluzione del servizio \textit{echo} per l'indirizzo -\texttt{www.truelite.it}, e si imposta \const{AI\_CANONNAME} per avere anche -la risoluzione del nome canonico, si avrà come risposta della funzione la -lista illustrata in fig.~\ref{fig:sock_addrinfo_list}. +struttura \struct{addrinfo} per ciascuna possibilità. + +Ad esempio se si richiede la risoluzione del servizio \textit{echo} per +l'indirizzo \texttt{www.truelite.it}, e si imposta \const{AI\_CANONNAME} per +avere anche la risoluzione del nome canonico, si avrà come risposta della +funzione la lista illustrata in fig.~\ref{fig:sock_addrinfo_list}. \begin{figure}[!htb] \centering @@ -1575,7 +1645,7 @@ gestita l'eventuale inizializzazione dell'argomento \var{hints} per restringere le ricerche su protocolli, tipi di socket o famiglie di indirizzi, è disponibile nel file \texttt{mygetaddr.c} dei sorgenti allegati alla guida. -\begin{figure}[!htbp] +\begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{\codesamplewidth} \includecodesample{listati/mygetaddr.c} @@ -1604,8 +1674,8 @@ puntatore valido. La selezione principale è fatta sul campo \var{ai\_family}, che stabilisce a quale famiglia di indirizzi fa riferimento la struttura in esame. Le possibilità sono due, un indirizzo IPv4 o IPv6, se nessuna delle due si verifica si provvede (\texttt{\small 27--30}) a stampare un messaggio di -errore ed uscire.\footnote{questa eventualità non dovrebbe mai verificarsi, - almeno fintanto che la funzione \func{getaddrinfo} lavora correttamente.} +errore ed uscire (questa eventualità non dovrebbe comunque mai verificarsi, +almeno fintanto che la funzione \func{getaddrinfo} lavora correttamente). Per ciascuno delle due possibili famiglie di indirizzi si estraggono le informazioni che poi verranno stampate alla fine del ciclo (\texttt{\small @@ -1628,7 +1698,7 @@ puntatore al campo contenente l'indirizzo IP nella struttura puntata dal campo sono presenti direttamente i valori finali, per l'uso con \func{inet\_ntop} occorre comunque passare un puntatore agli stessi (ed il costrutto \code{\&addr6->sin6\_addr} è corretto in quanto l'operatore \texttt{->} ha - on questo caso precedenza su \texttt{\&}).} + in questo caso precedenza su \texttt{\&}).} Una volta estratte dalla struttura \struct{addrinfo} tutte le informazioni relative alla risoluzione richiesta e stampati i relativi valori, l'ultimo @@ -1644,8 +1714,8 @@ nello stesso ordine in cui vengono inviati dal server DNS. In particolare nulla garantisce che vengano forniti prima i dati relativi ai servizi di un determinato protocollo o tipo di socket, se ne sono presenti di diversi. Se allora utilizziamo il nostro programma potremo verificare il risultato: -\begin{Verbatim} -[piccardi@gont sources]$ ./mygetaddr -c gapil.truelite.it echo +\begin{Console} +[piccardi@gont sources]$ \textbf{./mygetaddr -c gapil.truelite.it echo} Canonical name sources2.truelite.it IPv4 address: Indirizzo 62.48.34.25 @@ -1655,28 +1725,30 @@ IPv4 address: Indirizzo 62.48.34.25 Protocollo 17 Porta 7 -\end{Verbatim} +\end{Console} %$ Una volta estratti i risultati dalla \textit{linked list} puntata da \param{res} se questa non viene più utilizzata si dovrà avere cura di disallocare opportunamente tutta la memoria, per questo viene fornita l'apposita funzione \funcd{freeaddrinfo}, il cui prototipo è: -\begin{functions} - \headdecl{netdb.h} - \funcdecl{void freeaddrinfo(struct addrinfo *res)} - Libera la memoria allocata da una precedente chiamata a \func{getaddrinfo}. +\begin{funcproto}{ +\fhead{netdb.h} +\fdecl{void freeaddrinfo(struct addrinfo *res)} +\fdesc{Libera la memoria allocata da una precedente chiamata a \func{getaddrinfo}.} +} - \bodydesc{La funzione non restituisce nessun codice di errore.} -\end{functions} +{La funzione non restituisce nessun codice di errore.} +\end{funcproto} La funzione prende come unico argomento il puntatore \param{res}, ottenuto da una precedente chiamata a \func{getaddrinfo}, e scandisce la lista delle strutture per liberare tutta la memoria allocata. Dato che la funzione non ha valori di ritorno deve essere posta molta cura nel passare un valore valido -per \param{res}. +per \param{res} ed usare un indirizzo non valido o già liberato può avere +conseguenze non prevedibili. Si tenga presente infine che se si copiano i risultati da una delle strutture \struct{addrinfo} restituite nella lista indicizzata da \param{res}, occorre @@ -1690,19 +1762,20 @@ eseguire la risoluzione inversa e determinare nomi di servizi e di dominio dati i rispettivi valori numerici. La funzione che sostituisce le varie \func{gethostbyname}, \func{getipnodebyname} e \func{getservbyname} è \funcd{getnameinfo}, ed il suo prototipo è: -\begin{functions} - \headdecl{sys/socket.h} - \headdecl{netdb.h} - - \funcdecl{int getnameinfo(const struct sockaddr *sa, socklen\_t salen, char - *host, size\_t hostlen, char *serv, size\_t servlen, int flags)} - Risolve il contenuto di una struttura degli indirizzi in maniera - indipendente dal protocollo. +\begin{funcproto}{ +\fhead{netdb.h} +\fhead{sys/socket.h} +\fdecl{int getnameinfo(const struct sockaddr *sa, socklen\_t salen, \\ +\phantom{int getnameinfo(}char *host, size\_t hostlen, char *serv, size\_t +servlen, int flags)} +\fdesc{Effettua una risoluzione di un indirizzo di rete in maniera + indipendente dal protocollo.} +} - \bodydesc{La funzione restituisce 0 in caso di successo e un codice di - errore diverso da zero altrimenti.} -\end{functions} +{La funzione ritorna $0$ in caso di successo e un codice di errore diverso da + zero per un errore.} +\end{funcproto} La principale caratteristica di \func{getnameinfo} è che la funzione è in grado di eseguire una risoluzione inversa in maniera indipendente dal @@ -1714,36 +1787,47 @@ IPv6, la cui dimensione deve comunque essere specificata con l'argomento I risultati della funzione saranno restituiti nelle due stringhe puntate da \param{host} e \param{serv}, che dovranno essere state precedentemente allocate per una lunghezza massima che deve essere specificata con gli altri -due argomenti \param{hostlen} e \param{servlen}. Si può, quando non si è -interessati ad uno dei due, passare il valore \val{NULL} come argomento, -così che la corrispondente informazione non verrà richiesta. Infine l'ultimo +due argomenti \param{hostlen} e \param{servlen}. Quando non si è +interessati ad uno dei due, si può passare il valore \val{NULL} come argomento, +così che la corrispondente informazione non venga richiesta. Infine l'ultimo argomento \param{flags} è una maschera binaria i cui bit consentono di impostare le modalità con cui viene eseguita la ricerca, e deve essere specificato attraverso l'OR aritmetico dei valori illustrati in -tab.~\ref{tab:getnameinfo_flags}. +tab.~\ref{tab:getnameinfo_flags}, nella seconda parte della tabella si sono +aggiunti i valori introdotto con le \acr{glibc} 2.3.4 per gestire la +internazionalizzione dei nomi a dominio. \begin{table}[!htb] \centering \footnotesize - \begin{tabular}[c]{|l|p{10cm}|} + \begin{tabular}[c]{|l|p{8cm}|} \hline \textbf{Costante} & \textbf{Significato} \\ \hline \hline + \constd{NI\_DGRAM} & Richiede che venga restituito il nome del + servizio su UDP invece che quello su TCP per quei + pichi servizi (porte 512-214) che soni diversi + nei due protocolli.\\ \constd{NI\_NOFQDN} & Richiede che venga restituita solo il nome della macchina all'interno del dominio al posto del nome completo (FQDN).\\ + \constd{NI\_NAMEREQD} & Richiede la restituzione di un errore se il nome + non può essere risolto.\\ \constd{NI\_NUMERICHOST}& Richiede che venga restituita la forma numerica dell'indirizzo (questo succede sempre se il nome non può essere ottenuto).\\ - \constd{NI\_NAMEREQD} & Richiede la restituzione di un errore se il nome - non può essere risolto.\\ \constd{NI\_NUMERICSERV}& Richiede che il servizio venga restituito in - forma numerica (attraverso il numero di porta).\\ - \constd{NI\_DGRAM} & Richiede che venga restituito il nome del - servizio su UDP invece che quello su TCP per quei - pichi servizi (porte 512-214) che soni diversi - nei due protocolli.\\ + forma numerica (attraverso il numero di + porta).\\ + \hline + \const{NI\_IDN} & Se specificato il nome restituito viene convertito usando la + localizzazione corrente, se necessario, nella + codifica IDN.\\ + \const{NI\_IDN\_ALLOW\_UNASSIGNED} & attiva il controllo + \texttt{IDNA\_ALLOW\_UNASSIGNED}.\\ + \const{NI\_AI\_IDN\_USE\_STD3\_ASCII\_RULES} & attiva il controllo + \texttt{IDNA\_USE\_STD3\_ASCII\_RULES}\\ \hline \end{tabular} \caption{Costanti associate ai bit dell'argomento \param{flags} della @@ -1779,7 +1863,7 @@ fig.~\ref{fig:sockconn_code}, il codice completo è nel file \file{SockUtil.c} dei sorgenti allegati alla guida, che contiene varie funzioni di utilità per l'uso dei socket. -\begin{figure}[!htbp] +\begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{\codesamplewidth} \includecodesample{listati/sockconn.c} @@ -1795,38 +1879,42 @@ cui sarà effettuata la risoluzione; seguono il protocollo da usare (da specificare con il valore numerico di \conffile{/etc/protocols}) ed il tipo di socket (al solito specificato con i valori illustrati in sez.~\ref{sec:sock_type}). La funzione ritorna il valore del file descriptor -associato al socket (un numero positivo) in caso di successo, o -1 in caso di -errore; per risolvere il problema di non poter passare indietro i valori di -ritorno di \func{getaddrinfo} contenenti i relativi codici di -errore\footnote{non si può avere nessuna certezza che detti valori siano - negativi, è questo è invece necessario per evitare ogni possibile ambiguità - nei confronti del valore di ritorno in caso di successo.} si sono stampati i -messaggi d'errore direttamente nella funzione. - -Una volta definite le variabili necessarie (\texttt{\small 3--5}) la funzione +associato al socket (un numero positivo) in caso di successo, o $-1$ in caso +di errore. + +Per risolvere il problema di non poter passare indietro i valori di ritorno di +\func{getaddrinfo} contenenti i relativi codici di errore si sono stampati i +messaggi d'errore direttamente nella funzione; infatti non si può avere +nessuna certezza che detti valori siano negativi e per cui stampare subito +l'errore diventa necessario per evitare ogni possibile ambiguità nei confronti +del valore di ritorno in caso di successo. + +Una volta definite le variabili occorrenti (\texttt{\small 3--5}) la funzione prima (\texttt{\small 6}) azzera il contenuto della struttura \var{hint} e poi provvede (\texttt{\small 7--9}) ad inizializzarne i valori necessari per la chiamata (\texttt{\small 10}) a \func{getaddrinfo}. Di quest'ultima si -controlla (\texttt{\small 12--16}) il codice di ritorno, in modo da stampare un -avviso di errore, azzerare \var{errno} ed uscire in caso di errore. Dato che -ad una macchina possono corrispondere più indirizzi IP, e di tipo diverso (sia -IPv4 che IPv6), mentre il servizio può essere in ascolto soltanto su uno solo -di questi, si provvede a tentare la connessione per ciascun indirizzo -restituito all'interno di un ciclo (\texttt{\small 18--40}) di scansione della -lista restituita da \func{getaddrinfo}, ma prima (\texttt{\small 17}) si salva -il valore del puntatore per poterlo riutilizzare alla fine per disallocare la -lista. +controlla (\texttt{\small 12--16}) il codice di ritorno, in modo da stampare +un avviso di errore, azzerare \var{errno} ed uscire in caso di errore. + +Dato che ad una macchina possono corrispondere più indirizzi IP, e di tipo +diverso (sia IPv4 che IPv6), mentre il servizio può essere in ascolto soltanto +su uno solo di questi, si provvede a tentare la connessione per ciascun +indirizzo restituito all'interno di un ciclo (\texttt{\small 18--40}) di +scansione della lista restituita da \func{getaddrinfo}, ma prima +(\texttt{\small 17}) si salva il valore del puntatore per poterlo riutilizzare +alla fine per disallocare la lista. Il ciclo viene ripetuto (\texttt{\small 18}) fintanto che si hanno indirizzi validi, ed inizia (\texttt{\small 19}) con l'apertura del socket; se questa fallisce si controlla (\texttt{\small 20}) se sono disponibili altri indirizzi, nel qual caso si passa al successivo (\texttt{\small 21}) e si riprende (\texttt{\small 22}) il ciclo da capo; se non ve ne sono si stampa -l'errore ritornando immediatamente (\texttt{\small 24--27}). Quando la -creazione del socket ha avuto successo si procede (\texttt{\small 29}) -direttamente con la connessione, di nuovo in caso di fallimento viene ripetuto -(\texttt{\small 30--38}) il controllo se vi sono o no altri indirizzi da -provare nella stessa modalità fatta in precedenza, aggiungendovi però in +l'errore ritornando immediatamente (\texttt{\small 24--27}). + +Quando la creazione del socket ha avuto successo si procede (\texttt{\small + 29}) direttamente con la connessione, di nuovo in caso di fallimento viene +ripetuto (\texttt{\small 30--38}) il controllo se vi sono o no altri indirizzi +da provare nella stessa modalità fatta in precedenza, aggiungendovi però in entrambi i casi (\texttt{\small 32} e (\texttt{\small 36}) la chiusura del socket precedentemente aperto, che non è più utilizzabile. @@ -1840,16 +1928,6 @@ ritornata contiene indirizzi IPv6 o IPv4, in quanto si fa uso direttamente dei dati relativi alle strutture degli indirizzi di \struct{addrinfo} che sono opachi rispetto all'uso della funzione \func{connect}. -\begin{figure}[!htbp] - \footnotesize \centering - \begin{minipage}[c]{\codesamplewidth} - \includecodesample{listati/TCP_echo_fifth.c} - \end{minipage} - \normalsize - \caption{Il nuovo codice per la connessione del client \textit{echo}.} - \label{fig:TCP_echo_fifth} -\end{figure} - Per usare questa funzione possiamo allora modificare ulteriormente il nostro programma client per il servizio \textit{echo}; in questo caso rispetto al codice usato finora per collegarsi (vedi fig.~\ref{fig:TCP_echo_client_1}) @@ -1861,7 +1939,25 @@ codice completo è nel file \file{TCP\_echo\_fifth.c} dei sorgenti allegati) consente di utilizzare come argomento del programma un nome a dominio al posto dell'indirizzo numerico, e può utilizzare sia indirizzi IPv4 che IPv6. -\begin{figure}[!htbp] +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/TCP_echo_fifth.c} + \end{minipage} + \normalsize + \caption{Il nuovo codice per la connessione del client \textit{echo}.} + \label{fig:TCP_echo_fifth} +\end{figure} + +La seconda funzione di ausilio che abbiamo creato è \texttt{sockbind}, il cui +corpo principale è riportato in fig.~\ref{fig:sockbind_code} (al solito il +sorgente completo è nel file \file{sockbind.c} dei sorgenti allegati alla +guida). Come si può notare la funzione è del tutto analoga alla precedente +\texttt{sockconn}, e prende gli stessi argomenti, però invece di eseguire una +connessione con \func{connect} si limita a chiamare \func{bind} per collegare +il socket ad una porta. + +\begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{\codesamplewidth} \includecodesample{listati/sockbind.c} @@ -1871,14 +1967,6 @@ dell'indirizzo numerico, e può utilizzare sia indirizzi IPv4 che IPv6. \label{fig:sockbind_code} \end{figure} -La seconda funzione di ausilio è \texttt{sockbind}, il cui corpo principale è -riportato in fig.~\ref{fig:sockbind_code} (al solito il sorgente completo è -nel file \file{sockbind.c} dei sorgenti allegati alla guida). Come si può -notare la funzione è del tutto analoga alla precedente \texttt{sockconn}, e -prende gli stessi argomenti, però invece di eseguire una connessione con -\func{connect} si limita a chiamare \func{bind} per collegare il socket ad una -porta. - Dato che la funzione è pensata per essere utilizzata da un server ci si può chiedere a quale scopo mantenere l'argomento \param{host} quando l'indirizzo di questo è usualmente noto. Si ricordi però quanto detto in @@ -1903,11 +1991,11 @@ identici, solo che si è sostituita (\texttt{\small 31}) la chiamata a (\texttt{\small 43--44}) della funzione è identica. Si noti come anche in questo caso si siano inserite le stampe degli errori -sullo standard error, nonostante la funzione possa essere invocata da un -demone. Nel nostro caso questo non è un problema in quanto se la funzione non -ha successo il programma deve uscire immediatamente prima di essere posto in -background, e può quindi scrivere gli errori direttamente sullo standard -error. +sullo \textit{standard error}, nonostante la funzione possa essere invocata da +un demone. Nel nostro caso questo non è un problema in quanto se la funzione +non ha successo il programma deve uscire immediatamente prima di essere posto +in background, e può quindi scrivere gli errori direttamente sullo +\textit{standard error}. \begin{figure}[!htbp] \footnotesize \centering @@ -1928,21 +2016,24 @@ che si cura anche della eventuale risoluzione di un indirizzo specifico sul quale si voglia far ascoltare il server. - \section{Le opzioni dei socket} \label{sec:sock_options} Benché dal punto di vista del loro uso come canali di trasmissione di dati i -socket siano trattati allo stesso modo dei file, ed acceduti tramite i file -descriptor, la normale interfaccia usata per la gestione dei file non è -sufficiente a poterne controllare tutte le caratteristiche, che variano tra -l'altro a seconda del loro tipo (e della relativa forma di comunicazione -sottostante). In questa sezione vedremo allora quali sono le funzioni dedicate -alla gestione delle caratteristiche specifiche dei vari tipi di socket, le -cosiddette \textit{socket options}. +socket vengano trattati allo stesso modo dei file, siano acceduti tramite i +file descriptor, e gestiti con le ordinarie funzioni di lettura e scrittura +dei file, l'interfaccia standard usata per la gestione dei file generici non è +comunque sufficiente a poterne controllare tutte le caratteristiche +specifiche, considerato poi che queste variano a seconda del tipo di socket (e +della relativa forma di comunicazione sottostante). + +In questa sezione vedremo allora quali sono le funzioni dedicate alla gestione +delle caratteristiche specifiche dei vari tipi di socket, le cosiddette +\textit{socket options}, ma soprattutto analizzaremo quali sono queste opzioni +e quali caretteristiche e comportamenti dei socket permettono di controllare. -\subsection{Le funzioni \func{setsockopt} e \func{getsockopt}} +\subsection{Le funzioni di gestione delle opzioni dei socket} \label{sec:sock_setsockopt} Le varie caratteristiche dei socket possono essere gestite attraverso l'uso di @@ -1950,16 +2041,17 @@ due funzioni generiche che permettono rispettivamente di impostarle e di recuperarne il valore corrente. La prima di queste due funzioni, quella usata per impostare le \textit{socket options}, è \funcd{setsockopt}, ed il suo prototipo è: -\begin{functions} - \headdecl{sys/socket.h} - \headdecl{sys/types.h} - \funcdecl{int setsockopt(int sock, int level, int optname, const void +\begin{funcproto}{ +\fhead{sys/socket.h} +\fhead{sys/types.h} +\fdecl{int setsockopt(int sock, int level, int optname, const void *optval, socklen\_t optlen)} - Imposta le opzioni di un socket. +\fdesc{Imposta le opzioni di un socket.} +} - \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di - errore, nel qual caso \var{errno} assumerà i valori: +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EBADF}] il file descriptor \param{sock} non è valido. \item[\errcode{EFAULT}] l'indirizzo \param{optval} non è valido. @@ -1970,8 +2062,7 @@ prototipo è: un socket. \end{errlist} } -\end{functions} - +\end{funcproto} Il primo argomento della funzione, \param{sock}, indica il socket su cui si intende operare; per indicare l'opzione da impostare si devono usare i due diff --git a/socket.tex b/socket.tex index 2d31d6c..ceb724c 100644 --- a/socket.tex +++ b/socket.tex @@ -199,36 +199,36 @@ comunicazione. \textbf{Nome}&\textbf{Valore}&\textbf{Utilizzo}&\textbf{Man page} \\ \hline \hline - \constd{PF\_UNSPEC} & 0& Non specificato & \\ - \constd{PF\_LOCAL} & 1& Local communication & unix(7) \\ - \constd{PF\_UNIX}, \constd{PF\_FILE}&1&Sinonimi di \const{PF\_LOCAL}& \\ - \constd{PF\_INET} & 2& IPv4 Internet protocols & ip(7) \\ - \constd{PF\_AX25} & 3& Amateur radio AX.25 protocol & \\ - \constd{PF\_IPX} & 4& IPX - Novell protocols & \\ - \constd{PF\_APPLETALK}& 5& Appletalk & ddp(7) \\ - \constd{PF\_NETROM} & 6& Amateur radio NetROM & \\ - \constd{PF\_BRIDGE} & 7& Multiprotocol bridge & \\ - \constd{PF\_ATMPVC} & 8& Access to raw ATM PVCs & \\ - \constd{PF\_X25} & 9& ITU-T X.25 / ISO-8208 protocol& x25(7) \\ - \constd{PF\_INET6} &10& IPv6 Internet protocols & ipv6(7) \\ - \constd{PF\_ROSE} &11& Amateur Radio X.25 PLP & \\ - \constd{PF\_DECnet} &12& Reserved for DECnet project & \\ - \constd{PF\_NETBEUI} &13& Reserved for 802.2LLC project & \\ - \constd{PF\_SECURITY} &14& Security callback pseudo AF & \\ - \constd{PF\_KEY} &15& PF\_KEY key management API & \\ - \constd{PF\_NETLINK} &16& Kernel user interface device & netlink(7) \\ - \constd{PF\_ROUTE} &16& Sinonimo di \const{PF\_NETLINK} emula BSD.&\\ - \constd{PF\_PACKET} &17& Low level packet interface & packet(7) \\ - \constd{PF\_ASH} &18& Ash & \\ - \constd{PF\_ECONET} &19& Acorn Econet & \\ - \constd{PF\_ATMSVC} &20& ATM SVCs & \\ - \constd{PF\_SNA} &22& Linux SNA Project & \\ - \constd{PF\_IRDA} &23& IRDA socket (infrarossi) & \\ - \constd{PF\_PPPOX} &24& PPPoX socket & \\ - \constd{PF\_WANPIPE} &25& Wanpipe API socket & \\ - \constd{PF\_LLC} &26& Linux LLC & \\ - \constd{PF\_CAN} &29& Controller Are Network & \\ - \constd{PF\_BLUETOOTH}&31& Bluetooth socket & \\ + \constd{AF\_UNSPEC} & 0& Non specificato & \\ + \constd{AF\_LOCAL} & 1& Local communication & unix(7) \\ + \constd{AF\_UNIX}, \constd{AF\_FILE}&1&Sinonimi di \const{AF\_LOCAL}& \\ + \constd{AF\_INET} & 2& IPv4 Internet protocols & ip(7) \\ + \constd{AF\_AX25} & 3& Amateur radio AX.25 protocol & \\ + \constd{AF\_IPX} & 4& IPX - Novell protocols & \\ + \constd{AF\_APPLETALK}& 5& Appletalk & ddp(7) \\ + \constd{AF\_NETROM} & 6& Amateur radio NetROM & \\ + \constd{AF\_BRIDGE} & 7& Multiprotocol bridge & \\ + \constd{AF\_ATMPVC} & 8& Access to raw ATM PVCs & \\ + \constd{AF\_X25} & 9& ITU-T X.25 / ISO-8208 protocol& x25(7) \\ + \constd{AF\_INET6} &10& IPv6 Internet protocols & ipv6(7) \\ + \constd{AF\_ROSE} &11& Amateur Radio X.25 PLP & \\ + \constd{AF\_DECnet} &12& Reserved for DECnet project & \\ + \constd{AF\_NETBEUI} &13& Reserved for 802.2LLC project & \\ + \constd{AF\_SECURITY} &14& Security callback pseudo AF & \\ + \constd{AF\_KEY} &15& AF\_KEY key management API & \\ + \constd{AF\_NETLINK} &16& Kernel user interface device & netlink(7) \\ + \constd{AF\_ROUTE} &16& Sinonimo di \const{AF\_NETLINK} emula BSD.&\\ + \constd{AF\_PACKET} &17& Low level packet interface & packet(7) \\ + \constd{AF\_ASH} &18& Ash & \\ + \constd{AF\_ECONET} &19& Acorn Econet & \\ + \constd{AF\_ATMSVC} &20& ATM SVCs & \\ + \constd{AF\_SNA} &22& Linux SNA Project & \\ + \constd{AF\_IRDA} &23& IRDA socket (infrarossi) & \\ + \constd{AF\_PPPOX} &24& PPPoX socket & \\ + \constd{AF\_WANPIPE} &25& Wanpipe API socket & \\ + \constd{AF\_LLC} &26& Linux LLC & \\ + \constd{AF\_CAN} &29& Controller Are Network & \\ + \constd{AF\_BLUETOOTH}&31& Bluetooth socket & \\ \hline \end{tabular} \caption{Famiglie di protocolli definiti in Linux.} diff --git a/sources/mygetaddr.c b/sources/mygetaddr.c index c34d15d..67a570d 100644 --- a/sources/mygetaddr.c +++ b/sources/mygetaddr.c @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) * Init variables */ memset(&hint, 0, sizeof(hint)); - hint.ai_family = PF_UNSPEC; + hint.ai_family = AF_UNSPEC; /* * Input section: decode command line parameters * Use getopt function @@ -117,11 +117,11 @@ int main(int argc, char *argv[]) case 'v': /* set address type */ j = strtol(optarg, NULL, 10); if (j == 4) { - hint.ai_family = PF_INET; + hint.ai_family = AF_INET; break; } if (j == 6) { - hint.ai_family = PF_INET6; + hint.ai_family = AF_INET6; break; } printf("Wrong IP protocol version, use 4 o 6\n\n"); @@ -164,13 +164,13 @@ int main(int argc, char *argv[]) ptr = res; /* init list pointer */ printf("Canonical name %s\n", ptr->ai_canonname); /* print cname */ while (ptr != NULL) { /* loop on list */ - if (ptr->ai_family == PF_INET) { /* if IPv4 */ + if (ptr->ai_family == AF_INET) { /* if IPv4 */ printf("IPv4 address: \n"); addr = (struct sockaddr_in *) ptr->ai_addr; /* address */ port = ntohs(addr->sin_port); /* port */ string = inet_ntop(addr->sin_family, &addr->sin_addr, buffer, sizeof(buffer)); - } else if (ptr->ai_family == PF_INET6) { /* if IPv6 */ + } else if (ptr->ai_family == AF_INET6) { /* if IPv6 */ printf("IPv6 address: \n"); addr6 = (struct sockaddr_in6 *) ptr->ai_addr; /* address */ port = ntohs(addr6->sin6_port); /* port */