X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=sockctrl.tex;h=5ef2c7cc0ab160165a4d742fd3661294aba778c6;hp=1dbc855c05b9fcaec8eff896c96c3ff141e139a1;hb=d450a86ffcd4c7ef3265f950994cba25345881ed;hpb=b120ef0b0570efae73c8e50576a3f98fb7830769 diff --git a/sockctrl.tex b/sockctrl.tex index 1dbc855..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 @@ -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