Provided by:
manpages-fr-dev_2.80.1-1_all 
NOM
getaddrinfo, freeaddrinfo, gai_strerror - Traduction d’adresses et de
services réseau.
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
void freeaddrinfo(struct addrinfo *res);
const char *gai_strerror(int errcode);
DESCRIPTION
Pour un noeud node et un service donné, getaddrinfo() renvoie une
structure (ou plus) contenant les valeurs qui peuvent être utilisées
par les appels système bind(2) et connect(2) pour créer une socket d’un
client ou d’un serveur. La fonction getaddrinfo() combine la
fonctionnalité fournie par les fonctions getservbyname(3) et
getservbyport(3) en une interface unique, mais à l’inverse de ces
fonctions, getaddrinfo() est ré-entrante et permet aux programmes
d’éliminer la dépendance envers IPV4 ou IPV6.
La structure addrinfo utilisée par cette fonction contient les membres
suivants :
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
La fonction getaddrinfo() fait pointer res vers une liste de structures
addrinfo nouvellement allouées, chaînées par leurs membres ai_next. La
liste peut contenir plusieurs structures addrinfo pour plusieurs
raisons, par exemple : l’hôte fonctionne en « multi-home », ou le même
service est disponible sur plusieurs types de sockets (une socket
SOCK_STREAM et une socket SOCK_DGRAM par exemple).
Le paramètre hints pointe vers une structure addrinfo qui spécifie des
critères pour la sélection des structures d’adresse de socket renvoyées
dans la liste pointée par res. Si ce paramètre n’est pas NULL, il doit
pointer sur une structure addrinfo dont les membres ai_family,
ai_socktype, et ai_protocol indiquent les types de socket préférés.
AF_UNSPEC dans le membre ai_family indique que toute famille de
protocole (IPv4 ou IPv6, par exemple) est acceptable. De même, un 0
dans les membres ai_socktype ou ai_protocol indique que tout type de
socket ou de protocole est admis. Le membre ai_flags indique des
options supplémentaires décrites ci-dessous. Divers attributs sont
regroupés par un OU binaire. Tous les autres membres de l’argument
hints doivent contenir 0 ou être des pointeurs NULL. Une valeur NULL
pour hints est équivalente à configurer ai_socktype et ai_protocol à
0 ; ai_family à AF_UNSPEC ; et ai_flags à
(AI_V4MAPPED | AI_ADDRCONFIG).
L’argument node ou l’argument service peuvent être NULL, mais pas les
deux. node indique soit une adresse réseau en format numérique (décimal
pointé pour l’IPv4, hexadécimal pour l’IPv6), soit un nom d’hôte, dont
l’adresse réseau est alors résolue. Si le membre hints.ai_flags
contient l’attribut AI_NUMERICHOST alors le paramètre node devra être
une adresse réseau numérique. L’attribut AI_NUMERICHOST empêche toute
tentative, éventuellement longue, de résolution de nom d’hôte.
La fonction getaddrinfo() crée une liste chaînée de structures
addrinfo, une pour chaque adresse réseau soumise aux restrictions
imposées par l’argument hints. Le membre ai_canonname de la première de
ces structures addrinfo pointera vers le nom officiel de l’hôte si
hints.ai_flags contient l’attribut AI_CANONNAME. Les membres ai_family,
ai_socktype, et ai_protocol indiquent les paramètres de création de la
socket (c’est-à-dire qu’ils ont la même signification que leurs
homologues de l’appel système socket(2)). Un pointeur vers l’adresse de
la socket est placé dans le membre ai_addr, et la longueur de l’adresse
de la socket, en octets, est inscrite dans le membre ai_addrlen de la
structure.
La fonction getaddrinfo() renvoie les adresses de sockets autant en
IPv4 qu’en IPv6 (ai_family contiendra AF_INET ou AF_INET6).
Si l’argument node est NULL, l’adresse réseau de chaque structure
socket est initialisée en fonction de l’attribut AI_PASSIVE, défini
dans hints.ai_flags. L’adresse réseau de chaque structure sera non
spécifiée si l’attribut AI_PASSIVE est défini. Ceci est utilisé par les
serveurs qui désirent accepter les connexions depuis n’importe quelle
adresse. L’adresse réseau sera remplie avec l’adresse de boucle locale
si l’attribut AI_PASSIVE n’est pas utilisé. Ceci est utilisé par les
clients qui désirent se connecter sur un serveur fonctionnant sur le
même hôte.
Si hints.ai_flags inclut le drapeau AI_ADDRCONFIG, alors des adresses
IPv4 sont renvoyées dans la liste pointée par result seulement si le
système local possède au moins une adresse IPv4 configurée. Des
adresses IPv6 sont seulement renvoyées si le système local possède au
moins une adresse IPv6 configurée.
Si hint.ai_flags spécifie le drapeau AI_V4MAPPED, et si hints.ai_family
a été spécifié avec AF_INET6 et qu’aucune adresse IPv6 correspondante
n’a pu être trouvée, alors des adresses IPv4 au format IPv6 sont
renvoyées dans la liste pointée par result. Si AI_V4MAPPED et AI_ALL
sont spécifiés dans hints.ai_family, des adresses IPv6 et des adresses
IPv4 au format IPv6 sont renvoyées dans la liste pointée par result.
AI_ALL est ignoré si AI_V4MAPPED n’est pas aussi spécifié.
service définit le numéro de port de l’adresse réseau de chaque
structure socket. Si service est NULL, le numéro de port n’est pas
initialisé. Si AI_NUMERICSERV est spécifié dans hints.ai_flags et si
service n’est pas NULL, alors service doit pointer vers une chaîne
contenant le numéro de port. Ce drapeau est utilisé pour inhiber le
service de résolution des noms dans le cas où il ne serait pas requis.
La fonction freeaddrinfo() libère la mémoire qui a été allouée
dynamiquement pour la liste chaînée res.
Extensions de getaddrinfo() pour les noms de domaines internationalisés
Depuis la glibc 2.3.4, getaddrinfo() a été modifié pour sélectivement
permettre que les noms d’hôtes entrant et sortant soient convertis vers
ou depuis le format des noms de domaines internationalisés (IDN).
Consultez la RFC 3490, Internationalizing Domain Names in Applications
(IDNA). Quatre nouveaux attributs ont été ajoutés :
AI_IDN Si cet attribut est défini, alors le nom du nœud contenu dans
node est converti dans le format IDN si nécessaire. Le format
d’encodage choisi est celui de la locale du système.
Si le nom du nœud contient des caractères non ASCII, alors le
format IDN est utilisé. Ces parties du nom du nœud (séparées par
des points) qui contiennent des caractères non ASCI sont
encodées avec « ASCII Compatible Encoding (ACE) » avant d’être
transférées aux fonctions de résolution de noms.
AI_CANONIDN
À la suite d’une résolution de nom réussie et si AI_CANONNAME a
été spécifié, getaddrinfo() retournera le nom canonique du nœud
correspondant à la valeur de la structure addrinfo passée. La
valeur renvoyée est une copie exacte de la valeur retournée par
la fonction de résolution de noms.
Si le nom est encodé avec ACE, alors une ou plusieurs
composantes de son nom sont préfixées par xn--. Pour convertir
ces composantes dans un format lisible, l’attribut AI_CANONIDN
peut être utilisé en plus de AI_CANONNAME. La chaîne résultante
est encodée selon la locale du système.
AI_IDN_ALLOW_UNASSIGNED, AI_IDN_USE_STD3_ASCII_RULES
Utiliser ces attributs permet d’activer respectivement les
attributs « IDNA_ALLOW_UNASSIGNED » (permettre des caractères
Unicode non assignés) et « IDNA_USE_STD3_ASCII_RULES » (vérifier
la sortie pour être sûr que le nom d’hôte est conforme à STD3)
utilisés dans la gestion de l’IDNA.
VALEUR RENVOYÉE
getaddrinfo() renvoie 0 si elle réussit, ou l’un des codes d’erreur non
nuls suivants :
EAI_ADDRFAMILY
L’hôte indiqué n’a pas d’adresse dans la famille réseau
demandée.
EAI_AGAIN
Le serveur de noms a renvoyé une erreur temporaire. Réessayez
plus tard.
EAI_BADFLAGS
ai_flags contient des attributs invalides.
EAI_FAIL
Le serveur de noms a renvoyé une erreur définitive.
EAI_FAMILY
La famille d’adresse réclamée n’est pas supportée du tout.
EAI_MEMORY
Plus de mémoire disponible.
EAI_NODATA
L’hôte existe mais n’a pas d’adresse réseau définie.
EAI_NONAME
node ou service sont inconnus ou ils sont tous les deux NULL ;
ou AI_NUMERICSERV a été spécifié dans hints.ai_flags mais
service n’est pas un numéro de port.
EAI_SERVICE
Le service demandé n’est pas disponible pour le type de socket
réclamé. Il peut être disponible pour un autre type de socket.
EAI_SOCKTYPE
Le type de socket demandé n’est pas supporté.
EAI_SYSTEM
Autre erreur système, voir errno pour plus de détail.
La fonction gai_strerror() traduit ces codes d’erreur en une chaîne de
caractères compréhensible, utilisable pour rendre compte du problème.
CONFORMITÉ
POSIX.1-2001. La fonction getaddrinfo() est documentée dans la
RFC 2553.
NOTES
AI_ADDRCONFIG, AI_ALL et AI_V4MAPPED sont disponibles depuis la
glibc 2.3.3. AI_NUMERICSERV est disponible depuis glibc 2.3.4.
EXEMPLE
Le programme suivant explique l’utilisation de getaddrinfo(),
gai_strerror(), freeaddrinfo(), et getnameinfo(3). Les programmes sont
des clients et serveurs
C’est le serveur :
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s;
struct sockaddr_storage peer_addr;
socklen_t peer_addr_len;
ssize_t nread;
char buf[BUF_SIZE];
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
s = getaddrinfo(NULL, argv[1], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully bind(2).
If socket(2) (or bind(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sfd == -1)
continue;
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
break; /* Success */
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
/* Read datagrams and echo them back to sender */
for (;;) {
peer_addr_len = sizeof(struct sockaddr_storage);
nread = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &peer_addr, &peer_addr_len);
if (nread == -1)
continue; /* Ignore failed request */
char host[NI_MAXHOST], service[NI_MAXSERV];
s = getnameinfo((struct sockaddr *) &peer_addr,
peer_addr_len, host, NI_MAXHOST,
service, NI_MAXSERV, NI_NUMERICSERV);
if (s == 0)
printf("Received %ld bytes from %s:%s\n",
(long) nread, host, service);
else
fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s));
if (sendto(sfd, buf, nread, 0,
(struct sockaddr *) &peer_addr,
peer_addr_len) != nread)
fprintf(stderr, "Error sending response\n");
}
}
C’est le client :
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s, j;
size_t len;
ssize_t nread;
char buf[BUF_SIZE];
if (argc < 3) {
fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
s = getaddrinfo(argv[1], argv[2], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully connect(2).
If socket(2) (or connect(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sfd == -1)
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
/* Send remaining command-line arguments as separate
datagrams, and read responses from server */
for (j = 3; j < argc; j++) {
len = strlen(argv[j]) + 1;
/* +1 for terminating null byte */
if (len + 1 > BUF_SIZE) {
fprintf(stderr,
"Ignoring long message in argument %d\n", j);
continue;
}
if (write(sfd, argv[j], len) != len) {
fprintf(stderr, "partial/failed write\n");
exit(EXIT_FAILURE);
}
nread = read(sfd, buf, BUF_SIZE);
if (nread == -1) {
perror("read");
exit(EXIT_FAILURE);
}
printf("Received %ld bytes: %s\n", (long) nread, buf);
}
exit(EXIT_SUCCESS);
}
VOIR AUSSI
getnameinfo(3)
COLOPHON
Cette page fait partie de la publication 2.80 du projet man-pages
Linux. Une description du projet et des instructions pour signaler des
anomalies peuvent être trouvées à l’adresse
http://www.kernel.org/doc/man-pages/.
TRADUCTION
Cette page de manuel a été traduite et mise à jour par Christophe
Blaess <http://www.blaess.fr/christophe/> entre 1996 et 2003, puis par
Alain Portal <aportal AT univ-montp2 DOT fr> jusqu’en 2006, et mise à
disposition sur http://manpagesfr.free.fr/.
Les mises à jour et corrections de la version présente dans Debian sont
directement gérées par Florentin Duneau <fduneau@gmail.com> et l’équipe
francophone de traduction de Debian.
Veuillez signaler toute erreur de traduction en écrivant à
<debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
paquet manpages-fr.
Vous pouvez toujours avoir accès à la version anglaise de ce document
en utilisant la commande « man -L C <section> <page_de_man> ».