From def262af3493f8e141a94b4efe09a8d84b8f7c70 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 5 Sep 2004 16:17:46 +0000 Subject: [PATCH] Aggiunta gethostbyaddr e corretti dei riferimenti alle strutture per gli indirizzi IP --- listati/sockaddr_in6.h | 2 +- sockctrl.tex | 99 +++++++++++++++++++++++++++++++++++------- socket.tex | 24 +++++----- 3 files changed, 97 insertions(+), 28 deletions(-) diff --git a/listati/sockaddr_in6.h b/listati/sockaddr_in6.h index 34bc216..f6fe615 100644 --- a/listati/sockaddr_in6.h +++ b/listati/sockaddr_in6.h @@ -1,5 +1,5 @@ struct sockaddr_in6 { - uint16_t sin6_family; /* AF_INET6 */ + sa_family_t sin6_family; /* AF_INET6 */ in_port_t sin6_port; /* port number */ uint32_t sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ diff --git a/sockctrl.tex b/sockctrl.tex index 1dbc855..3adaa2b 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -678,7 +678,9 @@ IPv4, se si vogliono ottenere degli indirizzi IPv6 occorrer l'opzione \const{RES\_USE\_INET6} nel campo \texttt{\_res.options} e poi chiamare \func{res\_init} (vedi sez.~\ref{sec:sock_resolver_functions}) per modificare le opzioni del resolver; dato che questo non è molto comodo è stata -definita un'altra funzione, \funcd{gethostbyname2}, il cui prototipo è: +definita\footnote{questa è una estensione fornita dalle \acr{glibc}, + disponibile anche in altri sistemi unix-like.} un'altra funzione, +\funcd{gethostbyname2}, il cui prototipo è: \begin{functions} \headdecl{netdb.h} \headdecl{sys/socket.h} @@ -762,10 +764,24 @@ ci sono precauzioni particolari da prendere.\footnote{volendo essere pignoli avuto un errore con \func{gethostbyname}, ma si ricordi che la sicurezza non è mai troppa.} -Le funzioni illustrate finora hanno un difetto fondamentale, utilizzando una -area di memoria interna per allocare il contenuto della struttura -\struct{hostent} non possono essere rientranti. Per questo motivo ne sono -state definite delle versioni alternative rientranti, al solito queste sono +Le funzioni illustrate finora hanno un difetto: utilizzando una area di +memoria interna per allocare i contenuti della struttura \struct{hostent} non +possono essere rientranti. Questo comporta anche che in due successive +chiamate i dati potranno essere sovrascritti. Si tenga presente poi che +copiare il contenuto della sola struttura non è sufficiente per salvare tutti +i dati, in quanto questa contiene puntatori ad altri dati, che pure possono +essere sovrascritti; per questo motivo, se si vuole salvare il risultato di +una chiamata, occorrerà eseguire quella che si chiama una +\index{\textit{deep~copy}}\textit{deep copy}.\footnote{si chiama così quella + tecnica per cui, quando si deve copiare il contenuto di una struttura + complessa (con puntatori che puntano ad altri dati, che a loro volta possono + essere puntatori ad altri dati) si deve copiare non solo il contenuto della + struttura, ma eseguire una scansione per risolvere anche tutti i puntatori + contenuti in essa (e così via se vi sono altre sottostrutture con altri + puntatori) e copiare anche i dati da questi referenziati.} + +Per ovviare a questi problemi nelle \acr{glibc} sono definite anche delle +versioni rientranti delle precedenti funzioni, al solito queste sono caratterizzate dall'avere un suffisso \texttt{\_r}, pertanto avremo le due funzioni \funcd{gethostbyname\_r} e \funcd{gethostbyname2\_r} i cui prototipi sono: @@ -785,16 +801,16 @@ sono: negativo in caso di errore.} \end{functions} -Gli argomenti \param{name} (e \param{af} per \func{gethostbyname2}) hanno lo -stesso significato visto in precedenza. Tutti gli altri argomenti hanno lo +Gli argomenti \param{name} (e \param{af} per \func{gethostbyname2\_r}) hanno +lo stesso significato visto in precedenza. Tutti gli altri argomenti hanno lo stesso significato per entrambe le funzioni. Per evitare l'uso di variabili globali si dovrà allocare preventivamente una struttura \struct{hostent} in cui ricevere il risultato, passandone l'indirizzo alla funzione nell'argomento -\param{ret}. Inoltre, dato che \struct{hostent} contiene solo dei puntatori, -dovrà essere allocato anche un buffer in cui le funzioni possano scrivere -tutti i dati del risultato dell'interrogazione, l'indirizzo e la lunghezza di -questo buffer devono essere indicati con gli argomenti \param{buf} e -\param{buflen}. +\param{ret}. Inoltre, dato che \struct{hostent} contiene dei puntatori, dovrà +essere allocato anche un buffer in cui le funzioni possano scrivere tutti i +dati del risultato dell'interrogazione da questi puntati; l'indirizzo e la +lunghezza di questo buffer devono essere indicati con gli argomenti +\param{buf} e \param{buflen}. Gli ultimi due argomenti vengono utilizzati per avere indietro i risultati come \index{\textit{value~result~argument}}\textit{value result argument}, si @@ -816,9 +832,10 @@ con un buffer di dimensione maggiore. Una delle caratteristiche delle interrogazioni al servizio DNS è che queste sono normalmente eseguite con il protocollo UDP, ci sono casi in cui si preferisce che vengano usate connessioni permanenti con il protocollo TCP. Per -ottenere questo sono previste delle funzioni apposite (oltre che delle opzioni -in \var{\_\_res.options}); la prima è \funcd{sethostent}, il cui prototipo -è: +ottenere\footnote{si potrebbero impostare direttamente le opzioni di + \var{\_\_res.options}, ma queste funzioni permettono di semplificare la + procedura.} questo sono previste delle funzioni apposite; la prima è +\funcd{sethostent}, il cui prototipo è: \begin{prototype}{netdb.h} {void sethostent(int stayopen)} @@ -827,6 +844,58 @@ 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 contentente il valore dell'indirizzo IP (o IPv6) che si +vuole risolvere. L'uso del tipo \type{char *} per questo argomento ha è +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, 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 si successo, un puntatore ad una struttura +\struct{hostent}, solo che la ricerca è fatta richiedendo al DNS un record di +tipo \texttt{PTR}. In caso di errore al solito viene usata la variabile +\var{h\_errno} per restituire un opportuno codice. In questo caso il valore +dei vari campi \var{h\_addr\_list} viene inizializzato al valore passa \subsection{Altre funzioni di gestione dei nomi} diff --git a/socket.tex b/socket.tex index 4b450aa..968a18c 100644 --- a/socket.tex +++ b/socket.tex @@ -466,7 +466,7 @@ come struttura (un resto di una implementazione precedente in cui questa era una \direct{union} usata per accedere alle diverse classi di indirizzi) che direttamente come intero. In \file{netinet/in.h} vengono definite anche alcune costanti che identificano alcuni indirizzi speciali, riportati in -tab.~\ref{tab:TCP_ipv4_addr}. +tab.~\ref{tab:TCP_ipv4_addr}, che reincontreremo più avanti. Infine occorre sottolineare che sia gli indirizzi che i numeri di porta devono essere specificati in quello che viene chiamato \textit{network order}, cioè @@ -500,17 +500,17 @@ il campo \var{sin6\_port} il campo \var{sin6\_flowinfo} è a sua volta diviso in tre parti di cui i 24 bit inferiori indicano l'etichetta di flusso, i successivi 4 bit la priorità e gli ultimi 4 sono riservati. Questi valori fanno riferimento ad alcuni campi -specifici dell'header dei pacchetti IPv6 (vedi sez.~\ref{sec:IP_ipv6head}) ed il -loro uso è sperimentale. - -Il campo \var{sin6\_addr} contiene l'indirizzo a 128 bit usato da IPv6, infine -il campo \var{sin6\_scope\_id} è un campo introdotto in Linux con il kernel -2.4, per gestire alcune operazioni riguardanti il multicasting. - -Si noti che questa struttura ha una dimensione maggiore della struttura -\struct{sockaddr} generica vista in fig.~\ref{fig:sock_sa_gen_struct}, quindi -occorre stare attenti a non avere fatto assunzioni riguardo alla possibilità -di contenere i dati nelle dimensioni di quest'ultima. +specifici dell'header dei pacchetti IPv6 (vedi sez.~\ref{sec:IP_ipv6head}) ed +il loro uso è sperimentale. + +Il campo \var{sin6\_addr} contiene l'indirizzo a 128 bit usato da IPv6, +espresso da un vettore di 16 byte. Infine il campo \var{sin6\_scope\_id} è un +campo introdotto in Linux con il kernel 2.4, per gestire alcune operazioni +riguardanti il multicasting. Si noti infine che \struct{sockaddr\_in6} ha una +dimensione maggiore della struttura \struct{sockaddr} generica di +fig.~\ref{fig:sock_sa_gen_struct}, quindi occorre stare attenti a non avere +fatto assunzioni riguardo alla possibilità di contenere i dati nelle +dimensioni di quest'ultima. \subsection{La struttura degli indirizzi locali} -- 2.30.2