%% sockctrl.tex
%%
%% Copyright (C) 2004 Simone Piccardi.  Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Prefazione",
%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
%% license is included in the section entitled "GNU Free Documentation
%% License".
%%
\chapter{La gestione dei socket}
\label{cha:sock_generic_management}

Esamineremo in questo capitolo una serie di funzionalità aggiuntive relative
alla gestione dei socket, come la gestione della risoluzione di nomi e
indirizzi, le impostazioni delle varie proprietà ed opzioni relative ai
socket, e le funzioni di controllo che permettono di modificarne il
comportamento.


\section{La risoluzione dei nomi}
\label{sec:sock_name_resolution}

Negli esempi dei capitoli precedenti abbiamo sempre identificato le singole
macchine attraverso indirizzi numerici, sfruttando al più le funzioni di
conversione elementare illustrate in sez.~\ref{sec:sock_addr_func} che
permettono di passare da un indirizzo espresso in forma \textit{dotted
  decimal} ad un numero. Vedremo in questa sezione le funzioni utilizzate per
poter utilizzare dei nomi simbolici al posto dei valori numerici, e viceversa
quelle che permettono di ottenere i nomi simbolici associati ad indirizzi,
porte o altre proprietà del sistema.


\subsection{La struttura del \textit{resolver}}
\label{sec:sock_resolver}

La risoluzione dei nomi è associata tradizionalmente al servizio del
\textit{Domain Name Service} che permette di identificare le macchine su
internet invece che per numero IP attraverso il relativo \textsl{nome a
  dominio}.\footnote{non staremo ad entrare nei dettagli della definizione di
  cosa è un nome a dominio, dandolo per noto, una introduzione alla
  problematica si trova in \cite{AGL} (cap. 9) mentre per una trattazione
  approfondita di tutte le problematiche relative al DNS si può fare
  riferimento a \cite{DNSbind}.} In realtà per DNS si intendono spesso i
server che forniscono su internet questo servizio, mentre nel nostro caso
affronteremo la problematica dal lato client, di un qualunque programma che
necessita di compiere questa operazione.

\begin{figure}[htb]
  \centering
  \includegraphics[width=10cm]{img/resolver}
  \caption{Schema di funzionamento delle routine del \textit{resolver}.}
  \label{fig:sock_resolver_schema}
\end{figure}

Inoltre quella fra nomi a dominio e indirizzi IP non è l'unica corrispondenza
possibile fra nomi simbolici e valori numerici, come abbiamo visto anche in
sez.~\ref{sec:sys_user_group} per le corrispondenze fra nomi di utenti e
gruppi e relativi identificatori numerici; per quanto riguarda però tutti i
nomi associati a identificativi o servizi relativi alla rete il servizio di
risoluzione è gestito in maniera unificata da un insieme di routine fornite
con le librerie del C, detto appunto \textit{resolver}.

Lo schema di funzionamento del \textit{resolver} è illustrato in
fig.~\ref{fig:sock_resolver_schema}; in sostanza i programmi hanno a
disposizione un insieme di funzioni di libreria con cui chiamano il
\textit{resolver}, indicate con le frecce nere. Ricevuta la richiesta è
quest'ultimo che, sulla base della sua configurazione, esegue le operazioni
necessarie a fornire la risposta, che possono essere la lettura delle
informazioni mantenute nei relativi dei file statici presenti sulla macchina,
una interrogazione ad un DNS (che a sua volta, per il funzionamento del
protocollo, può interrogarne altri) o la richiesta ad altri server per i quali
sia fornito il supporto, come LDAP.\footnote{la sigla LDAP fa riferimento ad
  un protocollo, il \textit{Lightweight Directory Access Protocol}, che
  prevede un meccanismo per la gestione di \textsl{elenchi} di informazioni
  via rete; il contenuto di un elenco può essere assolutamente generico, e
  questo permette il mantenimento dei più vari tipi di informazioni su una
  infrastruttura di questo tipo.}

La configurazione del \textit{resolver} attiene più alla amministrazione di
sistema che alla programmazione, ciò non di meno, prima di trattare le varie
funzioni di librerie utilizzate dai programmi, vale la pena fare una
panoramica generale.  Originariamente la configurazione del \textit{resolver}
riguardava esclusivamente le questioni relative alla gestione dei nomi a
dominio, e prevedeva solo l'utilizzo del DNS e del file statico
\file{/etc/hosts}.

Per questo aspetto il file di configurazione principale del sistema è
\file{/etc/resolv.conf} che contiene in sostanza l'elenco degli indirizzi IP
dei server DNS da contattare; a questo si affianca il file
\file{/etc/host.conf} il cui scopo principale è indicare l'ordine in cui
eseguire la risoluzione dei nomi (se usare prima i valori di \file{/etc/hosts}
o quelli del DNS). Tralasciamo i dettagli relativi alle varie direttive che
possono essere usate in questi file, che si trovano nelle rispettive pagine di
manuale.

Con il tempo però è divenuto possibile fornire diversi sostituti per
l'utilizzo delle associazione statiche in \file{/etc/hosts}, inoltre oltre
alla risoluzione dei nomi a dominio ci sono anche altri nomi da risolvere,
come quelli che possono essere associati ad una rete (invece che ad una
singola macchina) o ai gruppi di macchine definiti dal servizio
NIS,\footnote{il \textit{Network Information Service} è un servizio, creato da
  Sun, e poi diffuso su tutte le piattaforme unix-like, che permette di
  raggruppare all'interno di una rete (in quelli che appunto vengono chiamati
  \textit{netgroup}) varie macchine, centralizzando i servizi di definizione
  di utenti e gruppi e di autenticazione, oggi è sempre più spesso sostituito
  da LDAP.} o come quelli dei protocolli e dei servizi che sono mantenuti nei
file statici \file{/etc/protocols} e \file{/etc/services}.  Molte di queste
informazioni non si trovano su un DNS, ma in una rete locale può essere molto
utile centralizzare il mantenimento di alcune di esse su opportuni server.
Inoltre l'uso di diversi supporti possibili per le stesse informazioni (ad
esempio il nome delle macchine può essere mantenuto sia tramite
\file{/etc/hosts}, che con il DNS, che con NIS) comporta il problema
dell'ordine in cui questi vengono interrogati.\footnote{con le implementazioni
  classiche i vari supporti erano introdotti modificando direttamente le
  funzioni di libreria, prevedendo un ordine di interrogazione predefinito e
  non modificabile (a meno di una ricompilazione delle librerie stesse).}

Per risolvere questa serie di problemi la risoluzione dei nomi a dominio
eseguirà dal \textit{resolver} è stata inclusa all'interno di un meccanismo
generico per la risoluzione di corrispondenze fra nomi ed informazioni ad essi
associate chiamato \textit{Name Service Switch}\footnote{il sistema è stato
  introdotto la prima volta nelle librerie standard di Solaris, le \acr{glibc}
  hanno ripreso lo stesso schema, si tenga presente che questo sistema non
  esiste per altre librerie standard come le \acr{libc5} o le \acr{uclib}.}
cui abbiamo accennato anche in sez.~\ref{sec:sys_user_group} per quanto
riguarda la gestione dei dati associati a utenti e gruppi.  Il \textit{Name
  Service Switch} (cui spesso si fa riferimento con l'acronimo NSS) è un
sistema di librerie dinamiche che permette di definire in maniera generica sia
i supporti su cui mantenere i dati di corrispondenza fra nomi e valori
numerici, sia l'ordine in cui effettuare le ricerche sui vari supporti
disponibili. Il sistema prevede una serie di possibili classi di
corrispondenza, quelle attualmente definite sono riportate in
tab.~\ref{tab:sys_NSS_classes}.

\begin{table}[htb]
  \footnotesize
  \centering
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Classe} & \textbf{Tipo di corrispondenza}\\
    \hline
    \hline
    \texttt{shadow}   & corrispondenze fra username e proprietà dell'utente
                       (\acr{uid}, ecc.).\\  
    \texttt{group}    & corrispondenze fra nome del gruppo e proprietà dello 
                        stesso.\\  
    \texttt{aliases}  & alias per la posta elettronica\\ 
    \texttt{ethers}   & corrispondenze fra numero IP e MAC address della
                        scheda di rete.\\ 
    \texttt{hosts}    & corrispondenze fra nome a dominio e numero IP.\\ 
    \texttt{netgroup} & corrispondenze gruppo di rete e macchine che lo
                        compongono.\\  
    \texttt{networks} & corrispondenze fra nome di una rete e suo indirizzo
                        IP.\\  
    \texttt{protocols}& corrispondenze fra nome di un protocollo e relativo
                        numero identificativo.\\ 
    \texttt{rpc}      & corrispondenze fra nome di un servizio RPC e relativo 
                        numero identificativo.\\ 
    \texttt{services} & corrispondenze fra nome di un servizio e numero di
                        porta. \\ 
    \hline
  \end{tabular}
  \caption{Le diverse classi di corrispondenze definite
    all'interno del \textit{Name Service Switch}.} 
  \label{tab:sys_NSS_classes}
\end{table}

Il sistema  del \textit{Name Service  Switch} è controllato dal  contenuto del
file \file{/etc/nsswitch.conf}; questo contiene una riga\footnote{seguendo una
  convezione  comune per  i  file  di configurazione  le  righe vuote  vengono
  ignorate  e  tutto  quello  che  segue un  carattere  ``\texttt{\#}''  viene
  considerato un  commento.} di configurazione per ciascuna  di queste classi,
che  viene inizia  col nome  di tab.~\ref{tab:sys_NSS_classes}  seguito  da un
carattere ``\texttt{:}'' e  prosegue con la lista dei  \textsl{servizi} su cui
le  relative informazioni sono  raggiungibili, scritti  nell'ordine in  cui si
vuole siano interrogati.

Ogni  servizio è  specificato  a sua  volta  da un  nome, come  \texttt{file},
\texttt{dns},  \texttt{db},  ecc.  che  identifica la  libreria  dinamica  che
realizza l'interfaccia  con esso. Per  ciascun servizio se \texttt{NAME}  è il
nome  utilizzato  dentro   \file{/etc/nsswitch.conf},  dovrà  essere  presente
(usualmente  in   \file{/lib})  una  libreria   \texttt{libnss\_NAME}  che  ne
implementa le funzioni.

In ogni caso, qualunque sia la modalità con cui ricevono i dati o il supporto
su cui vengono mantenuti, e che si usino o meno funzionalità aggiuntive
fornire dal sistema del \textit{Name Service Switch}, dal punto di vista di un
programma che deve effettuare la risoluzione di un nome a dominio, tutto
quello che conta sono le funzioni classiche che il \textit{resolver} mette a
disposizione,\footnote{è cura della implementazione fattane nelle \acr{glibc}
  tenere conto della presenza del \textit{Name Service Switch}.} e sono queste
quelle che tratteremo nelle sezioni successive.


\subsection{Le funzioni di interrogazione del \textit{resolver}}
\label{sec:sock_resolver_functions}

Prima di trattare le funzioni usate normalmente nella risoluzione dei nomi a
dominio conviene trattare in maniera più dettagliata il meccanismo principale
da esse utilizzato e cioè quello del servizio DNS. Come accennato questo,
benché in teoria sia solo uno dei possibili supporti su cui mantenere le
informazioni, in pratica costituisce il meccanismo principale con cui vengono
risolti i nomi a dominio.  Per questo motivo esistono una serie di funzioni di
libreria che servono specificamente ad eseguire delle interrogazioni verso un
server DNS, funzioni che poi vengono utilizzate per realizzare le funzioni
generiche di libreria usate anche dal sistema del \textit{resolver}.

Il sistema del DNS è in sostanza di un database distribuito organizzato in
maniera gerarchica, i dati vengono mantenuti in tanti server distinti ciascuno
dei quali si occupa della risoluzione del proprio \textsl{dominio}; i nomi a
dominio sono organizzati in una struttura ad albero analoga a quella
dell'albero dei file, con domini di primo livello (come i \texttt{.org}),
secondo livello (come \texttt{.truelite.it}), ecc.  In questo caso le
separazioni sono fra i vari livelli sono definite dal carattere ``\texttt{.}''
ed i nomi devono essere risolti da destra verso sinistra.\footnote{per chi si
  stia chiedendo quale sia la radice di questo albero, cioè l'equivalente di
  ``\texttt{/}'', la risposta è il dominio speciale ``\texttt{.}'', che in
  genere non viene mai scritto esplicitamente, ma che, come chiunque abbia
  configurato un server DNS sa bene, esiste ed è gestito dai cosiddetti
  \textit{root DNS} che risolvono i domini di primo livello.} Il meccanismo
funziona con il criterio della \textsl{delegazione}, un server responsabile
per un dominio di primo livello può delegare la risoluzione degli indirizzi
per un suo dominio di secondo livello ad un altro server, il quale a sua volta
potrà delegare la risoluzione di un eventuale sottodominio di terzo livello ad
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
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.\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
risoluzione dei nomi, un insieme di funzioni specifiche dedicate
all'interrogazione di un server DNS; la prima di queste funzioni è
\funcd{res\_init}, il cui prototipo è:
\begin{functions}
  \headdecl{netinet/in.h} \headdecl{arpa/nameser.h} \headdecl{resolv.h}
  \funcdecl{int res\_init(void)}

Inizializza il sistema del \textit{resolver}.

\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
  errore.}
\end{functions}

La funzione legge il contenuto dei file di configurazione (i già citati
\file{resolv.conf} e \file{host.conf}) per impostare il dominio di default,
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 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 \textit{resolver}. 

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Costante} & \textbf{Significato} \\
    \hline
    \hline
    \const{RES\_INIT}       & viene attivato se è stata chiamata
                              \func{res\_init}. \\
    \const{RES\_DEBUG}      & stampa dei messaggi di debug.\\
    \const{RES\_AAONLY}     & accetta solo risposte autoritative.\\
    \const{RES\_USEVC}      & usa connessioni TCP per contattare i server 
                              invece che l'usuale UDP.\\
    \const{RES\_PRIMARY}    & interroga soltanto server DNS primari.
                              \\
    \const{RES\_IGNTC}      & ignora gli errori di troncamento, non ritenta la
                              richiesta con una connessione TCP.\\
    \const{RES\_RECURSE}    & imposta il bit che indica che si desidera
                              eseguire una interrogazione ricorsiva.\\
    \const{RES\_DEFNAMES}   & se attivo \func{res\_search} aggiunge il nome
                              del dominio di default ai nomi singoli (che non
                              contengono cioè un ``\texttt{.}'').\\
    \const{RES\_STAYOPEN}   & usato con \const{RES\_USEVC} per mantenere
                              aperte le connessioni TCP fra interrogazioni
                              diverse. \\
    \const{RES\_DNSRCH}     & se attivo \func{res\_search} esegue le ricerche
                              di nomi di macchine nel dominio corrente o nei
                              domini ad esso sovrastanti.\\
    \const{RES\_INSECURE1}  & blocca i controlli di sicurezza di tipo 1.\\
    \const{RES\_INSECURE2}  & blocca i controlli di sicurezza di tipo 2.\\
    \const{RES\_NOALIASES}  & blocca l'uso della variabile di ambiente
                              \texttt{HOSTALIASES}.\\ 
    \const{RES\_USE\_INET6} & restituisce indirizzi IPv6 con
                              \func{gethostbyname}. \\
    \const{RES\_ROTATE}     & ruota la lista dei server DNS dopo ogni
                              interrogazione.\\
    \const{RES\_NOCHECKNAME}& non controlla i nomi per verificarne la
                              correttezza sintattica. \\
    \const{RES\_KEEPTSIG}   & non elimina i record di tipo \texttt{TSIG}.\\
    \const{RES\_BLAST}      & \\
    \const{RES\_DEFAULT}    & è l'insieme di \const{RES\_RECURSE},
                              \const{RES\_DEFNAMES} e \const{RES\_DNSRCH}.\\
    \hline
  \end{tabular}
  \caption{Costanti utilizzabili come valori per \var{\_res.options}.}
  \label{tab:resolver_option}
\end{table}

Per utilizzare questa funzionalità per modificare le impostazioni direttamente
da programma occorrerà impostare un opportuno valore per questo campo ed
invocare esplicitamente \func{res\_init}, dopo di che le altre funzioni
prenderanno le nuove impostazioni. Le costanti che definiscono i vari bit di
questo campo, ed il relativo significato sono illustrate in
tab.~\ref{tab:resolver_option}; trattandosi di una maschera binaria un valore
deve essere espresso con un opportuno OR aritmetico di dette costanti; ad
esempio il valore di default delle opzioni, espresso dalla costante
\const{RES\_DEFAULT}, è definito come:
\includecodesnip{listati/resolv_option_def.c}

Non tratteremo il significato degli altri campi non essendovi necessità di
modificarli direttamente; gran parte di essi sono infatti impostati dal
contenuto dei file di configurazione, mentre le funzionalità controllate da
alcuni di esse possono essere modificate con l'uso delle opportune variabili
di ambiente come abbiamo visto per \texttt{LOCALDOMAIN}. In particolare con
\texttt{RES\_RETRY} si soprassiede il valore del campo \var{retry} che
controlla quante volte viene ripetuto il tentativo di connettersi ad un server
DNS prima di dichiarare fallimento; il valore di default è 4, un valore nullo
significa bloccare l'uso del DNS. Infine con \texttt{RES\_TIMEOUT} si
soprassiede il valore del campo \var{retrans},\footnote{preimpostato al valore
  della omonima costante \const{RES\_TIMEOUT} di \file{resolv.h}.} che è il
valore preso come base (in numero di secondi) per definire la scadenza di una
richiesta, ciascun tentativo di richiesta fallito viene ripetuto raddoppiando
il tempo di scadenza per il numero massimo di volte stabilito da
\texttt{RES\_RETRY}.

La funzione di interrogazione principale è \funcd{res\_query}, che serve ad
eseguire una richiesta ad un server DNS per un nome a dominio
\textsl{completamente specificato} (quello che si chiama FQDN, \textit{Fully
  Qualified Domain Name}); il suo prototipo è:

\begin{functions}
\headdecl{netinet/in.h}
\headdecl{arpa/nameser.h}
\headdecl{resolv.h}
\funcdecl{int res\_query(const char *dname, int class, int type,
              unsigned char *answer, int anslen)}

  Esegue una interrogazione al DNS.

\bodydesc{La funzione restituisce un valore positivo pari alla lunghezza dei
    dati scritti nel buffer \param{answer} in caso di successo e -1 in caso di
    errore.}
\end{functions}

La funzione esegue una interrogazione ad un server DNS relativa al nome da
risolvere passato nella stringa indirizzata da \param{dname}, inoltre deve
essere specificata la classe di indirizzi in cui eseguire la ricerca con
\param{class}, ed il tipo di \textit{resource record} che si vuole ottenere
con \param{type}. Il risultato della ricerca verrà scritto nel buffer di
lunghezza \param{anslen} puntato da \param{answer} che si sarà opportunamente
allocato in precedenza.


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}
\headdecl{resolv.h}
\funcdecl{int res\_search(const char *dname, int class, int type,
              unsigned char *answer, int anslen)}

  Esegue una interrogazione al DNS.
  
  \bodydesc{La funzione restituisce un valore positivo pari alla lunghezza dei
    dati scritti nel buffer \param{answer} in caso di successo e -1 in caso di
    errore.}
\end{functions}

In sostanza la funzione ripete una serie di chiamate a \func{res\_query}
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 quattordicesimo
capitolo di \cite{DNSbind}.

Le classi di indirizzi supportate da un server DNS sono tre, ma di queste 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.}

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Costante} & \textbf{Significato} \\
    \hline
    \hline
    \const{C\_IN}   & indirizzi internet, in pratica i soli utilizzati oggi.\\
    \const{C\_HS}   & indirizzi \textit{Hesiod}, utilizzati solo al MIT, oggi
                      completamente estinti. \\
    \const{C\_CHAOS}& indizzi per la rete \textit{Chaosnet}, un'altra rete
                      sperimentale nata al MIT. \\
    \const{C\_ANY}  & indica un indirizzo di classe qualunque.\\
    \hline
  \end{tabular}
  \caption{Costanti identificative delle classi di indirizzi per l'argomento
    \param{class} di \func{res\_query}.}
  \label{tab:DNS_address_class}
\end{table}

Come accennato le tipologie di dati che sono mantenibili su un server DNS sono
diverse, ed a ciascuna di essa corrisponde 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 riferimento; 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
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Costante} & \textbf{Significato} \\
    \hline
    \hline
    \const{T\_A}     & indirizzo di una stazione.\\
    \const{T\_NS}    & server DNS autoritativo per il dominio richiesto.\\
    \const{T\_MD}    & destinazione per la posta elettronica.\\
    \const{T\_MF}    & redistributore per la posta elettronica.\\
    \const{T\_CNAME} & nome canonico.\\
    \const{T\_SOA}   & inizio di una zona di autorità.\\
    \const{T\_MB}    & nome a dominio di una casella di posta.\\
    \const{T\_MG}    & nome di un membro di un gruppo di posta.\\
    \const{T\_MR}    & nome di un cambiamento di nome per la posta.\\
    \const{T\_NULL}  & record nullo.\\
    \const{T\_WKS}   & servizio noto.\\
    \const{T\_PTR}   & risoluzione inversa di un indirizzo numerico.\\
    \const{T\_HINFO} & informazione sulla stazione.\\
    \const{T\_MINFO} & informazione sulla casella di posta.\\
    \const{T\_MX}    & server cui instradare la posta per il dominio.\\
    \const{T\_TXT}   & stringhe di testo (libere).\\
    \const{T\_RP}    & nome di un responsabile (\textit{responsible person}).\\
    \const{T\_AFSDB} & database per una cella AFS.\\
    \const{T\_X25}   & indirizzo di chiamata per X.25.\\
    \const{T\_ISDN}  & indirizzo di chiamata per ISDN.\\
    \const{T\_RT}    & router.\\
    \const{T\_NSAP}  & indirizzo NSAP.\\
    \const{T\_NSAP\_PTR}& risoluzione inversa per NSAP (deprecato).\\
    \const{T\_SIG}   & firma digitale di sicurezza.\\
    \const{T\_KEY}   & chiave per firma.\\
    \const{T\_PX}    & corrispondenza per la posta X.400.\\
    \const{T\_GPOS}  & posizione geografica.\\
    \const{T\_AAAA}  & indirizzo IPv6.\\
    \const{T\_LOC}   & informazione di collocazione.\\
    \const{T\_NXT}   & dominio successivo.\\
    \const{T\_EID}   & identificatore di punto conclusivo.\\
    \const{T\_NIMLOC}& posizionatore \textit{nimrod}.\\
    \const{T\_SRV}   & servizio.\\
    \const{T\_ATMA}  & indirizzo ATM.\\
    \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}  & trasferimento di zona di autorità.\\
    \const{T\_MAILB} & trasferimento di record di caselle di posta.\\
    \const{T\_MAILA} & trasferimento di record di server di posta.\\
    \const{T\_ANY}   & valore generico.\\
    \hline
  \end{tabular}
  \caption{Costanti identificative del tipo di record per l'argomento
    \param{type} di \func{res\_query}.}
  \label{tab:DNS_record_type}
\end{table}


L'elenco di tab.~\ref{tab:DNS_record_type} è quello di \textsl{tutti} i
\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 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}] viene usato per indicare la corrispondenza 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 corrispondenza 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 (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,
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 è 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, con il relativo significato, sono riportati in
tab.~\ref{tab:h_errno_values}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Costante} & \textbf{Significato} \\
    \hline
    \hline
    \const{HOST\_NOT\_FOUND} & l'indirizzo richiesto non è valido e la
                               macchina indicata è sconosciuta. \\
    \const{NO\_ADDRESS}      & il nome a dominio richiesto è valido, ma non ha
                               un indirizzo associato ad esso
                               (alternativamente può essere indicato come 
                               \const{NO\_DATA}). \\
    \const{NO\_RECOVERY}     & si è avuto un errore non recuperabile
                               nell'interrogazione di un server DNS. \\
    \const{TRY\_AGAIN}       & si è avuto un errore temporaneo
                               nell'interrogazione di un server DNS, si può
                               ritentare l'interrogazione in un secondo
                               tempo. \\
    \hline
  \end{tabular}
  \caption{Valori possibili della variabile \var{h\_errno}.}
  \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}
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)}

Stampa un errore di risoluzione.
\end{functions}

La funzione è l'analoga di \func{perror} e stampa sullo standard error un
messaggio di errore corrispondente al valore corrente di \var{h\_errno}, a cui
viene anteposta la stringa \param{string} passata come argomento.  La seconda
funzione è \funcd{hstrerror} ed il suo prototipo è:
\begin{functions}
\headdecl{netdb.h}
\funcdecl{const char *hstrerror(int err)}

Restituisce una stringa corrispondente ad un errore di risoluzione.
\end{functions}
\noindent che, come  l'analoga \func{strerror}, restituisce una stringa con un
messaggio di errore già formattato, corrispondente al codice passato come
argomento (che si presume sia dato da \var{h\_errno}).




\subsection{La risoluzione dei nomi a dominio}
\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
di richiesta generica ed esamineremo invece le funzioni a questo dedicate. La
prima funzione è \funcd{gethostbyname} il cui scopo è ottenere l'indirizzo di
una stazione noto il suo nome a dominio, il suo prototipo è:
\begin{prototype}{netdb.h}
{struct hostent *gethostbyname(const char *name)}

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} 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
a dominio che si vuole risolvere, in caso di successo i dati ad esso relativi
vengono memorizzati in una opportuna struttura \struct{hostent} la cui
definizione è riportata in fig.~\ref{fig:sock_hostent_struct}. 

\begin{figure}[!htb]
  \footnotesize \centering
  \begin{minipage}[c]{15cm}
    \includestruct{listati/hostent.h}
  \end{minipage}
  \caption{La struttura \structd{hostent} per la risoluzione dei nomi a
    dominio e degli indirizzi IP.}
  \label{fig:sock_hostent_struct}
\end{figure}

Quando un programma chiama \func{gethostbyname} e questa usa il DNS per
effettuare la risoluzione del nome, è con i valori contenuti nei relativi
record che vengono riempite le varie parti della struttura \struct{hostent}.
Il primo campo della struttura, \var{h\_name} contiene sempre il \textsl{nome
  canonico}, che nel caso del DNS è appunto il nome associato ad un record
\texttt{A}. Il secondo campo della struttura, \var{h\_aliases}, invece è un
puntatore ad vettore di puntatori, terminato da un puntatore nullo. Ciascun
puntatore del vettore punta ad una stringa contenente uno degli altri
possibili nomi associati allo stesso \textsl{nome canonico} (quelli che nel
DNS vengono inseriti come record di tipo \texttt{CNAME}).

Il terzo campo della struttura, \var{h\_addrtype}, indica il tipo di indirizzo
che è stato restituito, e può assumere soltanto i valori \const{AF\_INET} o
\const{AF\_INET6}, mentre il quarto campo, \var{h\_length}, indica la
lunghezza dell'indirizzo stesso in byte. 

Infine il campo \var{h\_addr\_list} è il puntatore ad un vettore di puntatori
ai singoli indirizzi; il vettore è terminato da un puntatore nullo.  Inoltre,
come illustrato in fig.~\ref{fig:sock_hostent_struct}, viene definito il campo
\var{h\_addr} come sinonimo di \code{h\_addr\_list[0]}, cioè un riferimento
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} 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\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}
  \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
  \begin{minipage}[c]{15cm}
    \includecodesample{listati/mygethost.c}
  \end{minipage}
  \normalsize
  \caption{Esempio di codice per la risoluzione di un indirizzo.}
  \label{fig:mygethost_example}
\end{figure}

Vediamo allora un primo esempio dell'uso delle funzioni di risoluzione, in
fig.~\ref{fig:mygethost_example} è riportato un estratto del codice di un
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, che comprende il trattamento delle opzioni ed una funzione
per stampare un messaggio di aiuto, è nel file \texttt{mygethost.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}, ricevendo 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: 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:
\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}

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 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
deve specificare l'indirizzo della variabile su cui la funzione dovrà salvare
il codice di errore con \param{h\_errnop} e quello su cui dovrà salvare il
puntatore 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}, può avere anche quello di \errcode{ERANGE}
qualora il buffer allocato su \param{buf} 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\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)}

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.

\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 contenente 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
sovrascritta 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
(con valori identici 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}
che contiene i risultati della ricerca, che viene allocata dinamicamente
insieme a tutto lo spazio necessario a contenere i dati in essa referenziati;
per questo motivo queste funzioni non soffrono dei problemi dovuti all'uso di
una sezione statica di memoria presenti con le precedenti \func{gethostbyname}
e \func{gethostbyaddr}.  L'uso di una allocazione dinamica però comporta anche
la necessità di deallocare esplicitamente la memoria occupata dai risultati
una volta che questi non siano più necessari; 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 però 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. 

Dopo la risoluzione dei nomi a dominio una delle ricerche più comuni è quella
sui nomi dei servizi noti (cioè \texttt{http}, \texttt{smtp}, ecc.) da
associare alle rispettive porte, le due funzioni da utilizzare per questo sono
\funcd{getservbyname} e \funcd{getservbyaddr}, che permettono rispettivamente
di ottenere il numero di porta associato ad un servizio dato il nome e
viceversa; i loro prototipi 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)} 

  Risolvono il nome di un servizio nel rispettivo numero di porta e viceversa.
       
  \bodydesc{Ritornano il puntatore ad una struttura \struct{servent} con i
    risultati in caso di successo, o \const{NULL} in caso di errore.}
\end{functions}

Entrambe le funzioni prendono come ultimo argomento una stringa \param{proto}
che indica il protocollo per il quale si intende effettuare la
ricerca,\footnote{le informazioni mantenute in \file{/etc/services} infatti
  sono relative sia alle porte usate su UDP che su TCP, occorre quindi
  specificare a quale dei due protocolli si fa riferimento.} che nel caso si
IP può avere come valori possibili solo \texttt{udp} o
\texttt{tcp};\footnote{in teoria si potrebbe avere un qualunque protocollo fra
  quelli citati in \file{/etc/protocols}, posto che lo stesso supporti il
  concetto di \textsl{porta}, in pratica questi due sono gli unici presenti.}
se si specifica un puntatore nullo la ricerca sarà eseguita su un protocollo
qualsiasi.

Il primo argomento è il nome del servizio per \func{getservbyname},
specificato tramite la stringa \param{name}, mentre \func{getservbyport}
richiede il numero di porta in \param{port}. Entrambe le funzioni eseguono una
ricerca sul file \file{/etc/services}\footnote{il \textit{Name Service Switch}
  astrae il concetto a qualunque supporto su cui si possano mantenere i
  suddetti dati. } ed estraggono i dati dalla prima riga che corrisponde agli
argomenti specificati; se la risoluzione ha successo viene restituito un
puntatore ad una apposita struttura \struct{servent} contenente tutti i
risultati), altrimenti viene restituito un puntatore nullo.  Si tenga presente
che anche in questo caso i dati vengono mantenuti in una area di memoria
statica e che quindi la funzione non è rientrante.

\begin{figure}[!htb]
  \footnotesize \centering
  \begin{minipage}[c]{15cm}
    \includestruct{listati/servent.h}
  \end{minipage}
  \caption{La struttura \structd{servent} per la risoluzione dei nomi dei
    servizi e dei numeri di porta.}
  \label{fig:sock_servent_struct}
\end{figure}

La definizione della struttura \struct{servent} è riportata in
fig.~\ref{fig:sock_servent_struct}, il primo campo, \var{s\_name} contiene
sempre il nome canonico del servizio, mentre \var{s\_aliases} è un puntatore
ad un vettore di stringhe contenenti gli eventuali nomi alternativi
utilizzabili per identificare lo stesso servizio. Infine \var{s\_port}
contiene il numero di porta e \var{s\_proto} il nome del protocollo.

Come riportato in tab.~\ref{tab:name_resolution_functions} ci sono analoghe
funzioni per la risoluzione del nome dei protocolli e delle reti; non staremo
a descriverle nei dettagli, in quanto il loro uso è molto limitato, esse
comunque hanno una struttura del tutto analoga alle precedenti, e tutti i
dettagli relativi al loro funzionamento possono essere trovati nelle
rispettive pagine di manuale.

Oltre alle funzioni di ricerca esistono delle ulteriori funzioni che prevedono
una lettura sequenziale delle informazioni mantenute nel \textit{Name Service
  Switch} (in sostanza permettono di leggere i file contenenti le informazioni
riga per riga), che sono analoghe a quelle elencate in
tab.~\ref{tab:sys_passwd_func} per le informazioni relative ai dati degli
utenti e dei gruppi.  Nel caso specifico dei servizi avremo allora le tre
funzioni \funcd{setservent}, \funcd{getservent} e \funcd{endservent} i cui
prototipi sono:
\begin{functions}
  \headdecl{netdb.h} 
  \funcdecl{void setservent(int stayopen)} 
  Apre il file \file{/etc/services} e si posiziona al suo inizio.

  \funcdecl{struct servent *getservent(void)}
  Legge la voce successiva nel file \file{/etc/services}.      

  \funcdecl{void endservent(void)} 
  Chiude il file \file{/etc/services}.

  \bodydesc{Le due funzioni \func{setservent} e \func{endservent} non
    restituiscono nulla, \func{getservent} restituisce il puntatore ad una
    struttura \struct{servent} in caso di successo e \const{NULL} in caso di
    errore o fine del file.}
\end{functions}

La prima funzione, \func{getservent}, legge una singola voce a partire dalla
posizione corrente in \file{/etc/services}, pertanto si può eseguire una
lettura sequenziale dello stesso invocandola più volte. Se il file non è
aperto provvede automaticamente ad aprirlo, nel qual caso leggerà la prima
voce. La seconda funzione, \func{setservent}, permette di aprire il file
\file{/etc/services} per una successiva lettura, ma se il file è già stato
aperto riporta la posizione di lettura alla prima voce del file, in questo
modo si può far ricominciare da capo una lettura sequenziale. L'argomento
\param{stayopen}, se diverso da zero, fa sì che il file resti aperto anche fra
diverse chiamate a \func{getservbyname} e \func{getservbyaddr}.\footnote{di
  default dopo una chiamata a queste funzioni il file viene chiuso, cosicchè
  una successiva chiamata a \func{getservent} riparte dall'inizio.}  La terza
funzione, \funcd{endservent}, provvede semplicemente a chiudere il file.

Queste tre funzioni per la lettura sequenziale di nuovo sono presenti per
ciascuno dei vari tipi di informazione relative alle reti di
tab.~\ref{tab:name_resolution_functions}; questo significa che esistono
altrettante funzioni nella forma \texttt{setXXXent}, \texttt{getXXXent} e
\texttt{endXXXent}, analoghe alle precedenti per la risoluzione dei servizi,
che abbiamo riportato in tab.~\ref{tab:name_sequential_read}.  Essendo, a
parte il tipo di informazione che viene trattato, sostanzialmente identiche
nel funzionamento e di scarso utilizzo, non staremo a trattarle una per una,
rimandando alle rispettive pagine di manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|l|l|}
    \hline
    \textbf{Informazione}&\multicolumn{3}{|c|}{\textbf{Funzioni}}\\
    \hline
    \hline
    indirizzo&\func{sethostent}&\func{gethostent}&\func{endhostent} \\
    servizio &cd te\func{setservent}&\func{getservent}&\func{endservent}\\ 
    rete     &\func{setnetent}&\func{getnetent}&\func{endnetent}\\ 
    protocollo&\func{setprotoent}&\func{getprotoent}&\func{endprotoent}\\ 
    \hline
  \end{tabular}
  \caption{Funzioni lettura sequenziale dei dati del \textit{Name Service
      Switch}.} 
  \label{tab:name_sequential_read}
\end{table}





\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 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
alcuni di questi inconvenienti,\footnote{rimane ad esempio il problema
  generico che si deve sapere in anticipo quale tipo di indirizzi IP (IPv4 o
  IPv6) corrispondono ad un certo nome a dominio.}  comunque esse non
forniscono una interfaccia sufficientemente generica.

Inoltre in genere quando si ha a che fare con i socket non esiste soltanto il
problema della risoluzione del nome che identifica la macchina, ma anche
quello del servizio a cui ci si vuole rivolgere.  Per questo motivo con lo
standard POSIX 1003.1-2001 sono state indicate come deprecate le varie
funzioni \func{gethostbyaddr}, \func{gethostbyname}, \var{getipnodebyname} e
\var{getipnodebyaddr} ed è stata introdotta una interfaccia completamente
nuova.

La prima funzione di questa interfaccia è \funcd{getaddrinfo},\footnote{la
  funzione è definita, insieme a \func{getnameinfo} che vedremo più avanti,
  nell'\href{http://www.ietf.org/rfc/rfc2553.txt} {RFC~2553}.} che combina le
funzionalità delle precedenti \func{getipnodebyname}, \func{getipnodebyaddr},
\func{getservbyname} e \func{getservbyport}, consentendo di ottenere
contemporaneamente sia la risoluzione di un indirizzo simbolico che del nome
di un servizio; il suo prototipo è:
\begin{functions}
  \headdecl{netdb.h} 
  \headdecl{sys/socket.h} 
  \headdecl{netdb.h} 

  \funcdecl{int getaddrinfo(const char *node, const char *service, const
    struct addrinfo *hints, struct addrinfo **res)}

  Esegue una risoluzione di un nome a dominio e di un nome di servizio.

  \bodydesc{La funzione restituisce 0 in caso di successo o un codice di
    errore diverso da zero in caso di fallimento.}
\end{functions}

La funzione prende come primo argomento il nome della macchina che si vuole
risolvere, specificato tramite la stringa \param{node}. Questo argomento,
oltre ad un comune nome a dominio, può indicare anche un indirizzo numerico in
forma \textit{dotted-decimal} per IPv4 o in formato esadecimale per IPv6.  Si
può anche specificare il nome di una rete invece che di una singola macchina.
Il secondo argomento, \param{service}, specifica invece il nome del servizio
che si intende risolvere. Per uno dei due argomenti si può anche usare il
valore \const{NULL}, nel qual caso la risoluzione verrà effettuata soltanto
sulla base del valore dell'altro.

Il terzo argomento, \param{hints}, deve essere invece un puntatore ad una
struttura \struct{addrinfo} usata per dare dei \textsl{suggerimenti} al
procedimento di risoluzione riguardo al protocollo o del tipo di socket che si
intenderà utilizzare; \func{getaddrinfo} infatti permette di effettuare
ricerche generiche sugli indirizzi, usando sia IPv4 che IPv6, e richiedere
risoluzioni sui nomi dei servizi indipendentemente dal protocollo (ad esempio
TCP o UDP) che questi possono utilizzare.

\begin{figure}[!htb]
  \footnotesize \centering
  \begin{minipage}[c]{15cm}
    \includestruct{listati/addrinfo.h}
  \end{minipage}
  \caption{La struttura \structd{addrinfo} usata nella nuova interfaccia POSIX
    per la risoluzione di nomi a dominio e servizi.}
  \label{fig:sock_addrinfo_struct}
\end{figure}

La struttura \struct{addrinfo}, la cui definizione\footnote{la definizione è
  ripresa direttamente dal file \texttt{netdb.h} in questa struttura viene
  dichiarata, la pagina di manuale riporta \type{size\_t} come tipo di dato
  per il campo \var{ai\_addrlen}, qui viene usata quanto previsto dallo
  standard POSIX, in cui viene utilizzato \type{socklen\_t}; i due tipi di
  dati sono comunque equivalenti.} è riportata in
fig.~\ref{fig:sock_addrinfo_struct}, viene usata sia in ingresso, per passare
dei valori di controllo alla funzione, che in uscita, per ricevere i
risultati. Il primo campo, \var{ai\_flags}, è una maschera binaria di bit che
permettono di controllare le varie modalità di risoluzione degli indirizzi,
che viene usato soltanto in ingresso. I tre campi successivi \var{ai\_family},
\var{ai\_socktype}, e \var{ai\_protocol} contengono rispettivamente la
famiglia di indirizzi, il tipo di socket e il protocollo, in ingresso vengono
usati per impostare una selezione (impostandone il valore nella struttura
puntata da \param{hints}), mentre in uscita indicano il tipo di risultato
contenuto nella struttura. 

Tutti i campi seguenti vengono usati soltanto in uscita; il campo
\var{ai\_addrlen} indica la dimensione della struttura degli indirizzi
ottenuta come risultato, il cui contenuto sarà memorizzato nella struttura
\struct{sockaddr} posta all'indirizzo puntato dal campo \var{ai\_addr}. Il
campo \var{ai\_canonname} è un puntatore alla stringa contenente il nome
canonico della macchina, ed infine, quando la funzione restituisce più di un
risultato, \var{ai\_next} è un puntatore alla successiva struttura
\struct{addrinfo} della lista.

Ovviamente non è necessario dare dei suggerimenti in ingresso, ed usando
\const{NULL} come valore per l'argomento \param{hints} si possono compiere
ricerche generiche.  Se però si specifica un valore non nullo questo deve
puntare ad una struttura \struct{addrinfo} precedentemente allocata nella
quale siano stati opportunamente impostati i valori dei campi
\var{ai\_family}, \var{ai\_socktype}, \var{ai\_protocol} ed \var{ai\_flags}.

I due campi \var{ai\_family} e \var{ai\_socktype} prendono gli stessi valori
degli analoghi argomenti della funzione \func{socket}; in particolare per
\var{ai\_family} si possono usare i valori di tab.~\ref{tab:net_pf_names} ma
sono presi in considerazione solo \const{PF\_INET} e \const{PF\_INET6}, mentre
se non si vuole specificare nessuna famiglia di indirizzi si può usare il
valore \const{PF\_UNSPEC}.  Allo stesso modo per \var{ai\_socktype} si possono
usare i valori illustrati in sez.~\ref{sec:sock_type} per indicare per quale
tipo di socket si vuole risolvere il servizio indicato, anche se i soli
significativi sono \const{SOCK\_STREAM} e \const{SOCK\_DGRAM}; in questo caso,
se non si vuole effettuare nessuna risoluzione specifica, si potrà usare un
valore nullo.

Il campo \var{ai\_protocol} permette invece di effettuare la selezione dei
risultati per il nome del servizio usando il numero identificativo del
rispettivo protocollo di trasporto (i cui valori possibili sono riportati in
\file{/etc/protocols}); di nuovo i due soli valori utilizzabili sono quelli
relativi a UDP e TCP, o il valore nullo che indica di ignorare questo campo
nella selezione.

Infine l'ultimo campo è \var{ai\_flags}; che deve essere impostato come una
maschera binaria; i bit di questa variabile infatti vengono usati per dare
delle indicazioni sul tipo di risoluzione voluta, ed hanno valori analoghi a
quelli visti in sez.~\ref{sec:sock_name_services} per \func{getipnodebyname};
il valore di \var{ai\_flags} può essere impostata con un OR aritmetico delle
costanti di tab.~\ref{tab:ai_flags_values}, ciascuna delle quali identifica un
bit della maschera.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Costante} & \textbf{Significato} \\
    \hline
    \hline
    \const{AI\_PASSIVE}    & viene utilizzato per ottenere un indirizzo in
                             formato adatto per una successiva chiamata a
                             \func{bind}. Se specificato quando si è usato 
                             \const{NULL} come valore per \param{node} gli
                             indirizzi restituiti saranno inizializzati al
                             valore generico (\const{INADDR\_ANY} per IPv4 e
                             \const{IN6ADDR\_ANY\_INIT} per IPv6), altrimenti
                             verrà usato l'indirizzo dell'interfaccia di
                             \textit{loopback}. Se invece non è impostato gli
                             indirizzi verrano restituiti in formato adatto ad
                             una chiamata a \func{connect} o \func{sendto}.\\
    \const{AI\_CANONNAME}  & richiede la restituzione del nome canonico della
                             macchina, che verrà salvato in una stringa il cui
                             indirizzo sarà restituito nel campo
                             \var{ai\_canonname} della prima struttura
                             \struct{addrinfo} dei risultati. Se il nome
                             canonico non è disponibile al suo posto
                             viene restituita una copia di \param{node}. \\ 
    \const{AI\_NUMERICHOST}& se impostato il nome della macchina specificato
                             con \param{node} deve essere espresso in forma
                             numerica, altrimenti sarà restituito un errore
                             \const{EAI\_NONAME} (vedi
                             tab.~\ref{tab:addrinfo_error_code}), in questo
                             modo si evita ogni chiamata alle funzioni di
                             risoluzione.\\ 
    \const{AI\_V4MAPPED}   & stesso significato dell'analoga di
                             tab.~\ref{tab:sock_getipnodebyname_flags}.\\  
    \const{AI\_ALL}        & stesso significato dell'analoga di
                             tab.~\ref{tab:sock_getipnodebyname_flags}.\\ 
    \const{AI\_ADDRCONFIG} & stesso significato dell'analoga di
                             tab.~\ref{tab:sock_getipnodebyname_flags}.\\ 
    \hline
  \end{tabular}
  \caption{Costanti associate ai bit del campo \var{ai\_flags} della struttura 
    \struct{addrinfo}.} 
  \label{tab:ai_flags_values}
\end{table}

Come ultimo argomento di \func{getaddrinfo} deve essere passato un puntatore
ad una variabile (di tipo puntatore ad una struttura \struct{addrinfo}) che
verrà utilizzata dalla funzione per riportare (come \textit{value result
  argument}) i propri risultati. La funzione infatti è rientrante, ed alloca
autonomamente tutta la memoria necessaria in cui verranno riportati i
risultati della risoluzione.  La funzione scriverà in \param{res} il puntatore
iniziale ad una \textit{linked list} di strutture di tipo \struct{addrinfo}
contenenti tutte le informazioni ottenute.

La funzione restituisce un valore nullo in caso di successo, o un codice in
caso di errore. I valori usati come codice di errore sono riportati in
tab.~\ref{tab:addrinfo_error_code}; dato che la funzione utilizza altre
funzioni e chiamate al sistema per ottenere il suo risultato in generale il
valore di \var{errno} non è significativo, eccetto il caso in cui si sia
ricevuto un errore di \const{EAI\_SYSTEM}, nel qual caso l'errore
corrispondente è riportato tramite \var{errno}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Costante} & \textbf{Significato} \\
    \hline
    \hline
    \const{EAI\_FAMILY}  & la famiglia di indirizzi richiesta non è
                           supportata. \\ 
    \const{EAI\_SOCKTYPE}& il tipo di socket richiesto non è supportato. \\
    \const{EAI\_BADFLAGS}& il campo \var{ai\_flags} contiene dei valori non
                           validi. \\
    \const{EAI\_NONAME}  & il nome a dominio o il servizio non sono noti,
                           viene usato questo errore anche quando si specifica
                           il valore \const{NULL} per entrambi gli argomenti
                           \param{node} e \param{service}. \\
    \const{EAI\_SERVICE} & il servizio richiesto non è disponibile per il tipo
                           di socket richiesto, anche se può esistere per
                           altri tipi di socket. \\
    \const{EAI\_ADDRFAMILY}& la rete richiesta non ha nessun indirizzo di rete
                           per la famiglia di indirizzi specificata. \\
    \const{EAI\_NODATA}  & la macchina specificata esiste, ma non ha nessun
                           indirizzo di rete definito. \\
    \const{EAI\_MEMORY}  & è stato impossibile allocare la memoria necessaria
                           alle operazioni. \\
    \const{EAI\_FAIL}    & il DNS ha restituito un errore di risoluzione  
                           permanente. \\
    \const{EAI\_AGAIN}   & il DNS ha restituito un errore di risoluzione  
                           temporaneo, si può ritentare in seguito. \\
    \const{EAI\_SYSTEM}  & c'è stato un errore di sistema, si può controllare
                           \var{errno} per i dettagli. \\
%    \hline
% estensioni GNU, trovarne la documentazione
%    \const{EAI\_INPROGRESS}& richiesta in corso. \\
%    \const{EAI\_CANCELED}& la richiesta è stata cancellata.\\
%    \const{EAI\_NOTCANCELED}& la richiesta non è stata cancellata. \\
%    \const{EAI\_ALLDONE} & tutte le richieste sono complete. \\
%    \const{EAI\_INTR}    & richiesta interrotta. \\
    \hline
  \end{tabular}
  \caption{Costanti associate ai valori dei codici di errore della funzione
    \func{getaddrinfo}.} 
  \label{tab:addrinfo_error_code}
\end{table}

Come per i codici di errore di \func{gethostbyname} anche in questo caso è
fornita una apposita funzione, analoga di \func{strerror}, che consente di
utilizzarli direttamente per stampare a video un messaggio esplicativo; la
funzione è \func{gai\_strerror} ed il suo prototipo è:
\begin{functions}
  \headdecl{netdb.h} 

  \funcdecl{const char *gai\_strerror(int errcode)}

  Fornisce il messaggio corrispondente ad un errore di \func{getaddrinfo}.

  \bodydesc{La funzione restituisce il puntatore alla stringa contenente il
    messaggio di errore.}
\end{functions}

La funzione restituisce un puntatore alla stringa contenente il messaggio
corrispondente dal codice di errore \param{errcode} ottenuto come valore di
ritorno di \func{getaddrinfo}.  La stringa è allocata staticamente, ma essendo
costante, ed accessibile in sola lettura, questo non comporta nessun problema
di rientranza della funzione.

Dato che ad un certo nome a dominio possono corrispondere più indirizzi IP
(sia IPv4 che IPv6), e che un certo servizio può essere fornito su protocolli
e tipi di socket diversi, in generale, a meno di non aver eseguito una
selezione specifica attraverso l'uso di \param{hints}, si otterrà una diversa
struttura \struct{addrinfo} per ciascuna possibilità.  Ad esempio se si
richiede la risoluzione del servizio \textit{echo} per l'indirizzo
\texttt{www.truelite.it}, e si imposta \const{AI\_CANONNAME} per avere anche
la risoluzione del nome canonico, si avrà come risposta della funzione la
lista illustrata in fig.~\ref{fig:sock_addrinfo_list}.

\begin{figure}[!htb]
  \centering
  \includegraphics[width=10cm]{img/addrinfo_list}
  \caption{La \textit{linked list} delle strutture \struct{addrinfo}
    restituite da \func{getaddrinfo}.}
  \label{fig:sock_addrinfo_list}
\end{figure}

Come primo esempio di uso di \func{getaddrinfo} vediamo un programma
elementare di interrogazione del resolver basato questa funzione, il cui corpo
principale è riportato in fig.~\ref{fig:mygetaddr_example}. Il codice completo
del programma, compresa la gestione delle opzioni in cui è gestita l'eventuale
inizializzazione dell'argomento \var{hints} per restringere le ricerche su
protocolli, tipi di socket o famiglie di indirizzi, è disponibile nel file
\texttt{mygetaddr.c} dei sorgenti allegati alla guida.

\begin{figure}[!htb]
  \footnotesize \centering
  \begin{minipage}[c]{15cm}
    \includecodesample{listati/mygetaddr.c}
  \end{minipage}
  \normalsize
  \caption{Esempio di codice per la risoluzione di un indirizzo.}
  \label{fig:mygetaddr_example}
\end{figure}

Il corpo principale inizia controllando (\texttt{\small 1--5}) il numero di
argomenti passati, che devono essere sempre due, e corrispondere
rispettivamente all'indirizzo ed al nome del servizio da risolvere. A questo
segue la chiamata (\texttt{\small 7}) alla funzione \func{getaddrinfo}, ed il
successivo controllo (\texttt{\small 8--11}) del suo corretto funzionamento,
senza il quale si esce immediatamente stampando il relativo codice di errore.

Se la funzione ha restituito un valore nullo il programma prosegue
inizializzando (\texttt{\small 12}) il puntatore \var{ptr} che sarà usato nel
sucessivo ciclo (\texttt{\small 14--35}) di scansione della lista delle
strutture \struct{addrinfo} restituite dalla funzione. Prima di eseguire
questa scansione (\texttt{\small 12}) viene stampato il valore del nome
canonico che è presente solo nella prima struttura.

La scansione viene ripetuta (\texttt{\small 14}) fintanto che si ha un
puntatore valido. La selezione principale è fatta sul campo \var{ai\_family},
che stabilisce a quale famiglia di indirizzi fa riferimento la struttura in
esame. Le possibilità sono due, un indirizzo IPv4 o IPv6, se nessuna delle due
si verifica si provvede (\texttt{\small 27--30}) a stampare un messaggio di
errore ed uscire.\footnote{questa eventualità non dovrebbe mai verificarsi,
  almeno fintanto che la funzione \func{getaddrinfo} lavora correttamente.}

Per ciascuno delle due possibili famiglie di indirizzi si estraggono le
informazioni che poi verranno stampate alla fine del ciclo (\texttt{\small
  31--34}). Il primo caso esaminato (\texttt{\small 15--21}) è quello degli
indirizzi IPv4, nel qual caso prima se ne stampa l'indentificazione
(\texttt{\small 16}) poi si provvede a ricavare la struttura degli indirizzi
(\texttt{\small 17}) indirizzata dal campo \var{ai\_addr}, eseguendo un
opportuno casting del puntatore per poter estrarre da questa la porta
(\texttt{\small 18}) e poi l'indirizzo (\texttt{\small 19}) che verrà
convertito con una chiamata ad \func{inet\_ntop}.

La stessa operazione (\texttt{\small 21--27}) viene ripetuta per gli indirizzi
IPv6, usando la rispettiva struttura degli indirizzi. Si noti anche come in
entrambi i casi per la chiamata a \func{inet\_ntop} si sia dovuto passare il
puntatore al campo contenente l'indirizzo IP nella struttura puntata dal campo
\var{ai\_addr}.\footnote{il meccanismo è complesso a causa del fatto che al
  contrario di IPv4, in cui l'indirizzo IP può essere espresso con un semplice
  numero intero, in IPv6 questo deve essere necessariamente fornito come
  struttura, e pertanto anche se nella struttura puntata da \var{ai\_addr}
  sono presenti direttamente i valori finali, per l'uso con \func{inet\_ntop}
  occorre comunque passare un puntatore agli stessi (ed il costrutto
  \code{\&addr6->sin6\_addr} è corretto in quanto l'operatore \texttt{->} ha
  on questo caso precedenza su \texttt{\&}).}

Una volta estratte dalla struttura \struct{addrinfo} tutte le informazioni
relative alla risoluzione richiesta e stampati i relativi valori, l'ultimo
passo (\texttt{\small 34}) è di estrarre da \var{ai\_next} l'indirizzo della
eventuale successiva struttura presente nella lista e ripetere il ciclo, fin
tanto che, completata la scansione, questo avrà un valore nullo e si potrà
terminare (\texttt{\small 36}) il programma.

Si tenga presente che \func{getaddrinfo} non garantisce nessun particolare
ordinamento della lista delle strutture \struct{addrinfo} restituite, anche se
usualmente i vari indirizzi IP (se ne è presente più di uno) sono forniti
nello stesso ordine in cui vengono inviati dal server DNS. In particolare
nulla garantisce che vengano forniti prima i dati relativi ai servizi di un
determinato protocollo o tipo di socket, se ne sono presenti di diversi.  Se
allora utilizziamo il nostro programma potremo verificare il risultato:
\begin{Verbatim}
[piccardi@gont sources]$ ./mygetaddr -c  gapil.truelite.it echo
Canonical name sources2.truelite.it
IPv4 address:
        Indirizzo 62.48.34.25
        Protocollo 6
        Porta 7
IPv4 address:
        Indirizzo 62.48.34.25
        Protocollo 17
        Porta 7
\end{Verbatim}
%$

Una volta estratti i risultati dalla \textit{linked list} puntata da
\param{res} se questa non viene più utilizzata si dovrà avere cura di
disallocare opportunamente tutta la memoria, per questo viene fornita
l'apposita funzione \funcd{freeaddrinfo}, il cui prototipo è:
\begin{functions}
  \headdecl{netdb.h} 

  \funcdecl{void freeaddrinfo(struct addrinfo *res)}

  Libera la memoria allocata da una precedente chiamata a \func{getaddrinfo}.

  \bodydesc{La funzione non restituisce nessun codice di errore.}
\end{functions}

La funzione prende come unico argomento il puntatore \param{res}, ottenuto da
una precedente chiamata a \func{getaddrinfo}, e scandisce la lista delle
strutture per liberare tutta la memoria allocata. Dato che la funzione non ha
valori di ritorno deve essere posta molta cura nel passare un valore valido
per \param{res}.

Si tenga presente infine che se si copiano i risultati da una delle strutture
\struct{addrinfo} restituite nella lista indicizzata da \param{res}, occorre
avere cura di eseguire una \index{\textit{deep~copy}}\textit{deep copy} in cui
si copiano anche tutti i dati presenti agli indirizzi contenuti nella
struttura \struct{addrinfo}, perché una volta disallocati i dati con
\func{freeaddrinfo} questi non sarebbero più disponibili. 

Anche la nuova intefaccia definita da POSIX prevede una nuova funzione per
eseguire la risoluzione inversa e determinare nomi di servizi e di dominio
dati i rispettivi valori numerici. La funzione che sostituisce le varie
\func{gethostbyname}, \func{geipnodebyname} e \func{getservname} è
\funcd{getnameinfo}, ed il suo prototipo è:
\begin{functions}
  \headdecl{sys/socket.h}
  \headdecl{netdb.h}

  \funcdecl{int getnameinfo(const struct sockaddr *sa, socklen\_t salen, char
    *host, size\_t hostlen, char *serv, size\_t servlen, int flags)}

  Risolve il contenuto di una struttura degli indirizzi in maniera
  indipendente dal protocollo.

  \bodydesc{La funzione restituisce 0 in caso di successo e un codice di
    errore diverso da zero altrimenti.}
\end{functions}

La principale caratteristica di \func{getnameinfo} è che la funzione è in
grado di eseguire una risoluzione inversa in maniera indipendente dal
protocollo; il suo primo argomento \param{sa} infatti è il puntatore ad una
struttura degli indirizzi generica, che può contenere sia indirizzi IPv4 che
IPv6, la cui dimensione deve comunque essere specificata con l'argomento
\param{salen}. 

I risultati della funzione saranno restituiti nelle due stringhe puntate da
\param{host} e \param{serv}, che dovranno essere state precedentemente
allocate per una lunghezza massima che deve essere specificata con gli altri
due argomenti \param{hostlen} e \param{servlen}. Si può, quando non si è
interessati ad uno dei due, passare il valore \const{NULL} come argomento,
così che la corrispondente informazione non verrà richiesta. Infine l'ultimo
argomento \param{flags} è una maschera binaria i cui bit consentono di
impostare le modalità con cui viene eseguita la ricerca, e deve essere
specificato attraverso l'OR aritmetico dei valori illustrati in
tab.~\ref{tab:getnameinfo_flags}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Costante} & \textbf{Significato} \\
    \hline
    \hline
    \const{NI\_NOFQDN}     & richiede che venga restituita solo il nome della
                             macchina all'interno del dominio al posto del
                             nome completo (FQDN).\\
    \const{NI\_NUMERICHOST}& richiede che venga restituita la forma numerica
                             dell'indirizzo (questo succede sempre se il nome
                             non può essere ottenuto).\\ 
    \const{NI\_NAMEREQD}   & richiede la restituzione di un errore se il nome
                             non può essere risolto.\\
    \const{NI\_NUMERICSERV}& richiede che il servizio venga restituito in
                             forma numerica (attraverso il numero di porta).\\
    \const{NI\_DGRAM}      & richiede che venga restituito il nome del
                             servizio su UDP invece che quello su TCP per quei
                             pichi servizi (porte 512-214) che soni diversi
                             nei due protocolli.\\
    \hline
  \end{tabular}
  \caption{Costanti associate ai bit dell'argomento \param{flags} della  
    funzione \func{getnameinfo}.} 
  \label{tab:getnameinfo_flags}
\end{table}

La funzione ritorna zero in caso di successo, e scrive i propri risultati agli
indirizzi indicati dagli argomenti \param{host} e \param{serv} come stringhe
terminate dal carattere NUL, a meno che queste non debbano essere troncate
qualora la loro dimensione ecceda quelle specificate dagli argomenti
\param{hostlen} e \param{servlen}. Sono comunque definite le due costanti
\const{NI\_MAXHOST} e \const{NI\_MAXSERV}\footnote{in Linux le due costanti
  sono definite in \file{netdb.h} ed hanno rispettivamente il valore 1024 e
  12.}  che possono essere utilizzate come limiti massimi.  In caso di errore
viene restituito invece un codice che assume gli stessi valori illustrati in
tab.~\ref{tab:addrinfo_error_code}.

A questo punto possiamo fornire degli esempi di utilizzo della nuova
interfaccia, adottandola per le precedenti implementazioni del client e del
server per il servizio \textit{echo}; dato che l'uso delle funzioni appena
illustrate (in particolare di \func{getaddrinfo}) è piuttosto complesso,
essendo necessaria anche una impostazione diretta dei campi dell'argomento
\param{hints}, provvederemo una interfaccia semplificata per i due casi visti
finora, quello in cui si specifica nel client un indirizzo remoto per la
connessione al server, e quello in cui si specifica nel server un indirizzo
locale su cui porsi in ascolto.

La prima funzione è allora \func{sockconn} che restituisce un socket connesso
all'indirizzo ed al servizio specificati come argomenti; la funzione prende
poi altri due argomenti aggiuntivi per indicare il protocollo da usare ed il
tipo di socket. Il corpo della funzione è riportato in
fig.~\ref{fig:sockconn_code}, ed il codice completo è nel file
\file{sockconn.c} nei sorgenti allegati alla guida.

\begin{figure}[!htb]
  \footnotesize \centering
  \begin{minipage}[c]{15cm}
    \includecodesample{listati/sockconn.c}
  \end{minipage}
  \normalsize
  \caption{Il codice della funzione \func{sockconn}.}
  \label{fig:sockconn_code}
\end{figure}

La funzione prende quattro argomenti, i primi due sono le stringhe che
indicano il nome della macchina a cui collegarsi ed il relativo servizio;
seguono il protocollo da usare (in forma numerica) ed il tipo di socket (al
solito specificato con i valori illustrati in sez.~\ref{sec:sock_type}). La
funzione ritorna il filde descriptor associato al socket in caso di successo,
o -1 in caso di errore. Come si vede la funzione prevede anche ad alcune
stampe in maniera diretta (il che la rende non utilizzabile all'interno di un
demone).

Una volta definite le variabili necessarie (\texttt{\small 3--5}) la funzione
prima (\texttt{\small 7}) azzera il contenuto della struttura \var{hint} e poi
provvede (\texttt{\small 8--10}) ad inizializzarne i valori necessari per la
chiamata (\texttt{\small 11}) a \func{getaddrinfo}. Di quest'ultima si
controlla (\texttt{\small 12}) il codice di ritorno, in modo da stampare
(\texttt{\small 13--15}) un avviso di errore ed uscire in caso di errore.  Se
la risoluzioen del nome ha successo si provvede (\texttt{\small 18--22}) ad
aprire il socket, ed a connettersi ad esso (\texttt{\small 24--28}); in
entrambi casi si gestisce il caso di errore. Infine prima di ritornare
(\texttt{\small 30}) il file descriptor del socket si provvede (\texttt{\small
  29}) a liberare le strutture \struct{addrinfo} allocate da
\func{getaddrinfo}.

Si noti come la funzione si limiti ad usare i valori contenuti nella prima
struttura \struct{addrinfo} ritornata da \func{getaddrinfo}, non eseguendo
ulteriori tentativi sulle successive in caso di errore. Un'altra
caratteristica della funzione è che è del tutto irrilevante se la struttura
ritornata usa indirizzi IPv6 o IPv4, in quanto si fa uso direttamente dei dati
relativi alle strutture degli indirizzi di \struct{addrinfo} che sono
\textsl{opachi} rispetto all'uso della funzione \func{connect}.

Per usare questa funzione possiamo allora modificare ulteriormente il nostro
programma client per il servizio \textit{echo}; in questo caso rispetto al
codice usato finora per collegarsi (vedi fig.~\ref{fig:TCP_echo_client_1})
avremo una semplificazione per cui il corpo principale del nostro client
diventerà quello illustrato in fig.~\ref{fig:TCP_echo_fifth}, in cui le
chiamate a \func{socket}, \func{inet\_pton} e \func{connect} sono sostituite
da una singola chiamata a \func{sockconn}. Inoltre il nuovo client (il cui
codice completo è nel file \file{TCP\_echo\_fifth.c} dei sorgenti allegati)
consente di utilizzare come argomento del programma un nome a dominio al posto
dell'indirizzo numerico, e può utilizzare sia indirizzi IPv4 che IPv6.

\begin{figure}[!htb]
  \footnotesize \centering
  \begin{minipage}[c]{15cm}
    \includecodesample{listati/TCP_echo_fifth.c}
  \end{minipage}
  \normalsize
  \caption{Il nuovo codice per la connessione del client \textit{echo}.}
  \label{fig:TCP_echo_fifth}
\end{figure}

La seconda funzione di ausilio è \func{sockbind}, il cui corpo principale è
riportato in fig.~\ref{fig:sockbind_code} (al solito il sorgente completo è
nel file \file{sockbind.c} dei sorgenti allegati alla guida). Come si può
notare la funzione è del tutto analoga alla precedente \func{sockconn}, e
prende gli stessi argomenti, però invece di eseguire una connessione con
\func{connect} si limita a chiamare \func{bind} per collegare il socket ad una
porta. 

Dato che la funzione è pensata per utilizzata da un server ci si può chiedere
a quale scopo mantenere l'argomento \param{host} quando l'indirizzo di questo
è usualmente noto. Si ricordi però quanto detto in
sez.~\ref{sec:TCP_func_bind}, relativamente al significato della scelta di un
indirizzo specifico come argomento di \func{bind}, che consente di porre il
server in ascolto su uno solo dei possibili diversi indirizzi presenti su di
una macchina. 

Se non si vuole che la funzione esegua \func{bind} su un indirizzo specifico,
ma utilizzi l'indirizzo generico, occorrerà avere cura di passare un valore
\const{NULL} come valore per l'argomento \var{host}, l'uso del valore
\const{AI\_PASSIVE} serve ad ottenere il valore generico nella rispettiva
struttura degli indirizzi.

\begin{figure}[!htb]
  \footnotesize \centering
  \begin{minipage}[c]{15cm}
    \includecodesample{listati/sockbind.c}
  \end{minipage}
  \normalsize
  \caption{Il codice della funzione \func{sockbind}.}
  \label{fig:sockbind_code}
\end{figure}


Come già detto la funzione è analoga a \func{sockconn} ed inizia azzerando ed
inizializzando (\texttt{\small 6-11}) opportunamente la struttura \var{hint}
con i valori ricevuti come argomenti, soltanto che in questo caso si è usata
(\texttt{\small 8}) una impostazione specifica dei flag di \var{hint} usando
\const{AI\_PASSIVE} per indicare che il socket sarà usato per una apertura
passiva. Per il resto la chiamata a \func{getaddrinfo} (\texttt{\small 12-17})
e quella a \func{socket} (\texttt{\small 19--23}) sono identiche, mentre si è
sostituita (\texttt{\small 25--29}) la chiamata a \func{connect} con una
chiamata a \func{bind}. La conclusione (\texttt{\small 30--31}) della funzione
è identica. Si noti come anche in questo caso si siano inserite le stampe
degli errori sullo standard output, nonostante la funzione possa essere
invocata da un demone. In realtà questo non è un problema in quanto se la
funzione non ha successo il programma deve uscire immediatamente prima di
essere posto in background, e può quindi scrivere gli errori direttamente
sullo standard output.

Con l'uso di questa funzione si può modificare anche il codice del nostro
server \textit{echo}, che rispetto a quanto illustrato nella versione iniziale
di fig.~\ref{fig:TCP_echo_server_first_code} viene modificato nella forma
riportata in fig.~\ref{fig:TCP_echod_third}. In questo caso il socket su cui
porsi in ascolto viene ottenuto (\texttt{\small 15--18}) da \func{sockbind}
che si cura anche della eventuale risoluzione di un indirizzo specifico sul
quale si voglia far ascoltare il server.

\begin{figure}[!htb]
  \footnotesize \centering
  \begin{minipage}[c]{15cm}
    \includecodesample{listati/TCP_echod_third.c}
  \end{minipage}
  \normalsize
  \caption{Nuovo codice per l'apertura passiva del server \textit{echo}.}
  \label{fig:TCP_echod_third}
\end{figure}



\section{Le opzioni dei socket}
\label{sec:TCP_sock_options}

Finora abbiamo trattato i socket nel loro comportamento più comune, è però
possibile attivare alcune modalità diverse di funzionamento degli stessi

Dato che la maggior parte delle opzioni dei socket sono relative ai socket
 TCP, ed hanno poi significato analogo quando usate con altri socket, abbiamo
preferito trattare l'argomento in generale in questa sezione piuttosto che nel
capitolo dedicato alla trattazione generica dei socket.

\section{Altre funzioni di controllo}
\label{sec:TCP_sock_ctrl}





%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "gapil"
%%% End: 
