Materiale sulle funzioni di interrogazione dei nomi e del resolver
[gapil.git] / sockctrl.tex
index 1dbc855c05b9fcaec8eff896c96c3ff141e139a1..5ef2c7cc0ab160165a4d742fd3661294aba778c6 100644 (file)
@@ -612,7 +612,7 @@ argomento (che si presume sia dato da \var{h\_errno}).
 
 
 \subsection{La risoluzione dei nomi a dominio}
 
 
 \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
 
 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
@@ -678,7 +678,9 @@ IPv4, se si vogliono ottenere degli indirizzi IPv6 occorrer
 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
 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 è:
+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}
 \begin{functions}
   \headdecl{netdb.h} 
   \headdecl{sys/socket.h}
@@ -762,10 +764,24 @@ 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.}
 
   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
+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
+\index{\textit{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 sottostrutture 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:
 caratterizzate dall'avere un suffisso \texttt{\_r}, pertanto avremo le due
 funzioni \funcd{gethostbyname\_r} e \funcd{gethostbyname2\_r} i cui prototipi
 sono:
@@ -785,16 +801,16 @@ sono:
     negativo in caso di errore.}
 \end{functions}
 
     negativo in caso di errore.}
 \end{functions}
 
-Gli argomenti \param{name} (e \param{af} per \func{gethostbyname2}) hanno lo
-stesso significato visto in precedenza. Tutti gli altri argomenti hanno lo
+Gli argomenti \param{name} (e \param{af} per \func{gethostbyname2\_r}) 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
 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}. 
+\param{ret}.  Inoltre, dato che \struct{hostent} contiene dei puntatori, dovrà
+essere allocato anche un buffer in cui le funzioni possano scrivere tutti i
+dati del risultato dell'interrogazione da questi puntati; 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
 
 Gli ultimi due argomenti vengono utilizzati per avere indietro i risultati
 come \index{\textit{value~result~argument}}\textit{value result argument}, si
@@ -816,9 +832,10 @@ 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
 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 (oltre che delle opzioni
-in \var{\_\_res.options}); la prima è \funcd{sethostent}, il cui prototipo
-è:
+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)}
 
 \begin{prototype}{netdb.h}
 {void sethostent(int stayopen)}
 
@@ -827,14 +844,255 @@ Richiede l'uso di connessioni per le interrogazioni ad un server DNS.
 \bodydesc{La funzione non restituisce nulla.}
 \end{prototype}
 
 \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.
 
 
-\subsection{Altre funzioni di gestione dei nomi}
-\label{sec:sock_name_services}
+\bodydesc{La funzione non restituisce nulla.}
+\end{prototype}
+\noindent e come si può vedere 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 \const{NULL} in caso di errore.}
+\end{functions}
+
+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 è 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
 
 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