X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=sockctrl.tex;h=0364dd7732436b19f853386691c46c8433b16efe;hp=f371f92dfc39e017dea8faba069a4b291552137b;hb=65da2d8d7f73f58e1e3e6f867d91f8bb7cf7bf86;hpb=fae1b357c38b50ce788f3f06f7153b1ce4ee57df diff --git a/sockctrl.tex b/sockctrl.tex index f371f92..0364dd7 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -87,9 +87,9 @@ dominio, e prevedeva solo l'utilizzo del DNS e del file statico Per questo aspetto il file di configurazione principale del sistema è \conffile{/etc/resolv.conf} che contiene in sostanza l'elenco degli indirizzi -IP dei server DNS da contattare; a questo si affianca il file -\conffile{/etc/host.conf} il cui scopo principale è indicare l'ordine in cui -eseguire la risoluzione dei nomi (se usare prima i valori di +IP dei server DNS da contattare; a questo si affiancava (fino alle \acr{glibc} +2.4) il file \conffile{/etc/host.conf} il cui scopo principale era indicare +l'ordine in cui eseguire la risoluzione dei nomi (se usare prima i valori di \conffile{/etc/hosts} o quelli del DNS). Tralasciamo i dettagli relativi alle varie direttive che possono essere usate in questi file, che si trovano nelle rispettive pagine di manuale. @@ -182,6 +182,9 @@ 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. +Pertanto nelle versioni recenti delle librerie è questo file e non +\conffile{/etc/host.conf} a indicare l'ordine con cui si esegue la +risoluzione dei nomi. Ogni servizio è specificato a sua volta da un nome, come \texttt{file}, \texttt{dns}, \texttt{db}, ecc. che identifica la libreria dinamica che @@ -202,7 +205,7 @@ sezioni successive. \itindend{Name~Service~Switch~(NSS)} -\subsection{Le funzioni di interrogazione del \textit{resolver}} +\subsection{Le funzioni di interrogazione del DNS} \label{sec:sock_resolver_functions} Prima di trattare le funzioni usate normalmente nella risoluzione dei nomi a @@ -251,9 +254,8 @@ informazione che un server DNS fornisce normalmente. L'esistenza di vari tipi di informazioni è un altro dei motivi per cui il \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 è: +server DNS, tutte nella forma \texttt{res\_}\textsl{\texttt{nome}}. La prima +di queste funzioni è \funcd{res\_init}, il cui prototipo è: \begin{funcproto}{ \fhead{netinet/in.h} @@ -266,40 +268,41 @@ prototipo è: } \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, -gli indirizzi dei server DNS da contattare e l'ordine delle ricerche; se non -sono specificati server verrà utilizzato l'indirizzo locale, e se non è -definito un dominio di default sarà usato quello associato con l'indirizzo -locale (ma questo può essere sovrascritto con l'uso della variabile di -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. +La funzione legge il contenuto dei file di configurazione per impostare il +dominio di default, gli indirizzi dei server DNS da contattare e l'ordine +delle ricerche; se non sono specificati server verrà utilizzato l'indirizzo +locale, e se non è definito un dominio di default sarà usato quello associato +con l'indirizzo locale (ma questo può essere sovrascritto con l'uso della +variabile di ambiente \envvar{LOCALDOMAIN}). In genere non è necessario +eseguire questa funzione esplicitamente, in quanto viene automaticamente +chiamata la prima volta che si esegue una qualunque delle altre. 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: +campi di una apposita struttura. Questa struttura viene definita in +\headfiled{resolv.h} e mantenuta nella variabile globale \var{\_res}, che +viene utilizzata internamente da tutte le funzioni dell'interfaccia. Questo +consente anche di accedere direttamente al contenuto della variabile +all'interno di un qualunque programma, una volta che la sia opportunamente +dichiarata con: \includecodesnip{listati/resolv_option.c} -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: +Dato che l'uso di una variabile globale rende tutte le funzioni +dell'interfaccia classica non rientranti, queste sono state deprecate in +favore di una nuova interfaccia in cui esse sono state sostituite da +altrettante nuove funzioni, il cui nome è ottenuto apponendo una +``\texttt{n}'' al nome di quella tradizionale (cioè nella forma +\texttt{res\_n\textsl{nome}}). Tutte le nuove funzioni sono identiche alle +precedenti, ma hanno un primo argomento aggiuntivo, \param{statep}, puntatore +ad una struttura dello stesso tipo di \var{\_res}. Questo consente di usare +una variabile locale per mantenere lo stato del \textit{resolver}, rendendo le +nuove funzioni rientranti. In questo caso per poter utilizzare il nuovo +argomento occorrerà una opportuna dichiarazione del relativo 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 è: + +Così la nuova funzione utilizzata per inizializzare il \textit{resolver} (che +come la precedente viene chiamata automaticamente da tutte altre funzioni) è +\funcd{res\_ninit}, ed il suo prototipo è: \begin{funcproto}{ \fhead{netinet/in.h} @@ -313,12 +316,14 @@ come la precedente viene chiamata automaticamente dalle altre funzioni) è \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}. +della struttura (\var{\_res} o la variabile puntata da \param{statep}) 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} (o l'equivalente della variabile puntata +da\param{statep}), una maschera binaria che contiene una serie di bit che +esprimono le opzioni che permettono di controllare il comportamento del +\textit{resolver}. \begin{table}[htb] \centering @@ -334,8 +339,7 @@ comportamento del \textit{resolver}. \constd{RES\_AAONLY} & Accetta solo risposte autoritative.\\ \constd{RES\_USEVC} & Usa connessioni TCP per contattare i server invece che l'usuale UDP.\\ - \constd{RES\_PRIMARY} & Interroga soltanto server DNS primari. - \\ + \constd{RES\_PRIMARY} & Interroga soltanto server DNS primari.\\ \constd{RES\_IGNTC} & Ignora gli errori di troncamento, non ritenta la richiesta con una connessione TCP.\\ \constd{RES\_RECURSE} & Imposta il bit che indica che si desidera @@ -345,7 +349,7 @@ comportamento del \textit{resolver}. contengono cioè un ``\texttt{.}'').\\ \constd{RES\_STAYOPEN} & Usato con \const{RES\_USEVC} per mantenere aperte le connessioni TCP fra interrogazioni - diverse. \\ + diverse.\\ \constd{RES\_DNSRCH} & Se attivo \func{res\_search} esegue le ricerche di nomi di macchine nel dominio corrente o nei domini ad esso sovrastanti.\\ @@ -373,9 +377,9 @@ comportamento del \textit{resolver}. Per utilizzare questa funzionalità per modificare le impostazioni direttamente da programma occorrerà impostare un opportuno valore per questo campo ed -invocare esplicitamente \func{res\_init}, dopo di che le altre funzioni -prenderanno le nuove impostazioni. Le costanti che definiscono i vari bit di -questo campo, ed il relativo significato sono illustrate in +invocare esplicitamente \func{res\_init} o \func{res\_ninit}, dopo di che le +altre funzioni prenderanno le nuove impostazioni. Le costanti che definiscono +i vari bit di questo campo, ed il relativo significato sono illustrate in tab.~\ref{tab:resolver_option}; trattandosi di una maschera binaria un valore deve essere espresso con un opportuno OR aritmetico di dette costanti; ad esempio il valore di default delle opzioni, espresso dalla costante @@ -466,8 +470,8 @@ 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 costanti che identificano dette classi, da usare come valore per l'argomento \param{class} delle precedenti funzioni, sono riportate in -tab.~\ref{tab:DNS_address_class}.\footnote{esisteva in realtà anche una classe - \constd{C\_CSNET} per la omonima rete, ma è stata dichiarata obsoleta.} +tab.~\ref{tab:DNS_address_class} (esisteva in realtà anche una classe +\constd{C\_CSNET} per la omonima rete, ma è stata dichiarata obsoleta). \begin{table}[htb] \centering @@ -493,7 +497,7 @@ tab.~\ref{tab:DNS_address_class}.\footnote{esisteva in realtà anche una classe Come accennato le tipologie di dati che sono mantenibili su un server DNS sono diverse, ed a ciascuna di essa corrisponde un diverso tipo di \textit{resource record}. L'elenco delle costanti, ripreso dai file di dichiarazione - \headfiled{arpa/nameser.h} e \headfiled{arpa/nameser\_compat.h}, che +\headfiled{arpa/nameser.h} e \headfiled{arpa/nameser\_compat.h}, che definiscono i valori che si possono usare per l'argomento \param{type} per specificare il tipo di \textit{resource record} da richiedere è riportato in tab.~\ref{tab:DNS_record_type}; le costanti (tolto il \texttt{T\_} iniziale) @@ -504,7 +508,7 @@ BIND,\footnote{BIND, acronimo di \textit{Berkley Internet Name Domain}, è una (cioè i suoi \textit{resource record} vengono mantenuti in quelli che sono usualmente chiamati \textsl{file di zona}, e in essi ciascun tipo di dominio è identificato da un nome che è appunto identico a quello delle costanti di - tab.~\ref{tab:DNS_record_type} senza il \texttt{T\_} iniziale.} e che + tab.~\ref{tab:DNS_record_type} senza il \texttt{T\_} iniziale.} e che normalmente sono anche usati come nomi per indicare i record. \begin{table}[!htb] @@ -594,7 +598,7 @@ indicarli si è usata la notazione dei file di zona di BIND): Come accennato in caso di successo le due funzioni di richiesta restituiscono il risultato della interrogazione al server, in caso di insuccesso l'errore -invece viene segnalato da un valore di ritorno pari a -1, ma in questo caso, +invece viene segnalato da un valore di ritorno pari a $-1$, ma in questo caso, non può essere utilizzata la variabile \var{errno} per riportare un codice di errore, in quanto questo viene impostato per ciascuna delle chiamate al sistema utilizzate dalle funzioni del \textit{resolver}, non avrà alcun @@ -612,7 +616,7 @@ tab.~\ref{tab:h_errno_values}. \begin{table}[!htb] \centering \footnotesize - \begin{tabular}[c]{|l|p{11cm}|} + \begin{tabular}[c]{|l|p{9cm}|} \hline \textbf{Costante} & \textbf{Significato} \\ \hline @@ -635,45 +639,34 @@ tab.~\ref{tab:h_errno_values}. \label{tab:h_errno_values} \end{table} -Insieme alla nuova variabile vengono definite anche due nuove funzioni per +Insieme alla nuova variabile vengono definite anche delle nuove funzioni per stampare l'errore a video, analoghe a quelle di sez.~\ref{sec:sys_strerror} per \var{errno}, ma che usano il valore di \var{h\_errno}; la prima è \funcd{herror} ed il suo prototipo è: - -\begin{funcproto}{ +{\centering +\vspace{3pt} +\begin{funcbox}{ \fhead{netdb.h} \fdecl{void herror(const char *string)} \fdesc{Stampa un errore di risoluzione.} } - -{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual - caso \var{errno} assumerà uno dei valori: - \begin{errlist} - \end{errlist} - ed inoltre - nel loro significato generico.} -\end{funcproto} - - - -\begin{functions} -\headdecl{ -\funcdecl{ - -. -\end{functions} +\end{funcbox}} La funzione è l'analoga di \func{perror} e stampa sullo 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 è: -\begin{functions} -\headdecl{netdb.h} -\funcdecl{const char *hstrerror(int err)} -Restituisce una stringa corrispondente ad un errore di risoluzione. -\end{functions} +{\centering +\vspace{3pt} +\begin{funcbox}{ +\fhead{netdb.h} +\fdecl{const char *hstrerror(int err)} +\fdesc{Restituisce una stringa corrispondente ad un errore di risoluzione.} +} +\end{funcbox}} + \noindent che, come l'analoga \func{strerror}, restituisce una stringa con un messaggio di errore già formattato, corrispondente al codice passato come argomento (che si presume sia dato da \var{h\_errno}). @@ -681,23 +674,30 @@ argomento (che si presume sia dato da \var{h\_errno}). \itindend{resolver} -\subsection{La risoluzione dei nomi a dominio} +\subsection{La vecchia interfaccia per la risoluzione dei nomi a dominio} \label{sec:sock_name_services} La principale funzionalità del \textit{resolver} resta quella di risolvere i nomi a dominio in indirizzi IP, per cui non ci dedicheremo oltre alle funzioni -di richiesta generica ed esamineremo invece le funzioni a questo dedicate. La -prima funzione è \funcd{gethostbyname} il cui scopo è ottenere l'indirizzo di -una stazione noto il suo nome a dominio, il suo prototipo è: -\begin{prototype}{netdb.h} -{struct hostent *gethostbyname(const char *name)} +per effetture delle richieste generiche al DNS ed esamineremo invece le +funzioni del \textit{resolver} dedicate specificamente a questo. Tratteremo in +questa sezione l'interfaccia tradizionale, che ormai è deprecata, mentre +vedremo nella sezione seguente la nuova interfaccia. + +La prima funzione dell'interfaccia tradizionale è \funcd{gethostbyname} il cui +scopo è ottenere l'indirizzo di una stazione noto il suo nome a dominio, il +suo prototipo è: -Determina l'indirizzo associato al nome a dominio \param{name}. +\begin{funcproto}{ +\fhead{netdb.h} +\fdecl{struct hostent *gethostbyname(const char *name)} +\fdesc{Determina l'indirizzo associato ad un nome a dominio.} +} -\bodydesc{La funzione restituisce in caso di successo il puntatore ad una +{La funzione ritorna il puntatore ad una struttura di tipo \struct{hostent} contenente i dati associati al nome a - dominio, o un puntatore nullo in caso di errore.} -\end{prototype} + dominio in caso di successo o un puntatore nullo per un errore.} +\end{funcproto} La funzione prende come argomento una stringa \param{name} contenente il nome a dominio che si vuole risolvere, in caso di successo i dati ad esso relativi @@ -744,35 +744,36 @@ si limiterà a copiare la stringa nel campo \var{h\_name} ed a creare la corrispondente struttura \var{in\_addr} da indirizzare con \code{h\_addr\_list[0]}. -Con l'uso di \func{gethostbyname} normalmente si ottengono solo gli indirizzi -IPv4, se si vogliono ottenere degli indirizzi IPv6 occorrerà prima impostare -l'opzione \const{RES\_USE\_INET6} nel campo \texttt{\_res.options} e poi -chiamare \func{res\_init} (vedi sez.~\ref{sec:sock_resolver_functions}) per -modificare le opzioni del \textit{resolver}; dato che questo non è molto -comodo è stata definita\footnote{questa è una estensione fornita dalle - \acr{glibc}, disponibile anche in altri sistemi unix-like.} un'altra -funzione, \funcd{gethostbyname2}, il cui prototipo è: -\begin{functions} - \headdecl{netdb.h} - \headdecl{sys/socket.h} - \funcdecl{struct hostent *gethostbyname2(const char *name, int af)} +Con l'uso di \func{gethostbyname} si ottengono solo gli indirizzi IPv4, se si +vogliono ottenere degli indirizzi IPv6 occorrerà prima impostare l'opzione +\const{RES\_USE\_INET6} nel campo \texttt{\_res.options} e poi chiamare +\func{res\_init} (vedi sez.~\ref{sec:sock_resolver_functions}) per modificare +le opzioni del \textit{resolver}; dato che questo non è molto comodo è stata +definita (è una estensione fornita dalle \acr{glibc}, disponibile anche in +altri sistemi unix-like) un'altra funzione, \funcd{gethostbyname2}, il cui +prototipo è: -Determina l'indirizzo di tipo \param{af} associato al nome a dominio -\param{name}. +\begin{funcproto}{ +\fhead{netdb.h} +\fhead{sys/socket.h} +\fdecl{struct hostent *gethostbyname2(const char *name, int af)} +\fdesc{Determina l'indirizzo del tipo scelto associato ad un nome a dominio.} +} -\bodydesc{La funzione restituisce in caso di successo il puntatore ad una +{La funzione ritorna il puntatore ad una struttura di tipo \struct{hostent} contenente i dati associati al nome a - dominio, o un puntatore nullo in caso di errore.} -\end{functions} + dominio in caso di successo e un puntatore nullo per un errore.} +\end{funcproto} In questo caso la funzione prende un secondo argomento \param{af} che indica -(i soli valori consentiti sono \const{AF\_INET} o \const{AF\_INET6}, per -questo è necessario l'uso di \headfile{sys/socket.h}) la famiglia di indirizzi -che dovrà essere utilizzata nei risultati restituiti dalla funzione. Per tutto -il resto la funzione è identica a \func{gethostbyname}, ed identici sono i -suoi risultati. +quale famiglia di indirizzi è quella che dovrà essere utilizzata per +selezionare i risultati restituiti dalla funzione; i soli valori consentiti +sono \const{AF\_INET} o \const{AF\_INET6} per indicare rispettivamente IPv4 e +IPv6 (per questo è necessario l'uso di \headfile{sys/socket.h}). Per tutto il +resto la funzione è identica a \func{gethostbyname}, ed identici sono i suoi +risultati. -\begin{figure}[!htbp] +\begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{\codesamplewidth} \includecodesample{listati/mygethost.c} @@ -802,11 +803,10 @@ con lo stampare il nome canonico, dopo di che (\texttt{\small 26--30}) si stampano eventuali altri nomi. Per questo prima (\texttt{\small 26}) si prende il puntatore alla cima della lista che contiene i nomi e poi (\texttt{\small 27--30}) si esegue un ciclo che sarà ripetuto fin tanto che nella lista si -troveranno dei puntatori validi\footnote{si ricordi che la lista viene - terminata da un puntatore nullo.} per le stringhe dei nomi; prima -(\texttt{\small 28}) si stamperà la stringa e poi (\texttt{\small 29}) si -provvederà ad incrementare il puntatore per passare al successivo elemento -della lista. +troveranno dei puntatori validi per le stringhe dei nomi (si ricordi che la +lista viene terminata da un puntatore nullo); prima (\texttt{\small 28}) si +stamperà la stringa e poi (\texttt{\small 29}) si provvederà ad incrementare +il puntatore per passare al successivo elemento della lista. Una volta stampati i nomi si passerà a stampare gli indirizzi, il primo passo (\texttt{\small 31--38}) è allora quello di riconoscere il tipo di indirizzo @@ -835,42 +835,47 @@ ci sono precauzioni particolari da prendere.\footnote{volendo essere pignoli avuto un errore con \func{gethostbyname}, ma si ricordi che la sicurezza non è mai troppa.} -Le funzioni illustrate finora hanno un difetto: utilizzando una area di -memoria interna per allocare i contenuti della struttura \struct{hostent} non -possono essere rientranti. Questo comporta anche che in due successive -chiamate i dati potranno essere sovrascritti. Si tenga presente poi che -copiare il contenuto della sola struttura non è sufficiente per salvare tutti -i dati, in quanto questa contiene puntatori ad altri dati, che pure possono -essere sovrascritti; per questo motivo, se si vuole salvare il risultato di -una chiamata, occorrerà eseguire quella che si chiama una \itindex{deep~copy} -\textit{deep copy}.\footnote{si chiama così quella tecnica per cui, quando si - deve copiare il contenuto di una struttura complessa (con puntatori che - puntano ad altri dati, che a loro volta possono essere puntatori ad altri - dati) si deve copiare non solo il contenuto della struttura, ma eseguire una - scansione per risolvere anche tutti i puntatori contenuti in essa (e così - via se vi sono altre sotto-strutture con altri puntatori) e copiare anche i - dati da questi referenziati.} +Le funzioni illustrate finora hanno un difetto: utilizzano tutte una area di +memoria interna per allocare i contenuti della struttura \struct{hostent} e +per questo non possono essere rientranti. L'uso della memoria interna inoltre +comporta anche che in due successive chiamate i dati potranno essere +sovrascritti. + +Si tenga presente poi che copiare il contenuto della sola struttura non è +sufficiente per salvare tutti i dati, in quanto questa contiene puntatori ad +altri dati, che pure possono essere sovrascritti; per questo motivo, se si +vuole salvare il risultato di una chiamata, occorrerà eseguire quella che si +chiama una \itindex{deep~copy} \textit{deep copy}.\footnote{si chiama così + quella tecnica per cui, quando si deve copiare il contenuto di una struttura + complessa (con puntatori che puntano ad altri dati, che a loro volta possono + essere puntatori ad altri dati) si deve copiare non solo il contenuto della + struttura, ma eseguire una scansione per risolvere anche tutti i puntatori + contenuti in essa (e così via se vi sono altre sotto-strutture con altri + puntatori) e copiare anche i dati da questi referenziati.} Per ovviare a questi problemi nelle \acr{glibc} sono definite anche delle versioni rientranti delle precedenti funzioni, al solito queste sono caratterizzate dall'avere un suffisso \texttt{\_r}, pertanto avremo le due funzioni \funcd{gethostbyname\_r} e \funcd{gethostbyname2\_r} i cui prototipi sono: -\begin{functions} - \headdecl{netdb.h} - \headdecl{sys/socket.h} - \funcdecl{int gethostbyname\_r(const char *name, struct hostent *ret, - char *buf, size\_t buflen, struct hostent **result, int *h\_errnop)} - \funcdecl{int gethostbyname2\_r(const char *name, int af, - struct hostent *ret, char *buf, size\_t buflen, - struct hostent **result, int *h\_errnop)} - - Versioni rientranti delle funzioni \func{gethostbyname} e - \func{gethostbyname2}. - - \bodydesc{Le funzioni restituiscono 0 in caso di successo ed un valore - negativo in caso di errore.} -\end{functions} + +\begin{funcproto}{ +\fhead{netdb.h} +\fhead{sys/socket.h} +\fdecl{int gethostbyname\_r(const char *name, struct hostent *ret, + char *buf, size\_t buflen,\\ +\phantom{int gethostbyname\_r(}struct hostent **result, int *h\_errnop)} +\fdecl{int gethostbyname2\_r(const char *name, int af, + struct hostent *ret, char *buf,\\ +\phantom{int gethostbyname2\_r(}size\_t buflen, struct hostent **result, int *h\_errnop)} + +\fdesc{Versioni rientranti delle funzioni \func{gethostbyname} e + \func{gethostbyname2}.} +} + +{Le funzioni ritornano $0$ in caso di successo ed un valore diverso da zero per + un errore.} +\end{funcproto} Gli argomenti \param{name} (e \param{af} per \func{gethostbyname2\_r}) hanno lo stesso significato visto in precedenza. Tutti gli altri argomenti hanno lo @@ -890,7 +895,7 @@ con \param{h\_errnop} e quello su cui dovrà salvare il puntatore che si userà per accedere i dati con \param{result}. In caso di successo entrambe le funzioni restituiscono un valore nullo, -altrimenti restituiscono un codice di errore negativo e all'indirizzo puntato +altrimenti restituiscono un valore non nulla e all'indirizzo puntato da \param{result} sarà salvato un puntatore nullo, mentre a quello puntato da \param{h\_errnop} sarà salvato il valore del codice di errore, dato che per essere rientrante la funzione non può la variabile globale \var{h\_errno}. In @@ -903,64 +908,59 @@ con un buffer di dimensione maggiore. Una delle caratteristiche delle interrogazioni al servizio DNS è che queste sono normalmente eseguite con il protocollo UDP, ci sono casi in cui si preferisce che vengano usate connessioni permanenti con il protocollo TCP. Per -ottenere questo\footnote{si potrebbero impostare direttamente le opzioni di - \var{\_\_res.options}, ma queste funzioni permettono di semplificare la - procedura.} sono previste delle funzioni apposite; la prima è -\funcd{sethostent}, il cui prototipo è: -\begin{prototype}{netdb.h} -{void sethostent(int stayopen)} +ottenere questo sono previste delle funzioni apposite (si potrebbero impostare +direttamente le opzioni di \var{\_\_res.options}, ma queste funzioni +permettono di semplificare la procedura); la prime sono \funcd{sethostent} e +\func{endhostent}, il cui prototipo è: -Richiede l'uso di connessioni per le interrogazioni ad un server DNS. - -\bodydesc{La funzione non restituisce nulla.} -\end{prototype} - -La funzione permette di richiedere l'uso di connessioni TCP per la richiesta -dei dati, e che queste restino aperte per successive richieste. Il valore -dell'argomento \param{stayopen} indica se attivare questa funzionalità, un -valore pari a 1 (o diverso da zero), che indica una condizione vera in C, -attiva la funzionalità. Come si attiva l'uso delle connessioni TCP lo si può -disattivare con la funzione \funcd{endhostent}; il suo prototipo è: -\begin{prototype}{netdb.h} -{void endhostent(void)} - -Disattiva l'uso di connessioni per le interrogazioni ad un server DNS. +\begin{funcproto}{ +\fhead{netdb.h} +\fdecl{void sethostent(int stayopen)} +\fdesc{Richiede l'uso di connessioni TCP per le interrogazioni ad un server DNS.} +\fdecl{void endhostent(void)} +\fdesc{Disattiva l'uso di connessioni TCP per le interrogazioni ad un server DNS.} +} -\bodydesc{La funzione non restituisce nulla.} -\end{prototype} -\noindent e come si può vedere la funzione è estremamente semplice, non -richiedendo nessun argomento. +{Le funzioni non restituiscono nulla, e non danno errori.} +\end{funcproto} -% TODO manca gethostent (e gethostent_r) e altro ? (vedi man page) +La funzione \func{sethostent} permette di richiedere l'uso di connessioni TCP +per la richiesta dei dati, e che queste restino aperte per successive +richieste; il valore dell'argomento \param{stayopen} indica se attivare questa +funzionalità, un valore diverso da zero, che indica una condizione vera in C, +attiva la funzionalità. Per disattivare l'uso delle connessioni TCP si può +invece usare \func{endhostent}, e come si vede la funzione è estremamente +semplice, non richiedendo nessun argomento. Infine si può richiedere la risoluzione inversa di un indirizzo IP od IPv6, per ottenerne il nome a dominio ad esso associato, per fare questo si può usare la funzione \funcd{gethostbyaddr}, il cui prototipo è: -\begin{functions} - \headdecl{netdb.h} - \headdecl{sys/socket.h} - \funcdecl{struct hostent *gethostbyaddr(const char *addr, int len, int type)} - Richiede la risoluzione inversa di un indirizzo IP. - - \bodydesc{La funzione restituisce l'indirizzo ad una struttura - \struct{hostent} in caso di successo ed \val{NULL} in caso di errore.} -\end{functions} +\begin{funcproto}{ +\fhead{netdb.h} +\fhead{sys/socket.h} +\fdecl{struct hostent *gethostbyaddr(const char *addr, int len, int type)} +\fdesc{Richiede la risoluzione inversa di un indirizzo IP.} +} + +{La funzione ritorna l'indirizzo ad una struttura \struct{hostent} in caso di + successo e \val{NULL} per un errore.} +\end{funcproto} 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}\footnote{si ricordi che, come illustrato in - fig.~\ref{fig:sock_sa_ipv4_struct}, questo in realtà corrisponde ad un - numero intero, da esprimere comunque in \textit{network order}, non - altrettanto avviene però per \struct{in6\_addr}, pertanto è sempre opportuno - inizializzare questi indirizzi con \func{inet\_pton} (vedi - sez.~\ref{sec:sock_conv_func_gen}).} per un indirizzo IPv4 ed una struttura -\struct{in6\_addr} per un indirizzo IPv6, mentre in \param{len} se ne dovrà +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 -\param{type} indica il tipo di indirizzo e dovrà essere o \const{AF\_INET} o -\const{AF\_INET6}. +\param{type} deve indicare il tipo di indirizzo, e dovrà essere o +\const{AF\_INET} o \const{AF\_INET6}. La funzione restituisce, in caso di successo, un puntatore ad una struttura \struct{hostent}, solo che in questo caso la ricerca viene eseguita @@ -968,36 +968,68 @@ richiedendo al DNS un record di tipo \texttt{PTR} corrispondente all'indirizzo specificato. In caso di errore al solito viene usata la variabile \var{h\_errno} per restituire un opportuno codice. In questo caso l'unico campo del risultato che interessa è \var{h\_name} che conterrà il nome a -dominio, la funziona comunque inizializza anche il primo campo della lista +dominio, la funzione comunque inizializza anche il primo campo della lista \var{h\_addr\_list} col valore dell'indirizzo passato come argomento. +Dato che \func{gethostbyaddr} usa un buffer statico, anche di questa funzione +esiste una versione rientrante \funcd{gethostbyaddr\_r} fornita come +estensione dalle \acr{glibc}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{netdb.h} +\fhead{sys/socket.h} +\fdecl{struct hostent *gethostbyaddr\_r(const void *addr, socklen\_t len, int type,\\ +\phantom{struct hostent *gethostbyaddr\_r(}struct hostent *ret, char *buf, size\_t buflen,\\ +\phantom{struct hostent *gethostbyaddr\_r(}struct hostent **result, int *h\_errnop);} +\fdesc{Richiede la risoluzione inversa di un indirizzo IP.} +} + +{La funzione ritorna $0$ in caso di successo e un valore non nullo per un errore.} +\end{funcproto} + +La funzione prende per gli argomenti \param{addr}, \param{len} e \param{type} +gli stessi valori di \func{gethostbyaddr} con lo stesso significato, gli +argomenti successivi vengono utilizzati per restituire i dati, sono identici a +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}), vennero introdotte due nuove funzioni di -risoluzione,\footnote{le funzioni sono presenti nelle \acr{glibc} versione - 2.1.96, ma essendo considerate deprecate (vedi +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 sez.~\ref{sec:sock_advanced_name_services}) sono state rimosse nelle versioni successive.} \funcd{getipnodebyname} e \funcd{getipnodebyaddr}, i cui prototipi sono: -\begin{functions} - \headdecl{netdb.h} - \headdecl{sys/types.h} - \headdecl{sys/socket.h} - \funcdecl{struct hostent *getipnodebyname(const char *name, int af, int +\begin{funcproto}{ +\fhead{netdb.h} +\fhead{sys/types.h} +\fhead{sys/socket.h} +\fdecl{struct hostent *getipnodebyname(const char *name, int af, int flags, int *error\_num)} - - \funcdecl{struct hostent *getipnodebyaddr(const void *addr, size\_t len, +\fdesc{Richiede la risoluzione di un nome a dominio.} +\fdecl{struct hostent *getipnodebyaddr(const void *addr, size\_t len, int af, int *error\_num)} +\fdesc{Richiede la risoluzione inversa di un indirizzo IP.} +} - Richiedono rispettivamente la risoluzione e la risoluzione inversa di un - indirizzo IP. - - \bodydesc{Entrambe le funzioni restituiscono l'indirizzo ad una struttura - \struct{hostent} in caso di successo ed \val{NULL} in caso di errore.} -\end{functions} +{Le funzioni ritornano l'indirizzo ad una struttura \struct{hostent} in caso + di successo e \val{NULL} per un errore.} +\end{funcproto} Entrambe le funzioni supportano esplicitamente la scelta di una famiglia di indirizzi con l'argomento \param{af} (che può assumere i valori @@ -1053,22 +1085,23 @@ e \func{gethostbyaddr}. L'uso di una allocazione dinamica però comporta anche 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{functions} - \headdecl{netdb.h} - \headdecl{sys/types.h} - \headdecl{sys/socket.h} - \funcdecl{void freehostent(struct hostent *ip)} - Disalloca una struttura \var{hostent}. - - \bodydesc{La funzione non ritorna nulla.} -\end{functions} +\begin{funcproto}{ +\fhead{netdb.h} +\fhead{sys/types.h} +\fhead{sys/socket.h} +\fdecl{void freehostent(struct hostent *ip)} +\fdesc{Disalloca una struttura \var{hostent}.} +} + +{La funzione non ritorna nulla, e non da errori.} +\end{funcproto} La funzione permette di disallocare una struttura \var{hostent} precedentemente allocata in una chiamata di \func{getipnodebyname} o \func{getipnodebyaddr}, e prende come argomento l'indirizzo restituito da una -di queste funzioni. +di queste funzioni. Infine per concludere la nostra panoramica sulle funzioni di risoluzione dei nomi dobbiamo citare le funzioni che permettono di interrogare gli altri @@ -1254,9 +1287,6 @@ rimandando alle rispettive pagine di manuale. \end{table} - - - \subsection{Le funzioni avanzate per la risoluzione dei nomi} \label{sec:sock_advanced_name_services}