From 2354bea32f841874996df139e72aab07b29ba12e Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sat, 21 Aug 2004 16:09:00 +0000 Subject: [PATCH] Altro materiale sulle interrogazioni al DNS, ed indicizzazione dei value result argumet --- filedir.tex | 11 +- filestd.tex | 21 ++-- othersock.tex | 7 +- process.tex | 7 +- prochand.tex | 7 +- sockctrl.tex | 323 +++++++++++++++++++++++++++++++++++--------------- 6 files changed, 256 insertions(+), 120 deletions(-) diff --git a/filedir.tex b/filedir.tex index b9d4017..829f5a0 100644 --- a/filedir.tex +++ b/filedir.tex @@ -765,11 +765,12 @@ con i thread; il suo prototipo errore, gli errori sono gli stessi di \func{readdir}.} \end{functions} -La funzione restituisce in \param{result} (come \textit{value result - argument}) l'indirizzo dove sono stati salvati i dati, che di norma -corrisponde a quello della struttura precedentemente allocata e specificata -dall'argomento \param{entry} (anche se non è assicurato che la funzione usi lo -spazio fornito dall'utente). +La funzione restituisce in \param{result} (come +\index{\textit{value~result~argument}}\textit{value result argument}) +l'indirizzo dove sono stati salvati i dati, che di norma corrisponde a quello +della struttura precedentemente allocata e specificata dall'argomento +\param{entry} (anche se non è assicurato che la funzione usi lo spazio fornito +dall'utente). I vari campi di \struct{dirent} contengono le informazioni relative alle voci presenti nella directory; sia BSD che SVr4\footnote{POSIX prevede invece solo diff --git a/filestd.tex b/filestd.tex index 9d06757..9ff0123 100644 --- a/filestd.tex +++ b/filestd.tex @@ -862,12 +862,12 @@ linea. Quest'ultimo \emph{deve} essere stato allocato in precedenza con una locale); come secondo parametro la funzione vuole l'indirizzo della variabile contenente le dimensioni del buffer suddetto. -Se il buffer di destinazione è sufficientemente ampio la stringa viene -scritta subito, altrimenti il buffer viene allargato usando -\func{realloc} e la nuova dimensione ed il nuovo puntatore vengono -passata indietro (si noti infatti come per entrambi i parametri si siano -usati dei \textit{value result argument}, passando dei puntatori anziché -i valori delle variabili, secondo la tecnica spiegata in +Se il buffer di destinazione è sufficientemente ampio la stringa viene scritta +subito, altrimenti il buffer viene allargato usando \func{realloc} e la nuova +dimensione ed il nuovo puntatore vengono passata indietro (si noti infatti +come per entrambi i parametri si siano usati dei +\index{\textit{value~result~argument}}\textit{value result argument}, passando +dei puntatori anziché i valori delle variabili, secondo la tecnica spiegata in sez.~\ref{sec:proc_var_passing}). Se si passa alla funzione l'indirizzo di un puntatore impostato a \val{NULL} @@ -1141,10 +1141,11 @@ sono: Entrambe le funzioni prendono come parametro \param{strptr} che deve essere l'indirizzo di un puntatore ad una stringa di caratteri, in cui verrà restituito (si ricordi quanto detto in sez.~\ref{sec:proc_var_passing} a -proposito dei \textit{value result argument}) l'indirizzo della stringa -allocata automaticamente dalle funzioni. Occorre inoltre ricordarsi di -invocare \func{free} per liberare detto puntatore quando la stringa non serve -più, onde evitare memory leak\index{memory leak}. +proposito dei \index{\textit{value~result~argument}}\textit{value result + argument}) l'indirizzo della stringa allocata automaticamente dalle +funzioni. Occorre inoltre ricordarsi di invocare \func{free} per liberare +detto puntatore quando la stringa non serve più, onde evitare memory +leak\index{memory leak}. Infine una ulteriore estensione GNU definisce le due funzioni \func{dprintf} e \func{vdprintf}, che prendono un file descriptor al posto dello stream. Altre diff --git a/othersock.tex b/othersock.tex index 3944e5d..648dc61 100644 --- a/othersock.tex +++ b/othersock.tex @@ -264,9 +264,10 @@ I due argomenti \param{from} e \param{fromlen} sono utilizzati per ottenere l'indirizzo del mittente del pacchetto che è stato ricevuto, e devono essere opportunamente inizializzati con i puntatori alle variabili dove la struttura contenente quest'ultimo e la relativa lunghezza saranno scritti (si noti che -\param{fromlen} è un valore intero ottenuto come \textit{value return - argument}). Se non si è interessati a questa informazione, entrambi gli -argomenti devono essere inizializzati al valore \const{NULL}. +\param{fromlen} è un valore intero ottenuto come +\index{\textit{value~result~argument}}\textit{value result argument}). Se non +si è interessati a questa informazione, entrambi gli argomenti devono essere +inizializzati al valore \const{NULL}. Una differenza fondamentale del comportamento di queste funzioni rispetto alle usuali \func{read} e \func{write} che abbiamo usato con i socket TCP è che in diff --git a/process.tex b/process.tex index cbdbc1d..29fd15f 100644 --- a/process.tex +++ b/process.tex @@ -1286,9 +1286,10 @@ nella programmazione normale. Talvolta però è necessario che la funzione possa restituire indietro alla funzione chiamante un valore relativo ad uno dei suoi parametri. Per far -questo si usa il cosiddetto \textit{value result argument}, si passa cioè, -invece di una normale variabile, un puntatore alla stessa; vedremo alcuni -esempi di questa modalità nelle funzioni che gestiscono i socket (in +questo si usa il cosiddetto +\index{\textit{value~result~argument}}\textit{value result argument}, si passa +cioè, invece di una normale variabile, un puntatore alla stessa; vedremo +alcuni esempi di questa modalità nelle funzioni che gestiscono i socket (in sez.~\ref{sec:TCP_functions}), in cui, per permettere al kernel di restituire informazioni sulle dimensioni delle strutture degli indirizzi utilizzate, viene usato questo meccanismo. diff --git a/prochand.tex b/prochand.tex index 9f6ae1f..69da2ce 100644 --- a/prochand.tex +++ b/prochand.tex @@ -1685,9 +1685,10 @@ corrente. Anche queste funzioni sono un'estensione specifica di Linux, e non richiedono nessun privilegio. I valori sono restituiti negli argomenti, che vanno -specificati come puntatori (è un altro esempio di \textit{value result - argument}). Si noti che queste funzioni sono le uniche in grado di leggere -gli identificatori del gruppo \textit{saved}. +specificati come puntatori (è un altro esempio di +\index{\textit{value~result~argument}}\textit{value result argument}). Si noti +che queste funzioni sono le uniche in grado di leggere gli identificatori del +gruppo \textit{saved}. \subsection{Le funzioni \func{setfsuid} e \func{setfsgid}} diff --git a/sockctrl.tex b/sockctrl.tex index ea69815..74ba399 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -227,14 +227,16 @@ 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 +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. Oggigiorno i dati mantenuti nei server DNS sono -sostanzialmente relativi soltanto ad indirizzi internet, per cui in pratica -c'è soltanto una classe di indirizzi utilizzata, i dati invece possono essere -di vario tipo, uno dei quali è appunto la corrispondenza fra nome a dominio e -numero IP. +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 +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 @@ -257,22 +259,24 @@ 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 \texttt{LOCALDOMAIN}). In genere è necessario eseguire questa -funzione direttamente in quanto viene automaticamente chiamata la prima che si -esegue una delle altre. - -Le impostazioni del resolver e lo stato del sistema vengono mantenute in una -serie di variabili contenute in una apposita struttura interna che viene -definita in \file{resolv.h} ed è utilizzata come variabile globale, così che -anche un programma vi può accedure una volta che essa sia stata opportunamente -dichiarata come: \includecodesnip{listati/resolv_option.c} +ambiente \texttt{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 \file{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 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 resolver. +comportamento del \textit{resolver}. \begin{table}[htb] \centering @@ -378,10 +382,10 @@ lunghezza \param{anslen} puntato da \param{answer} che si sar allocato in precedenza. -Una seconda funzione di ricerca, analoga a \func{res\_query}, e che prende gli -stessi argomenti, ma esegue l'interrogazione con le funzionalità addizionali -previste dalle due opzioni \const{RES\_DEFNAMES} e \const{RES\_DNSRCH}, è -\funcd{res\_search}, il cui prototipo è: +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} @@ -397,19 +401,19 @@ previste dalle due opzioni \const{RES\_DEFNAMES} e \const{RES\_DNSRCH}, \end{functions} In sostanza la funzione ripete una serie di chiamate a \func{res\_query} -aggiungendo opportunamente il dominio di default da cercare nella stinga -\param{dname}, fermandosi non appena trova un risultato. Il risultato di +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 capitolo 14 di -\cite{DNSbind}. +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 solo quella degli indirizzi internet; le -costanti che identificano dette classi come valore per l'argomento -\param{class} sono riportate 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 \const{C\_CSNET} per la omonima rete, ma è stata dichiarata obsoleta.} @@ -434,15 +438,22 @@ tab.~\ref{tab:DNS_address_class}.\footnote{esisteva in realt \label{tab:DNS_address_class} \end{table} -Come accennato le tipologie di dati che sono mantenibili su un DNS sono -diverse, ed a ciascuna di essa corriponde ad un diverso tipo di -\textit{resource record}; l'elenco dei valori possibili\footnote{come - ottenibile dai file di dichiarazione \file{arpa/nameser.h} e - \file{arpa/nameser_compat.h}.} che si possono indicare per l'argomento -\param{type} è riportato in tab.~\ref{tab:DNS_record_type}; le costanti (tolto -il \texttt{T\_} iniziale) usano gli stessi valori usati per identificare i -record nei file di zona di BIND, e che normalmente sono anche usati come -\textsl{nomi} per indicare i record. +Come accennato le tipologie di dati che sono mantenibili su un server DNS sono +diverse, ed a ciascuna di essa corriponde un diverso tipo di \textit{resource + record}. L'elenco delle costanti\footnote{ripreso dai file di dichiarazione + \file{arpa/nameser.h} e \file{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) +hanno gli stessi nomi usati per identificare i record nei file di zona di +BIND,\footnote{BIND, acronimo di \textit{Berkley Internet Name Domain}, è una + implementazione di un server DNS, ed, essendo utilizzata nella stragrande + maggioranza dei casi, fa da rifererimento; i dati relativi ad un certo + dominio (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 normalmente sono anche usati come nomi per indicare i record. \begin{table}[!htb] \centering @@ -489,9 +500,9 @@ record nei file di zona di BIND, e che normalmente sono anche usati come \const{T\_NAPTR} & puntatore ad una \textit{naming authority} .\\ \const{T\_TSIG} & firma di transazione.\\ \const{T\_IXFR} & trasferimento di zona incrementale.\\ - \const{T\_AXFR} & trasferimenzo di zona di autorità.\\ + \const{T\_AXFR} & trasferimento di zona di autorità.\\ \const{T\_MAILB} & trasferimento di record di caselle di posta.\\ - \const{T\_MAILA} & trasferimetno di record di server di posta.\\ + \const{T\_MAILA} & trasferimento di record di server di posta.\\ \const{T\_ANY} & valore generico.\\ \hline \end{tabular} @@ -505,45 +516,46 @@ L'elenco di tab.~\ref{tab:DNS_record_type} \textit{resource record} definiti, con una breve descrizione del relativo significato. Di tutti questi però viene impiegato correntemente solo un piccolo sottoinsieme, alcuni sono obsoleti ed altri fanno riferimento a dati -applicativi che non ci interessano, pertanto non entreremo nei dettagli del -significato di tutti quanti, ma solo di quelli usati dalle funzioni del -\textit{resolver}, che sono sostanzialmente i seguenti: +applicativi che non ci interessano non avendo nulla a che fare con la +risoluzione degli indirizzi IP, pertanto non entreremo nei dettagli del +significato di tutti i \textit{resource record}, ma solo di quelli usati dalle +funzioni del \textit{resolver}. Questi sono sostanzialmente i seguenti (per +indicarli si è usata la notazione dei file di zona di BIND): \begin{basedescript}{\desclabelwidth{1.2cm}\desclabelstyle{\nextlinelabel}} -\item[\texttt{A}] per indicare la corripondenza fra un nome a dominio ed un - indirizzo IPv4, ad esempio la corrispondenza fra \texttt{dodds.truelite.it} - e l'indirizzo IP \texttt{62.48.34.25}. -\item[\texttt{AAAA}] per indicare la corrispondenza fra un nome a dominio ed - un indirizzo IPv6; è chiamato in questo modo dato che la dimensione di un - indirizzo IPv6 è quattro volte quella di un indirizzo IPv4. -\item[\texttt{PTR}] per provvedere la mappatura inversa fra un indirizzo IP ed - un nome a dominio si utilizza questo tipo di record (il cui nome sta per - \textit{pointer}). +\item[\texttt{A}] viene usato per indicare la corripondenza fra un nome a + dominio ed un indirizzo IPv4; ad esempio la corrispondenza fra + \texttt{dodds.truelite.it} e l'indirizzo IP \texttt{62.48.34.25}. +\item[\texttt{AAAA}] viene usato per indicare la corrispondenza fra un nome a + dominio ed un indirizzo IPv6; è chiamato in questo modo dato che la + dimensione di un indirizzo IPv6 è quattro volte quella di un indirizzo IPv4. +\item[\texttt{PTR}] per fornire la corripondenza inversa fra un indirizzo IP + ed un nome a dominio ad esso associato si utilizza questo tipo di record (il + cui nome sta per \textit{pointer}). \item[\texttt{CNAME}] qualora si abbiamo più nomi che corrispondono allo stesso indirizzo (come ad esempio \texttt{www.truelite.it}, o \texttt{sources.truelite.it}, che fanno sempre riferimento a \texttt{dodds.truelite.it}) si può usare questo tipo di record per creare degli \textit{alias} in modo da associare un qualunque altro nome al - \textsl{nome canonico} della macchina (quello associato al record - \texttt{A}). + \textsl{nome canonico} della macchina (si chiama così quello associato al + record \texttt{A}). \end{basedescript} 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, a -differenza delle funzioni viste finora, 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, e può non avere -nessun significato nell'indicare quale parte del procedimento di risoluzione è +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 +significato nell'indicare quale parte del procedimento di risoluzione è fallita. -Per questo motivo all'interno del resolver è stata definita una apposita -variabile di errore, \var{h\_errno} che viene utilizzata dalle funzioni del -resolver per indicare quale problema ha causato il fallimento della -risoluzione del nome. Ad essa si può accedere una volta che la si dichiara -con: +Per questo motivo è stata definita una variabile di errore separata, +\var{h\_errno}, che viene utilizzata dalle funzioni del \textit{resolver} per +indicare quale problema ha causato il fallimento della risoluzione del nome. +Ad essa si può accedere una volta che la si dichiara con: \includecodesnip{listati/herrno.c} -ed i valori che può assumere sono riportati in tab.~\ref{tab:h_errno_values}. - +ed i valori che può assumere, con il relativo significato, sono riportati in +tab.~\ref{tab:h_errno_values}. \begin{table}[!htb] \centering @@ -571,11 +583,10 @@ ed i valori che pu \label{tab:h_errno_values} \end{table} - Insieme alla nuova variabile vengono definite anche due nuove funzioni per -stampare l'errore a video, analoghe a quelle di sez.~\ref{sec:sys_strerror}, -ma che usano il valore di \var{h\_errno}; la prima è \funcd{herror} ed il suo -prototipo è: +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{functions} \headdecl{netdb.h} \funcdecl{void herror(const char *string)} @@ -593,8 +604,8 @@ funzione Restituisce una stringa corripondente ad un errore di risoluzione. \end{functions} -\noindent e come per l'analoga \func{strerror} restituise una stringa con un -messaggio di errore già formattato corrispondente al codice passato come +\noindent che, come l'analoga \func{strerror}, restituise una stringa con un +messaggio di errore già formattato, corrispondente al codice passato come argomento (che si presume sia dato da \var{h\_errno}). @@ -614,8 +625,8 @@ una stazione noto il suo nome a dominio, il suo prototipo Determina l'indirizzo associato al nome a dominio \param{name}. \bodydesc{La funzione restituisce in caso di successo il puntatore ad una - struttura di tipo \struct{hostent} contente i dati associati al nome a - dominio o un puntatore nullo in caso di errore.} + struttura di tipo \struct{hostent} contenente i dati associati al nome a + dominio, o un puntatore nullo in caso di errore.} \end{prototype} La funzione prende come argomento una stringa \param{name} contenente il nome @@ -656,12 +667,37 @@ diretto al primo indirizzo della lista. Oltre ai normali nomi a dominio la funzione accetta come argomento \param{name} anche indirizzi numerici, in formato dotted decimal per IPv4 o -con la notazione illustrata in sez.~\ref{sec:IP_ipv6_notation}. In tal caso -\func{gethostbyname} non eseguirà nessuna interrogazione remota, ma si -limiterà a copiare la stringa nel campo \var{h\_name} ed a creare la -corrispondente struttura \var{in\_addr} da indirizzara con +con la notazione illustrata in sez.~\ref{sec:IP_ipv6_notation} per IPv6. In +tal caso \func{gethostbyname} non eseguirà nessuna interrogazione remota, ma +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 resolver; dato che questo non è molto comodo è stata +definita 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)} + +Determina l'indirizzo di tipo \param{af} associato al nome a dominio +\param{name}. + +\bodydesc{La funzione restituisce in caso di successo 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} + +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 \texttt{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. \begin{figure}[!htb] \footnotesize \centering @@ -673,36 +709,131 @@ corrispondente struttura \var{in\_addr} da indirizzara con \label{fig:myhost_example} \end{figure} -Vediamo allora un primo esempio dell'uso di queste funzioni, in +Vediamo allora un primo esempio dell'uso delle funzioni di risoluzione, in fig.~\ref{fig:myhost_example} è riportato un estratto del codice di un -programma che esegue una semplice interrogazione al resolver usando -\func{gethostbyname} e stampa a video i risultati. Al solito il sorgente -completo, he comprende il trattamento delle opzioni ed una funzione per -stampare un messaggio di aiuto, è nel file \texttt{myhost.c} dei sorgenti +programma che esegue una semplice interrogazione al \textit{resolver} usando +\func{gethostbyname} e poi ne stampa a video i risultati. Al solito il +sorgente completo, he comprende il trattamento delle opzioni ed una funzione +per stampare un messaggio di aiuto, è nel file \texttt{myhost.c} dei sorgenti allegati alla guida. +Il programma richiede un solo argomento che specifichi il nome da cercare, +senza il quale (\texttt{\small 12--15}) esce con un errore. Dopo di che +(\texttt{\small 16}) si limita a chiamare \func{gethostbyname}, ricendo il +risultato nel puntatore \var{data}. Questo (\texttt{\small 17--20}) viene +controllato per rilevare eventuali errori, nel qual caso il programma esce +dopo aver stampato un messaggio con \func{herror}. + +Se invece la risoluzione è andata a buon fine si inizia (\texttt{\small 21}) +con lo stampare il nome canonico, dopo di che (\texttt{\small 22--26}) si +stampano eventuali altri nomi. Per questo prima (\texttt{\small 22}) si prende +il puntatore alla cima della lista che contiene i nomi e poi (\texttt{\small + 23--26}) 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 24}) si stamperà la stringa e poi (\texttt{\small 25}) 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 27--34}) è allora quello di riconoscere il tipo di indirizzo +sulla base del valore del campo \var{h\_addrtype}, stampandolo a video. Si è +anche previsto di stampare un errore nel caso (che non dovrebbe mai accadere) +di un indirizzo non valido. + +Infine (\texttt{\small 35--40}) si stamperanno i valori degli indirizzi, di +nuovo (\texttt{\small 35}) si inizializzerà un puntatore alla cima della lista +e si eseguirà un ciclo fintanto che questo punterà ad indirizzi validi in +maniera analoga a quanto fatto in precedenza per i nomi a dominio. Si noti +come, essendo il campo \var{h\_addr\_list} un puntatore ad strutture di +indirizzi generiche, questo sia ancora di tipo \texttt{char **} e si possa +riutilizzare lo stesso puntatore usato per i nomi. + +Per ciascun indirizzo valido si provvederà (\texttt{\small 37}) ad una +conversione con la funzione \func{inet\_ntop} (vedi +sez.~\ref{sec:sock_addr_func}) passandole gli opportuni argomenti, questa +restituirà la stringa da stampare (\texttt{\small 38}) con il valore +dell'indirizzo in \var{buffer}, che si è avuto la cura di dichiarare +inizialmente (\texttt{\small 10}) con dimensioni adeguate; dato che la +funzione è in grado di tenere conto automaticamente del tipo di indirizzo non +ci sono precauzioni particolari da prendere.\footnote{volendo essere pignoli + si dovrebbe controllarne lo stato di uscita, lo si è tralasciato per non + appesantire il codice, dato che in caso di indirizzi non validi si sarebbe + avuto un errore con \func{gethostbyname}, ma si ricordi che la sicurezza non + è mai troppa.} + +Le funzioni illustrate finora hanno un difetto fondamentale, utilizzando una +area di memoria interna per allocare il contenuto della struttura +\struct{hostent} non possono essere rientranti. Per questo motivo ne sono +state definite delle versioni alternative rientranti, 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} - -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 chiamare -\func{res\_init} (vedi sez.~\ref{sec:sock_resolver_functions}) per modificare -le opzioni del resolver; dato che questo non è molto comodo è stata definita -un'altra funzione, \funcd{gethostbyname2}, il cui prototipo è: +Gli argomenti \param{name} (e \param{af} per \func{gethostbyname2}) hanno lo +stesso significato visto in precedenza. Tutti gli altri argomenti hanno lo +stesso significato per entrambe le funzioni. Per evitare l'uso di variabili +globali si dovrà allocare preventivamente una struttura \struct{hostent} in +cui ricevere il risultato, passandone l'indirizzo alla funzione nell'argomento +\param{ret}. Inoltre, dato che \struct{hostent} contiene solo dei puntatori, +dovrà essere allocato anche un buffer in cui le funzioni possano scrivere +tutti i dati del risultato dell'interrogazione, l'indirizzo e la lunghezza di +questo buffer devono essere indicati con gli argomenti \param{buf} e +\param{buflen}. + +Gli ultimi due argomenti vengono utilizzati per avere indietro i risultati +come \index{\textit{value~result~argument}}\textit{value result argument}, si +deve specificare l'indirizzo della variabile su cui salvare il codice di +errore con \param{h\_errnop} e quello su cui salvare il puntatatore 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 +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 +questo caso il codice di errore, oltre ai valori di +tab.~\ref{tab:h_errno_values} si può avere anche quello di \errcode{ERANGE} +qualora il buffer allocato non sia sufficiente a contenere i dati, in tal caso +si dovrà semplicemente ripetere l'esecuzione della funzione 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 sono previste delle funzioni apposite; la prima è +\funcd{sethostent}, il cui prototipo è: \begin{prototype}{netdb.h} -{struct hostent *gethostbyname2(const char *name, int af)} +{void sethostent(int stayopen)} -Determina l'indirizzo di tipo \param{af} associato al nome a dominio -\param{name}. +Richiede l'uso di connessioni per le interrogazioni ad un server DNS. -\bodydesc{La funzione restituisce in caso di successo il puntatore ad una - struttura di tipo \struct{hostent} contente i dati associati al nome a - dominio o un puntatore nullo in caso di errore.} +\bodydesc{La funzione non restituisce nulla.} \end{prototype} -In questo caso la funzione prende un secondo argomento \param{af} che indica -la famiglia di indirizzi da usare come + +\subsection{Altre funzioni di gestione dei nomi} +\label{sec:sock_name_services} + +Quelle illustrate nella sezione precedente sono le funzioni classiche per la +risoluzione di nomi ed indirizzi IP, ma abbiamo già visto in + -- 2.30.2