From: Simone Piccardi Date: Sun, 2 May 2004 22:38:52 +0000 (+0000) Subject: Altro materiale sulla risoluzione dei nomi, e inizio della trattazione di X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=00edc2dae3c235b4ccd51f5ec5fc2eae61331776 Altro materiale sulla risoluzione dei nomi, e inizio della trattazione di gethostbyname. --- diff --git a/img/resolver.dia b/img/resolver.dia new file mode 100644 index 0000000..d935609 Binary files /dev/null and b/img/resolver.dia differ diff --git a/listati/hostent.h b/listati/hostent.h new file mode 100644 index 0000000..2c34947 --- /dev/null +++ b/listati/hostent.h @@ -0,0 +1,8 @@ +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses */ +} +#define h_addr h_addr_list[0] /* for backward compatibility */ diff --git a/sockctrl.tex b/sockctrl.tex index 66015ac..5103df1 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -17,25 +17,202 @@ indirizzi, le impostazioni delle varie propriet di controllo che vanno ad operare su di essi. - -\section{La gestione degli indirizzi} -\label{sec:sock_addresses} +\section{La risoluzione dei nomi} +\label{sec:sock_name_resolution} Negli esempi precedenti abbiamo sempre identificato le singole macchine attraverso indirizzi numerici, sfruttando al più le funzioni di conversione elementari illustrate in sez.~\ref{sec:sock_addr_func} che permettono di passare da un indirizzo espresso in forma dotted decimal ad un numero. Vedremo -in questa sezione le funzioni utilizzate per poter identificare le varie -proprietà di un indirizzo (numero IP e porta) attraverso dei nomi simbolici -che vengano automaticamente tradotti nei rispettivi valori numerici. +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{Il sistema del \textit{resolver}} +\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}. 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 freccie 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ò interrogarene altri) o la richiesta ad altri server per i quali +sia fornito il supporto, come LDAP. + +La configurazione del resolver attiene più alla amministrazione di sistema che +alla programmazione, ciò non di meno, prima di trattare le varie funzioni che +vale la pena farne una panoramica. Originariamente la configurazione +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}, il file di configurazione principale è +\file{/etc/resolv.conf} e contiene in sostanza l'elenco dei server DNS da +contattare, a cui si affianca \file{/etc/host.conf} per indicare l'ordine in +cui eseguire la risoluzione dei nomi (se usare prima i valori di +\file{/etc/hosts} o il DNS); tralasciamo i dettagli che si trovano nelle +relative pagine di manuale. + +Con il tempo però è divenuto possibile fornire diversi sostituti per +l'utilizzo dei file statici, ed ai nomi a dominio si sono aggiunti altri nomi, +come quelli associati alle reti ed ai gruppi di macchine definiti dal servizio +NIS, o quelli dei protocolli e dei servizi mantenuti nei file statici +\file{/etc/protocols} e \file{/etc/services}, tutte informazioni che +normalmente non si trovano su un DNS, ma possono essere accedute in maniera +centralizzata su opportuni server (ad esempio su LDAP) in grado di mantenerle. + +Questo ha portato alla creazione di un sistema di risoluzione più ampio, il +\textit{Name Service Switch} di cui il \textit{resolver} viene a costituire un +sottoinsieme. Questo sistema, che si applica anche alla risoluzioni fra nomi +di utenti e gruppi e relativi identificatori, permette di definire in maniera +generica (attraverso una serie di librerie dinamiche) 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, ed è controllato dal +file \file{/etc/nsswitch.conf}. Anche per questo si può fare riferimento alle +pagine di manuale ed al relativo capitolo nel manuale \cite{glibc} delle +\textsl{glibc}. + +In ogni caso, qualunque sia la modalità con cui ricevono i dati o il supporto +su cui vengono mantenuti, dal punto di vista di un programma che deve +effettuare la risoluzione di un nome, tutto quello che conta sono le funzioni +che il \textit{resolver} mette a disposizione, e sono queste quelle che +tratteremo nelle sezioni successive. + + + +\subsection{La risoluzione dei nomi a dominio} +\label{sec:sock_gethostbyname} + +Dato che la principale funzionalità del \textit{resolver} resta quella di +risolvere i nomi a dominio in indirizzi IP, vedremo per prime 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} contente 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}. In caso di +insuccesso l'errore viene segnalato da un valore nullo del puntatore, ma in +questo caso, a differenza delle funzioni viste finora, non viene utilizzata la +variabile \var{errno} per riportare un codice di errore, in quanto questo è +dipende solo dalle sottostanti chiamate al sistema e non avere nessun +significato nell'indicare quale parte del procedimento di risoluzione è +fallita. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includestruct{listati/hostent.h} + \end{minipage} + \caption{La struttura \structd{hostent} .} + \label{fig:sock_hostent_struct} +\end{figure} + +Per questo motivo all'interno del resolver è stata definita una apposita +variabile di errore, \var{h\_errno} che viene utilizzata dalle funzioni di +libreria per indicare quale problema ha causato il fallimento della +risoluzione. Ad essa si può accedere una volta che la si dichiara con: +\includecodesnip{listati/herrno.c} +ed i valori che può assumere sono i seguenti: +\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}} +\item[\const{HOST\_NOT\_FOUND}] l'indirizzo richiesto non è valido e la + macchina indicata è sconosciuta. +\item[\const{NO\_ADDRESS}] il nome a dominio richiesto è valido, ma non ha un + indirizzo associato ad esso. +\item[\const{NO\_RECOVERY}] si è avuto un errore non recuperabile + nell'interrogazione di un server DNS. +\item[\const{TRY\_AGAIN}] si è avuto un errore temporaneo nell'interrogazione + di un server DNS, si può ritentare l'interrogazione in un secondo tempo. +\end{basedescript} + + +Per capire meglio il contenuto della struttura \struct{hostent} conviene +spendere alcune parole sul funzionamento del DNS. Questo in sostanza è un +enorme database distribuito interrogando il quale si possono avere una serie +di informazioni la principale delle quali è la corrispondenza fra un nome (a +dominio) ed indirizzo IP. Un server DNS contiene comunque una serie di altre +informazioni; ciascuna voce nel database viene chiamata \textit{resource + record} e vi è associato un certo \textsl{tipo}, identificato da una sigla. +Per quanto ci interessa i \textit{resource record} che vengono utilizzati dal +\textit{resolver} sono sostanzialmente i seguenti: +\begin{basedescript}{\desclabelwidth{1.2cm}\desclabelstyle{\nextlinelabel}} +\item[\texttt{A}] indica la corripondenza 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}] chiamato in questo modo dato che la dimensione è quattro + volte quella di un indirizzo IPv4, questo record contiene la corrispondenza + fra un nome a dominio ed un indirizzo IPv6. +\item[\texttt{PTR}] per provvedere la mappatura inversa fra un indirizzo IP ed + un nome a dominio si utilizza invece questo tipo di record (il cui nome sta + per \textit{pointer}). +\item[\texttt{CNAME}] qualora si abbiamo più nomi con i quali si voglia + indicare lo stesso indirizzo (ad esempio \texttt{www.truelite.it}, o + \texttt{sources.truelite.it}, che comunque fanno sempre riferimento alla + macchina \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 (quello associato al record + \texttt{A}). +\end{basedescript} + +Quando un programma chiama \func{gethostbyname} e questa usa il DNS per +effettuare la risoluzione del nome, è con i valori di questi 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 invece è un puntatore ad vettore +di puntatori, terminato da un puntatore nullo, alle strighe che contengono +tutti i possibili altri nomi (quelli che nel DNS sarebbero record +\texttt{CNAME}). + +Il terzo campo, \var{h\_addrtype}, indica il tipo di indirizzo che è stato +restituito, e può essere solo \const{AF\_INET} o \const{AF\_INET6}, mentre il +quarto campo, e \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 +per compatibilità il campo \var{h\_addr} corrispondente al puntatore al primo +indirizzo della lista. + +In sostanza + + -Effettueremo in questa sezione una trattazione completa delle funzioni -utilizzate per la gestione degli indirizzi dei socket.