a.a. 2003/04 Università degli studi di Salerno Laurea in Informatica Prof. Vincenzo Auletta [email protected]http://www.dia.unisa.it/professori/auletta/ Conversioni di Nomi ed Indirizzi 1 Interazione con il DNS Il DNS consente di convertire dinamicamente nomi di dominio in indirizzi IP e viceversa L’interazione con il name server avviene tramite l’API resolver l’applicazione interagisce con il name server utilizzando le funzioni dell’API il funzionamento delle funzioni è modificabile tramite file di configurazione /etc/resolv.conf /etc/hosts, /etc/services, ecc. Il resolver è utilizzato in generale per calcolare corrispondenze tra nomi ed indirizzi nomi di servizio e numeri di porta 2 Funzioni del resolver #include <netdb.h> struct hostent* gethostbyname(const char* hostname); struct hostent* gethostbyaddr(const char* addr, size_t len, int family); Restituisce NULL se errore puntatore diverso da NULL se OK Permettono di interrogare il resolver per effettuare conversioni da nomi ad indirizzi gethostbyname: nome indirizzo gethostbyaddr: indirizzo nome 3 Struttura hostent Le funzioni gethostbyname e gethostbyaddr restituiscono puntatori ad oggetti hostent allocati staticamente struct hostent { char* h_name; /* nome canonico */ char** h_aliases; /* elenco di alias */ int h_addrtype; /* tipo di indirizzo */ int h_length; /* lunghezza dell’indirizzo */ char** h_addr_list; /* elenco indirizzi */ }; #define h_addr h_addr_list[0] h_aliases e h_addr_list sono array di stringhe terminati da una stringa nulla
9
Embed
Dipartimento di Informatica - Conversioni di Nomi ed Il DNS … · 2003. 12. 2. · 4 Esempio oggetto restituito da gethostbyname per il nome koala un nome canonico (bsdi), due alias
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
a.a. 2003/04
Università degli studi di SalernoLaurea in Informatica
Interazione con il DNSIl DNS consente di convertire dinamicamente nomi di dominio in indirizzi IP e viceversaL’interazione con il name server avviene tramite l’API resolver
l’applicazione interagisce con il name server utilizzando le funzioni dell’APIil funzionamento delle funzioni è modificabile tramite file di configurazione
/etc/resolv.conf/etc/hosts, /etc/services, ecc.
Il resolver è utilizzato in generale per calcolare corrispondenze tra nomi ed indirizzi
nomi di servizio e numeri di porta
2
Funzioni del resolver#include <netdb.h>struct hostent* gethostbyname(const char* hostname);
struct hostent* gethostbyaddr(const char* addr, size_t len, int family);
RestituisceNULL se errorepuntatore diverso da NULL se OK
Permettono di interrogare il resolver per effettuare conversioni da nomi ad indirizzi
gethostbyname: nome indirizzogethostbyaddr: indirizzo nome
3
Struttura hostentLe funzioni gethostbyname e gethostbyaddrrestituiscono puntatori ad oggetti hostent allocati staticamente
struct hostent {char* h_name; /* nome canonico */char** h_aliases; /* elenco di alias */int h_addrtype; /* tipo di indirizzo */int h_length; /* lunghezza dell’indirizzo */char** h_addr_list; /* elenco indirizzi */
};#define h_addr h_addr_list[0]
h_aliases e h_addr_list sono array di stringhe terminati da una stringa nulla
4
Esempiooggetto restituito da gethostbyname per il nome koala
un nome canonico (bsdi), due alias (koala e panda) e tre indirizzi IP 4 (140.252.1.11, 140.252.3.54, 140.252.4.54)
h_nameh_aliasesh_addrtypeh_lengthh_addr_list
bsdi
koalapandaNULL
AF_INET4
140.252.1.11140.252.3.54140.252.4.54NULL 5
Funzionamento del ResolverIl resolver può operare sia localmente che interagendo con il DNS
il file /etc/resolv.conf contiene gli indirizzi dei name server da contattare e le regole di espansioneil file /etc/hosts contiene un elenco delle corrispondenze nome/indirizzo
il file di configurazione (/etc/resolv.conf) stabilisce le regole di funzionamento del resolver
per default contatta prima i name server e poi legge il file locale
6
ErroriIn caso di errore le funzioni del resolverscrivono un codice nella variabile h_errno
la funzione hstrerror() legge il valore di h_errno e restituisce un messaggio di errore appropriatoi valori che può assumere h_errno sono definiti in <netdb.h>
HOST_NOT_FOUND Il nome specificato è sconosciutoTRY_AGAIN Un errore temporaneo si è verificato su un name serverNO_RECOVERY Un errore irrimediabile si è verificato su un name serverNO_ADDRESS (NO_DATA) Il nome specificato è valido ma non ha un indirizzo IP
Permettono di interrogare il resolver per effettuare conversioni nomi di servizi/numeri di porta
getservbyname: nome portagetservbyaddr: porta nome
Il resolver non interagisce con il DNS ma legge soltanto il contenuto di un file locale (/etc/services)
8
Struttura serventLe funzioni getservbyname e getservbyaddrrestituiscono puntatori ad oggetti servent allocati staticamente
struct servent {char* s_name; /* nome ufficiale del servizio */char** s_aliases; /* elenco di alias */int s_port; /* numero di porta */char* s_proto; /* protocollo da utilizzare */
};
9
Altri Tipi di Interrogazioni#include <netdb.h>struct netent* getnetbyname(const char* netname);
consentono di assegnare dei nomi a reti e protocolli
funzioni poco utilizzateIl resolver legge i file locali (/etc/networks e/etc/protocols)
10
Altre Funzioni#include <netdb.h>void sethostent(int flag);
void endhostent(void);
#include <unistd.h>#include <sys/utsname.h>int gethostname(char* name, size_t len); /* name contiene il risultato */
sethostent(true) consente di utilizzare TCP per interrrogare il DNSendhostent() ripristina l’uso di UDPgethostname() restituisce il nome dell’host corrente
stesso risultato ottenuto con uname()11
Client daytime con resolver – 1 1.legge da
linea di comando il nome del server e del servizio
2.recupera l’elenco di indirizzi IP del server
3.recupera il numero di porta ed il tipo di protocollo
Consente di fare interrogazioni sia per nomi di host che di servizi contemporaneamente
Legge dalla struttura puntata da hints il tipo di informazioni richiesterestituisce il risultato nella lista puntata da result
18
Struttura addrinfostruct addrinfo {
int ai_flags; /* nome canonico */int ai_family; /* famiglia di indirizzi */int ai_socktype; /* tipo di socket */int ai_protocol; /* tipo di protocollo */size_t ai_addrlength; /* lunghezza di ai_addr */
char* ai_canonname; /* puntatore al nome ufficiale */struct sockaddr *ai_addr; /* puntatore all’indirizzostruct addrinfo *ai_next; /* puntatore al nodo succ */
};
Tutti i puntatori indirizzano memoria allocata dinamicamente
L’applicazione deve preoccuparsi di rilasciare la memoriaLa funzione freeaddrinfo() rilascia tutta la memoria associata ad un oggetto addrinfo
19
Esempio Richiediamo informazioni sul servizio daytime e l’host koala
Specifichiamo che vogliamo indirizzi IP 4 e trasporto TCP
ai_flagai_familyai_socktypeai_protocolai_addrlen
AF_INET
0
AI_CANONNAME
SOCK_STREAM
ai_canonnameai_addrai_next
0NULLNULLNULL
HINTS
bsdi.xyz.com
ai_flagai_familyai_socktypeai_protocolai_addrlen
AF_INET
0
0
SOCK_STREAM
ai_canonnameai_addrai_next
16
140.252.1.11AF_INET 7
prossimo nodo
RESULTS
20
ErroriIn caso di errore la funzione getaddrinfo() restituisce un intero nonnegativo
la funzione gai_strerror() legge il valore restituito dalla funzione e restituisce un messaggio di errore appropriato
EAI_ADDRFAMILY tipo di indirizzo non supportato per nameEAI_AGAIN un errore temporaneo si è verificato su un name serverEAI_FAIL un errore irrecuperabile si è verificato su un name serverEAI_BADFLAGS valore non corretto di ai_flagsEAI_FAMILY valore di ai_family non supportatoEAI_MEMORY errore di allocazione della memoriaEAI_NODATA nessun indirizzo associato a nameEAI_NONAME name o service non conosciutoEAI_SERVICE service non supportato per ai_socktypeEAI_SOCKTYPE ai_socktype non supportatoEAI_SYSTEM errore di sistema restituito in errno 21
Funzione getnameinfo#include <netdb.h>int getaddrinfo(const struct sockaddr* sockaddr, socklen_t addrlen,
char* host, size_t hostlen,char* serv, size_t servlen, int flags);
Restituisce-1 se errore0 se OK
Consente di trasformare l’indirizzo del socket contenuto in sockaddr in due stringhe
host contiene il nome dell’host e serv contiene il nome del serviziohostlen e servlen sono le lunghezze allocate per le stringheflags consente di modificare il comportamento di default della funzione
22
Utilizzo di getaddrinfo()E’ possibile costruire delle funzioni che nascondono all’applicazione tutti i dettagli relativi alla gestione del socket
L’applicazione usa solo i nomi dell’host e del servizioLe funzioni utilizzano le informazioni restituite da getaddrinfo() per invocare le funzioni sul socket
Useremo le seguenti funzionitcp_connect() (client TCP)tcp_listen() (server TCP)udp_client() (client UDP non connesso)udp_connect() (client UDP connesso)udp_server() (server UDP)
23
Schema BaseTutte le funzioni adotteranno il seguente schema
Leggono da linea di comando nome dell’host e del servizio
È possibile anche specificare l’indirizzo IP o il numero di porta
Invocano getaddrinfo()Scorrono la lista di risultati e provano ad utilizzare ognuno degli indirizzi
Appena ne trovano uno funzionante esconoSe nessuno funziona escono con un errore
err_sys("errore in setsockopt");if (bind(listend, risp->ai_addr, risp->ai_addrlen) < 0)
/* ignora questo indirizzo e chiude il descrittore. */break;
} while ( (risp = risp->ai_next) != NULL);if (risp == NULL) err_quit("errore in tcp_listen per %s:%s", host, serv);if( listen(listend, LISTENQ) < 0 ) err_sys("errore in listen"); (4)if (addrlenp) *addrlenp = risp->ai_addrlen; (5)freeaddrinfo(backup); (6)return(listend);
}
3. Setta il socket per poter utilizzare una porta occupata4. Se socket() e bind() riescono chiama la listen()5. Restituisce in addrlenp un puntatore alla lunghezza dell’indirizzo
assegnato al socket6. Dealloca la memoria dinamica
28
Client daytime con tcp_connect() –1
1. legge da linea di comando il nome del server e del servizio
2.recupera l’elenco di indirizzi IP del server
3.recupera il numero di porta ed il tipo di protocollo
err_sys("errore in setsockopt");if( (pid = fork()) == 0 ) {
/* il processo figlio chiude il socket di ascolto */ticks = time(NULL);snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));if( write(connd, buff, strlen(buff)) != strlen(buff) )
err_sys("errore in write");/* il processo figlio chiude il socket di connessione */exit(0);
}/* il processo padre chiude il socket di connessione */
}
32
Client e Server UDPDal sito è possibile scaricare
il codice delle funzioni udp_client(), udp_server() e udp_connect()
logica simile a tcp_connect() e tcp_listen()
Il codice di un client ed un server UDP indipendenti dal protocollo