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}
-\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
@@ -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
-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}
@@ -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.}
 
-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:
@@ -785,16 +801,16 @@ sono:
     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
-\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
@@ -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
-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)}
 
@@ -827,14 +844,255 @@ 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.
 
-\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
-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