From: Simone Piccardi Date: Sun, 3 Oct 2004 22:56:37 +0000 (+0000) Subject: Materiale sulle funzioni di interrogazione dei nomi e del resolver X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=d450a86ffcd4c7ef3265f950994cba25345881ed Materiale sulle funzioni di interrogazione dei nomi e del resolver --- diff --git a/sockctrl.tex b/sockctrl.tex index 3adaa2b..5ef2c7c 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -612,7 +612,7 @@ argomento (che si presume sia dato da \var{h\_errno}). \subsection{La risoluzione dei nomi a dominio} -\label{sec:sock_gethostbyname} +\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 @@ -832,9 +832,9 @@ 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\footnote{si potrebbero impostare direttamente le opzioni di +ottenere questo\footnote{si potrebbero impostare direttamente le opzioni di \var{\_\_res.options}, ma queste funzioni permettono di semplificare la - procedura.} questo sono previste delle funzioni apposite; la prima è + procedura.} sono previste delle funzioni apposite; la prima è \funcd{sethostent}, il cui prototipo è: \begin{prototype}{netdb.h} {void sethostent(int stayopen)} @@ -867,8 +867,7 @@ 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)} + \funcdecl{struct hostent *gethostbyaddr(const char *addr, int len, int type)} Richiede la risoluzione inversa di un indirizzo IP. @@ -878,32 +877,222 @@ usare la funzione \funcd{gethostbyaddr}, il cui prototipo In questo caso l'argomento \param{addr} dovrà essere il puntatore ad una appropriata struttura contentente il valore dell'indirizzo IP (o IPv6) che si -vuole risolvere. L'uso del tipo \type{char *} per questo argomento ha è -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 \var{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à -specificare la dimensione, infine l'argomento \param{type} indica il tipo di -indirizzo e dovrà essere o \const{AF\_INET} o \const{AF\_INET6}. - - -La funzione restituisce, in caso si successo, un puntatore ad una struttura -\struct{hostent}, solo che la ricerca è fatta richiedendo al DNS un record di -tipo \texttt{PTR}. In caso di errore al solito viene usata la variabile -\var{h\_errno} per restituire un opportuno codice. In questo caso il valore -dei vari campi \var{h\_addr\_list} viene inizializzato al valore passa - - -\subsection{Altre funzioni di gestione dei nomi} -\label{sec:sock_name_services} +vuole risolvere. L'uso del tipo \type{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 \var{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à 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}. + +La funzione restituisce, in caso di successo, un puntatore ad una struttura +\struct{hostent}, solo che in questo caso la ricerca viene eseguita +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 +\var{h\_addr\_list} col valore dell'indirizzo passato come argomento. + +Per risolvere il problema dell'uso da parte delle due funzioni +\func{gethostbyname} e \func{gethostbyaddr} di memoria statica che può essere +socrascritta 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 + 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 + flags, int *error\_num)} + + \funcdecl{struct hostent *getipnodebyaddr(const void *addr, size\_t len, + int af, int *error\_num)} + + 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 \const{NULL} in caso di errore.} +\end{functions} + +Entrambe le funzioni supportano esplicitamente la scelta di una famiglia di +indirizzi con l'argomento \param{af} (che può assumere i valori +\const{AF\_INET} o \const{AF\_INET6}), e restituiscono un codice di errore +(identico a quelli precedentemente illustrati in +tab.~\ref{tab:h_errno_values}) nella variabile puntata da +\param{error\_num}. La funzione \func{getipnodebyaddr} richiede poi che si +specifichi l'indirizzo come per \func{gethostbyaddr} passando anche la +lunghezza dello stesso nell'argomento \param{len}. + +La funzione \func{getipnodebyname} prende come primo argomento il nome da +risolvere, inoltre prevede un apposito argomento \param{flags}, da usare come +maschera binaria, che permette di specificarne il comportamento nella +risoluzione dei diversi tipi di indirizzi (IPv4 e IPv6); ciascun bit +dell'argomento esprime una diversa opzione, e queste possono essere specificate +con un OR aritmetico delle costanti riportate in +tab.~\ref{tab:sock_getipnodebyname_flags}. + +\begin{table}[!htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{10cm}|} + \hline + \textbf{Costante} & \textbf{Significato} \\ + \hline + \hline + \const{AI\_V4MAPPED} & usato con \const{AF\_INET6} per richiedere una + ricerca su un indirizzo IPv4 invece che IPv6; gli + eventuali risultati saranno rimappati su indirizzi + IPv6.\\ + \const{AI\_ALL} & usato con \const{AI\_V4MAPPED}; richiede sia + indirizzi IPv4 che IPv6, e gli indirizzi IPv4 + saranno rimappati in IPv6.\\ + \const{AI\_ADDRCONFIG}& richiede che una richiesta IPv4 o IPv6 venga + eseguita solo se almeno una interfaccia del + sistema è associata ad un indirizzo di tale tipo.\\ + \const{AI\_DEFAULT} & il valore di default, è equivalente alla + combinazione di \const{AI\_ADDRCONFIG} e di + \const{AI\_V4MAPPED)}.\\ + \hline + \end{tabular} + \caption{Valori possibili per i bit dell'argomento \param{flags} della + funzione \func{getipnodebyname}.} + \label{tab:sock_getipnodebyname_flags} +\end{table} + +Entrambe le funzioni restituiscono un puntatore ad una struttura \var{hostent} +allocata dinamicamente che contiene i risultati della ricerca, e per questo +non soffrono dei problemi dovuti all'uso di una sezione statica di memoria +presenti con le precedenti \func{gethostbyname} e \func{gethostbyaddr}. +Questo però comporta la necessità di deallocare esplicitamente la memoria +occupata dai risultati una volta che questi non siano più necessari, onde +evitare perdite di memoria; 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} + +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. + +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} 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 +al tipo di informazione che forniscono (riportato in prima colonna). Nella +tabella si è anche riportato il file su cui vengono ordinariamente mantenute +queste informazioni, che può essere sostituito da un qualunque supporto +interno al \textit{Name Service Switch}, anche se usualmente questo avviene +solo per la risoluzione degli indirizzi. Ciascuna funzione fa riferimento ad +una sua apposita struttura che contiene i relativi dati, riportata in terza +colonna. + +\begin{table}[!htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|l|l|l|l|} + \hline + \textbf{Informazione}&\textbf{File}&\textbf{Struttura}& + \multicolumn{2}{|c|}{\textbf{Funzioni}}\\ + \hline + \hline + indirizzo&\file{/etc/hosts}&\struct{hostent}&\func{gethostbyname}& + \func{gethostbyaddr}\\ + servizio &\file{/etc/services}&\struct{servent}&\func{getservbyname}& + \func{getservbyaddr}\\ + rete &\file{/etc/networks}&\struct{netent}&\func{getnetbyname}& + \func{getnetbyaddr}\\ + protocollo&\file{/etc/protocols}&\struct{protoent}&\func{getprotobyname}& + \func{getprotobyaddr}\\ + \hline + \end{tabular} + \caption{Funzioni di risoluzione dei nomi per i vari servizi del + \textit{Name Service Switch}.} + \label{tab:name_resolution_functions} +\end{table} + +Delle funzioni di tab.~\ref{tab:name_resolution_functions} abbiamo trattato +finora soltanto quelle relative alla risoluzione dei nomi, dato che sono le +più usate, e prevedono praticamente da sempre la necessità di rivolgersi ad +una entità esterna; per le altre invece, estensioni fornite dal NSS a parte, +si fa sempre riferimento ai dati mantenuti nei rispettivi file. + +Consideriamo allora una ricerca sui nomi dei servizi, le due funzioni in +questione sono \funcd{getservbyname} e \funcd{getservbyaddr} i cui prototopi +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)} + + Disalloca una struttura \var{hostent}. + + \bodydesc{La funzione non ritorna nulla.} +\end{functions} + + + +Oltre alle precedenti funzioni di ricerca sono definite anche delle ulteriori +funzioni generiche che permettono di accedere direttamente al contenuto dei +file contenenti le informazioni; come le precedenti esse sono tutte nella +forma \texttt{setXXXent}, \texttt{getXXXent} ed \texttt{endXXXent}, e sono +analoghe a quelle viste in sez.~\ref{sec:sys_user_group} per la lettura delle +informazioni relative ai dati degli utenti e dei gruppi (vedi +tab.~\ref{tab:sys_passwd_func}) che pure sono mantenute tremite il +\textit{Name Service Switch}. + + + + + + +\subsection{Le funzioni avanzate per la risoluzione dei nomi} +\label{sec:sock_advanced_name_services} Quelle illustrate nella sezione precedente sono le funzioni classiche per la -risoluzione di nomi ed indirizzi IP, ma abbiamo già visto in +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 +questi inconvenienti, non c'è comunque una interfaccia sufficientemente +generica + + +Per questo motivo lo standard Posix 1003.1-2001 indicava come deprecate le +varie \func{gethostbyaddr}, \func{gethostbyname}, \var{getipnodebyname} e +\var{getipnodebyaddr} per introdurre una interfaccia + + +rimane comunque il problema generico che si deve sapere +in anticipo quale tipo di indirizzi devo