[successivo] [precedente] [inizio] [fine] [indice generale]


Capitolo 5.   Risoluzione dei nomi

La comunicazione tra i processi in rete è possibile se si specificano gli indirizzi dei due nodi che comunicano; come detto in precedenza essi sono costituiti da coppie IP:porta.

Quindi è fondamentale conoscere gli indirizzi IP dei nodi in cui vengono eseguiti i processi e per questo possono essere molto utili le funzioni che permettono di risalire a tali informazioni partendo dal nome delle macchine, cioè quelle che eseguono la «risoluzione dei nomi».

Tali funzioni sono definite in <netdb.h> insieme alle strutture dati che utilizzano.

5.1   Nome della macchina ospite

La prima funzione esaminata in verità non riguarda la risoluzione dei nomi ma può essere comunque utile perché permette di conoscere il nome della macchina in cui il processo che la invoca è in esecuzione; si tratta della funzione gethostname() definita in <unistd.h> e il cui prototipo è:

int gethostname(char *nome, size_t lun)

//nome è il nome che si ottiene in risposta;
//lun dimensione della variabile nome.

Ritorna 0 se non ci sono errori, altrimenti -1 (ad esempio se nome è un puntatore non valido).

5.2   Ricavare l'indirizzo IP dal nome

Ci sono diverse funzioni utili a risolvere il nome in un indirizzo IP; iniziamo da gethostbyname() che ha questo prototipo:

struct hostent *gethostbyname(const char *nome)

//trova l'indirizzo associato al nome nome.

Ritorna il puntatore ad una struttura di tipo hostent con i dati associati al nome, oppure un puntatore nullo in caso di errore, nel qual caso la variabile esterna h_errno può valere:

mentre errno può valere:

La struttura hostent è definita nel seguente modo:

struct hostent {
    char    *h_name;        // nome ufficiale dell'host 
    char    **h_aliases;    // lista degli alias  
    int     h_addrtype;     // tipo di indirizzo 
    int     h_length;       // lunghezza dell'indirizzo 
    char    **h_addr_list;  // lista degli indirizzi 
} 
#define h_addr  h_addr_list[0]  // primo indirizzo della lista,
                                // serve per motivi di compatibilità 

La funzione gethostbyname() interroga un servente DNS oppure usa il contenuto del file /etc/hosts a seconda di quanto indicato in /etc/resolv.conf e valorizza i campi della struttura hostent in questa maniera:

La funzione gethostbyname() permette di ottenere solo indirizzi IPv4; per ottenere anche indirizzi IPv6 si utilizza gethostbyname2() che ha il seguente prototipo:

struct hostent *gethostbyname2(const char *nome, int af)

//trova l'indirizzo di tipo af associato a nome.

Questa funzione è del tutto analoga alla precedente; l'unica differenza è il parametro af da impostare come AF_INET o AF_INET6 per stabilire il tipo di indirizzi che si vuole in risposta.

Occorre ricordare infine che esistono anche le funzioni gethostbyname_r() e gethostbyname2_r() che sono le versioni rientranti delle due funzioni appena esaminate e delle quali non vengono forniti dettagli.

5.3   Risoluzione inversa

Per ottenere il nome di una stazione se è noto il suo indirizzo IPv4 o IPv6 si può usare la funzione gethostbyaddr() cha ha il seguente prototipo:

struct hostent *gethostbyaddr(const char *ind, int lun, int tipo)

//trova il nome associato all'indirizzo ind;
//lun è la dimensione dell'indirizzo (4 o 16);
//tipo è il tipo di indirizzo (AF_INET o AF_INET6).

Ritorna il puntatore a una struttura hostent in caso di successo o NULL in caso di errore; in quest'ultimo caso valgono gli stessi codici per h_errno e errno visti per la funzione gethostbyname() con in più, per errno, il valore EFAULT (ind puntatore non valido).

L'unico campo della struttura hostent da considerare è h_name contenente il nome cercato; la funziona comunque valorizza anche il primo campo di h_addr_list con l'indirizzo ind.

Si deve notare che, malgrado nel prototipo ind sia un puntatore a carattere, esso deve essere definito come struttura in_addr (o in6_addr) su cui fare il casting a puntatore a carattere.

5.4   Risoluzione con connessioni TCP

La risoluzione dei nomi tramite un servente DNS viene effettuata solitamente con il protocollo UDP (sulla porta 53); nel caso si voglia invece ricorrere al TCP si può utilizzare la funzione sethostent() il cui prototipo è:

void sethostent(int val)

//con val=1 attiva l'uso di connessioni TCP per interrogare il DNS. 

Per disattivare l'uso del TCP si usa invece endhostent() così definita:

void endhostent(void)

//disattiva l'uso di connessioni TCP per interrogare il DNS.

5.5   Nomi dei servizi noti

Nel caso sia utile utile conoscere il numero di porta associato ad un servizio di rete o viceversa si possono usare le due funzioni getservbyname() e getservbyport() con i seguenti prototipi:

struct servent *getservbyname(const char *nome, const char *proto)

//restituisce la porta associata al servizio nome.

struct servent *getservbyport(int porta, const char *proto)

//restituisce il nome di servizio associato a porta.

Ritornano il puntatore ad una struttura servent in caso di successo, oppure NULL se c'è errore.

In entrambe c'è l'argomento proto che indica il protocollo su cui effettuare la ricerca e che può essere udp, tcp o NULL, nel qual caso la ricerca viene fatta su un protocollo qualsiasi.

Le due funzioni si servono di quanto contenuto nel file /etc/services per elaborare la risposta che viene restituita nella struttura servent così definita:

struct servent { 
     char    *s_name;        // nome del servizio 
     char    **s_aliases;    // lista di nomi ulteriori 
     int     s_port;         // porta 
     char    *s_proto;       // protocollo 
} 

Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome risoluzione_dei_nomi.html

[successivo] [precedente] [inizio] [fine] [indice generale]

Valid ISO-HTML!

CSS validator!