L'objectif de cette section est de fournir un programme
minimaliste qui affiche les adresses IP associées à un hôte ou à une interface
réseau. Le code source de ce programme fait donc appel à la
fonction getaddrinfo()
. Cette
fonction offre de nombreuses options mais son utilisation reste
simple. Elle s'appuie sur l'enregistrement de type addrinfo
. Ce type permet de
constituer une liste chaînée des différentes adresses
disponibles.
Note | |
---|---|
Cette section suit la démarche proposée dans le livre Beej's Guide to Network Programming. Relativement au code proposé dans cet excellent guide, les modifications apportées ici sont marginales. Elles ont cependant une incidence sur l'organisation du code des sections suivantes. |
Le programme showip est
constitué d'un appel à la fonction getaddrinfo()
suivi d'une boucle de parcours des
enregistrements renseignés lors de l'appel. Cette boucle de
parcours est reprise ensuite dans tous les autres programmes de ce
document.
Appel à getaddrinfo()
struct addrinfo hints, *res, *p; <snipped/> memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // IPv4 ou IPv6 hints.ai_socktype = SOCK_STREAM; // Une seule famille de socket if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); return 2; }
On utilise 3 variables de type |
|
Les options choisies pour l'appel à |
|
Les paramètres du programme showip sont passés directement en ligne de
commande de façon classique ; |
|
Le pointeur |
|
En cas d'erreur sur l'interprétation de la chaîne fournie dans
|
Boucle de parcours des enregistrements addrinfo
<snipped/> printf("IP addresses for %s:\n\n", argv[1]); p = res; while (p != NULL) { // Identification de l'adresse courante <snipped/> // Adresse suivante p = p->ai_next; }
Le pointeur |
|
Si cette adresse vaut |
|
On fait pointer |
Cette technique de parcours des enregistrements de type
addrinfo
est reprise dans
les sections suivantes pour définir les conditions d'ouverture des
«prises» réseau ou sockets.
Exemple d'utilisation du programme showip
L'exemple donné ci-dessous montre que deux adresses
IP sont assoicées au nom d'hôte
vm1.fake.domain
.
$
./showip.o vm1.fake.domain
IP addresses for vm1.fake.domain:
IPv6: 2001:db8:feb2:10::11
IPv4: 192.0.2.11
Code source complet du programme showip.c
/* * showip.c -- Affiche les adresses IP correspondant à un nom d'hôte donné en * ligne de commande * * This code was first published in the * Beej's Guide to Network Programming * Credit has to be given back to beej(at)beej.us */ #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> int main (int argc, char *argv[]) { struct addrinfo hints, *res, *p; void *addr; int status; char ipstr[INET6_ADDRSTRLEN], ipver; if (argc != 2) { fprintf(stderr, "usage: showip hostname\n"); return 1; } memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // IPv4 ou IPv6 hints.ai_socktype = SOCK_STREAM; // Une seule famille de socket if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); return 2; } printf("IP addresses for %s:\n\n", argv[1]); p = res; while (p != NULL) { // Identification de l'adresse courante if (p->ai_family == AF_INET) { // IPv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; addr = &(ipv4->sin_addr); ipver = '4'; } else { // IPv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; addr = &(ipv6->sin6_addr); ipver = '6'; } // Conversion de l'adresse IP en une chaîne de caractères inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); printf(" IPv%c: %s\n", ipver, ipstr); // Adresse suivante p = p->ai_next; } // Libération de la mémoire occupée par les enregistrements freeaddrinfo(res); return 0; }