Man page - getaddrinfo(3)

Packages contains this manual

Available languages:

en fr pl ja ru

Manual

getaddrinfo

NOM
BIBLIOTHÈQUE
SYNOPSIS
DESCRIPTION
Extensions de getaddrinfo() pour les noms de domaines internationalisés
VALEUR RENVOYÉE
FICHIERS
ATTRIBUTS
VERSIONS
STANDARDS
HISTORIQUE
NOTES
EXEMPLES
Programme du serveur
Programme du client
VOIR AUSSI
TRADUCTION

NOM

getaddrinfo, freeaddrinfo, gai_strerror - Traduction d’adresses et de services rĂ©seau

BIBLIOTHÈQUE

BibliothĂšque C standard ( libc , -lc )

SYNOPSIS

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int getaddrinfo(const char *restrict node ,
const char *restrict
service ,
const struct addrinfo *restrict
hints ,
struct addrinfo **restrict
res );

void freeaddrinfo(struct addrinfo * res );

const char *gai_strerror(int errcode );

Exigences de macros de test de fonctionnalités pour la glibc (consulter feature_test_macros (7)) :

getaddrinfo (), freeaddrinfo (), gai_strerror () :
Depuis la glibc 2.22 :
_POSIX_C_SOURCE >= 200112L
glibc 2.21 et antérieures :
_POSIX_C_SOURCE

DESCRIPTION

Étant donnĂ©s node et service , qui identifient un hĂŽte Internet et un service, getaddrinfo () renvoie une ou plusieurs structure addrinfo , chacune d’entre elles contenant une adresse Internet qui puisse ĂȘtre indiquĂ©e dans un appel Ă  bind (2) ou connect (2). La fonction getaddrinfo () combine la fonctionnalitĂ© fournie par les fonctions gethostbyname (3) et getservbyname (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 getaddrinfo () contient les membres suivants :

struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};

Le paramĂštre hints pointe sur une structure addrinfo qui indique les critĂšres de sĂ©lection des structures d’adresses de sockets renvoyĂ©es dans la liste pointĂ©e par res . Si hints n’est pas NULL, il doit pointer sur une structure addrinfo dont les membres ai_family , ai_socktype , et ai_protocol indiquent les critĂšres limitant l’ensemble d’adresses de sockets renvoyĂ©es par getaddrinfo (), de la façon suivante :
ai_family

Ce champ indique la famille d’adresse dĂ©sirĂ©e des adresses renvoyĂ©es. AF_INET et AF_INET6 font partie des valeurs valables pour ce champ. La valeur AF_UNSPEC indique que getaddrinfo () doit renvoyer les adresses de socket de n’importe quelle famille d’adresses (par exemple, IPv4 ou IPv6) pouvant ĂȘtre utilisĂ©es avec node et service .

ai_socktype

Ce champ indique le type prĂ©fĂ©rĂ© de socket, par exemple SOCK_STREAM ou SOCK_DGRAM . Mettre 0 dans ce champ indique que getaddrinfo () peut renvoyer n’importe quel type d’adresse de socket.

ai_protocol

Ce champ indique le protocole des adresses de socket renvoyĂ©es. Mettre 0 dans ce champ indique que getaddrinfo () peut renvoyer des adresses de socket de n’importe quel type.

ai_flags

Ce champ indique des options supplĂ©mentaires, dĂ©crites ci-dessous. Plusieurs attributs peuvent ĂȘtre indiquĂ©s en les groupant par un OU binaire.

Tous les autres membres de la structure pointĂ©e par hints doivent contenir 0 ou ĂȘtre des pointeurs NULL.

SpĂ©cifier hints Ă  NULL est Ă©quivalent Ă  dĂ©finir ai_socktype et ai_protocol Ă  0, ai_family Ă  AF_UNSPEC et ai_flags Ă  (AI_V4MAPPED | AI_ADDRCONFIG) . (POSIX spĂ©cifie d’autres valeurs par dĂ©faut pour ai_flags ; consultez les NOTES.) node indique soit une adresse rĂ©seau en format numĂ©rique (dĂ©cimal pointĂ© pour l’IPv4, comme prise en charge par inet_aton (3) ; hexadĂ©cimal pour l’IPv6, comme prise en charge par inet_pton (3)), 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 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.

Si l’attribut AI_PASSIVE est indiquĂ© dans hints.ai_flags , et si node est NULL, les adresses de socket renvoyĂ©es seront pertinentes pour lier ( bind (2)) un socket qui acceptera ( accept (2)) les connexions. Les adresses de socket renvoyĂ©es contiendront l’« adresse joker » (wildcard adress) ( INADDR_ANY pour les adresses IPv4, IN6ADDR_ANY_INIT pour les adresses IPv6). L’« adresse joker » est utilisĂ©e par des applications (typiquement des serveurs) qui ont l’intention d’accepter des connexions de n’importe quel hĂŽte. Si node n’est pas NULL, l’attribut AI_PASSIVE est ignorĂ©.

Si l’attribut AI_PASSIVE n’est pas positionnĂ© dans hints.ai_flags , les adresses de socket renvoyĂ©es seront pertinentes pour ĂȘtre utilisĂ©es avec connect (2), sendto (2) ou sendmsg (2). Si node est NULL, l’adresse rĂ©seau sera dĂ©finie avec l’adresse de l’interface de boucle (loopback) ( INADDR_LOOPBACK pour les adresses IPv4, IN6ADDR_LOOPBACK_INIT pour les adresses IPv6) ; cela est utilisĂ© par les applications qui doivent communiquer avec des correspondants s’exĂ©cutant sur la mĂȘme machine.

service dĂ©finit le port dans chacune des structures d’adresses renvoyĂ©es. Si cet argument est un nom de service (consultez services (5)), il est convertit en son numĂ©ro de port correspondant. Cet argument peut Ă©galement ĂȘtre indiquĂ© sous forme dĂ©cimale, qui est simplement converti en binaire. Si service est NULL, le numĂ©ro de port des adresses de socket renvoyĂ©es n’est pas initialisĂ©. Si AI_NUMERICSERV est indiquĂ© dans hints.ai_flags et si service n’est pas NULL, service doit pointer vers une chaĂźne contenant une valeur numĂ©rique de port. Cet attribut est utilisĂ© pour inhiber l’invocation du service de rĂ©solution des noms dans les cas oĂč l’on sait qu’il n’est pas nĂ©cessaire.

node ou service peuvent ĂȘtre NULL, mais pas les deux Ă  la fois.

La fonction getaddrinfo () alloue et initialise une liste chaĂźnĂ©e de structures addrinfo , une pour chaque adresse rĂ©seau correspondant Ă  node et service , soumise aux restrictions imposĂ©es par l’argument hints , et renvoie dans res un pointeur sur le dĂ©but de la liste. Les Ă©lĂ©ments de la liste sont chaĂźnĂ©s par le champ ai_next .

Il y a plusieurs raisons pour lesquelles la liste chaĂźnĂ©e peut avoir plus d’une structure addrinfo : l’hĂŽte rĂ©seau est « multihomed » ; le mĂȘme service est accessible depuis plusieurs protocoles (par exemple AF_INET et AF_INET6 ) ou accessible depuis plusieurs types de socket (par exemple une adresse de type SOCK_STREAM et une autre de type SOCK_DGRAM ). Normalement, l’application essaie d’utiliser les adresses dans l’ordre oĂč elles sont renvoyĂ©es. La fonction de tri utilisĂ©e dans getaddrinfo () est dĂ©finie dans la RFC 3484 ; le tri peut ĂȘtre configurĂ© pour un systĂšme particulier avec le fichier /etc/gai.conf (disponible depuis la glibc 2.5).

Si hints.ai_flags contient l’attribut AI_CANONNAME , le champ ai_canonname de la premiĂšre structure addrinfo de la liste renvoyĂ©e est dĂ©fini pour pointer vers le nom officiel de l’hĂŽte.

Les champs restants de chaque structure addrinfo renvoyée sont initialisés de la façon suivante :

-

Les champs ai_family , ai_socktype et ai_protocol renvoient les paramĂštres de crĂ©ation de la socket (c’est-Ă -dire que ces champs ont la mĂȘme signification que les paramĂštres correspondants de socket (2)). Par exemple, ai_family pourrait renvoyer AF_INET ou AF_INET6 ; ai_socktype pourrait renvoyer SOCK_DGRAM ou SOCK_STREAM ; et ai_protocol renvoie le protocole de la socket.

-

Un pointeur vers l’adresse de la socket est placĂ© dans le champ ai_addr , et la longueur de l’adresse de la socket, en octets, est inscrite dans le champ ai_addrlen de la structure.

Si hints.ai_flags inclut l’attribut AI_ADDRCONFIG , alors des adresses IPv4 sont renvoyĂ©es dans la liste pointĂ©e par res 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. Dans ce cas, l’adresse de boucle n’est pas considĂ©rĂ©e comme une adresse configurĂ©e valable. Cet attribut est par exemple utile sur les systĂšmes uniquement en IPv4, pour s’assurer que getaddrinfo () ne renvoie pas d’adresse de socket IPv6 qui Ă©chouerait toujours dans connect (2) ou bind (2).

Si hints.ai_flags indique le drapeau AI_V4MAPPED , et si hints.ai_family a Ă©tĂ© indiquĂ© 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 res . Si AI_V4MAPPED et AI_ALL sont indiquĂ©s dans hints.ai_flags , des adresses IPv6 et des adresses IPv4 au format IPv6 sont renvoyĂ©es dans la liste pointĂ©e par res . AI_ALL est ignorĂ© si AI_V4MAPPED n’est pas aussi indiquĂ©.

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Ă© indiquĂ©, 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 diffĂ©rent de 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

hints.ai_flags contient des drapeaux incorrects ; ou hints.ai_flags inclut AI_CANONNAME et node est NULL.

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.

EAI_MEMORY

Plus assez de mémoire.

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Ă© indiquĂ© 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 demandĂ©. Il est probablement disponible avec un autre type de socket. Par exemple, cette erreur peut se produire si service est « shell » (un service uniquement disponible avec les sockets de type flux), et soit si hints.ai_protocol est Ă©gal Ă  IPPROTO_UDP ou soit si hints.ai_socktype est Ă©gal Ă  SOCK_DGRAM . L’erreur peut aussi se produire si service est non NULL et hints.ai_socktype est Ă©gal Ă  SOCK_RAW (un type de socket qui ne gĂšre pas le concept de service).

EAI_SOCKTYPE

Le type de socket demandĂ© n’est pas gĂ©rĂ©. Cela peut se produire, par exemple si hints.ai_socktype et hints.ai_protocol sont inconsistants (par exemple, SOCK_DGRAM et IPPROTO_TCP , respectivement).

EAI_SYSTEM

Autre erreur systĂšme, la valeur de retour est -1 et errno est dĂ©fini pour indiquer l’erreur.

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.

FICHIERS

/etc/gai.conf

ATTRIBUTS

Pour une explication des termes utilisés dans cette section, consulter attributes (7).

Image grohtml-3878546-1.png

VERSIONS

Selon POSIX.1, définir hints comme NULL devrait supposer que ai_flags soit égal à 0 . La bibliothÚque C de GNU suppose à la place que ai_flags est égal à (AI_V4MAPPED | AI_ADDRCONFIG) dans ce cas, puisque cette valeur est considérée comme une amélioration de la spécification.

STANDARDS

POSIX.1-2008.
getaddrinfo
()

RFC 2553.

HISTORIQUE

POSIX.1-2001.
AI_ADDRCONFIG

AI_ALL

AI_V4MAPPED

glibc 2.3.3.

AI_NUMERICSERV

glibc 2.3.4.

NOTES

getaddrinfo () gùre la notation address % scope-id pour indiquer l’identifiant scope de IPv6.

EXEMPLES

Le programme suivant explique l’utilisation de getaddrinfo (), gai_strerror (), freeaddrinfo (), et getnameinfo (3). Les programmes sont des clients et serveurs pour les datagrammes UDP.

Programme du serveur

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{
int sfd, s;
char buf[BUF_SIZE];
ssize_t nread;
socklen_t peer_addrlen;
struct addrinfo hints;
struct addrinfo *result, *rp;
struct sockaddr_storage peer_addr;
if (argc != 2) {
fprintf(stderr, "Utilisation : %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* IPv4 ou IPv6 permis */
hints.ai_socktype = SOCK_DGRAM; /* Socket du datagramme */
hints.ai_flags = AI_PASSIVE; /* Pour une adresse IP joker */
hints.ai_protocol = 0; /* Tout protocole */
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() renvoie une liste de structures d’adresse.
Essayer cheque adresse jusqu’à un bind(2) rĂ©ussi.
Si socket(2) (ou bind(2)) échoue, on (clÎt le socket
et) essaie l’adresse suivante. */
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; /* SuccĂšs */
close(sfd);
}
freeaddrinfo(result); /* Plus nécessaire */
if (rp == NULL) { /* Toutes les adresses ont échoué */
fprintf(stderr, "Pas de lien créé\n");
exit(EXIT_FAILURE);
}
/* Lire les datagrammes et les renvoyer à l’envoyeur. */
for (;;) {
char host[NI_MAXHOST], service[NI_MAXSERV];
peer_addrlen = sizeof(peer_addr);
nread = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &peer_addr, &peer_addrlen);
if (nread == -1)
continue; /* Ignorer la requĂȘte en Ă©chec */
s = getnameinfo((struct sockaddr *) &peer_addr,
peer_addrlen, host, NI_MAXHOST,
service, NI_MAXSERV, NI_NUMERICSERV);
if (s == 0)
printf("%zd octets reçus de %s:%s\n",
nread, host, service);
else
fprintf(stderr, "getnameinfo : %s\n", gai_strerror(s));
if (sendto(sfd, buf, nread, 0, (struct sockaddr *) &peer_addr,
peer_addrlen) != nread)
{
fprintf(stderr, "Erreur d’envoi de rĂ©ponse\n");
}
}
}

Programme du client

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{
int sfd, s;
char buf[BUF_SIZE];
size_t len;
ssize_t nread;
struct addrinfo hints;
struct addrinfo *result, *rp;
if (argc < 3) {
fprintf(stderr, "Utilisation : %s host port msg...\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Obtenir les adresses correspondantes hĂŽte/port. */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* IPv4 ou IPv6 permis */
hints.ai_socktype = SOCK_DGRAM; /* Socket du datagramme */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Tout protocole */
s = getaddrinfo(argv[1], argv[2], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() renvoie une liste de structures d’adresse.
Essayer chaque adresse jusqu’à un bind(2) rĂ©ussi.
Si socket(2) (ou bind(2)) échoue, on (clÎt le socket
et) essaie l’adresse suivante. */
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; /* SuccĂšs */
close(sfd);
}
freeaddrinfo(result); /* Plus nécessaire */
if (rp == NULL) { /* Toutes les adresses ont échoué */
fprintf(stderr, "Connexion impossible\n");
exit(EXIT_FAILURE);
}
/* Envoyer les arguments en ligne de commande comme des datagrammes
séparés et lire les réponses du serveur. */
for (size_t j = 3; j < argc; j++) {
len = strlen(argv[j]) + 1;
/* +1 pour l’octet NULL de terminaison */
if (len > BUF_SIZE) {
fprintf(stderr,
"Ignorer le message long dans l’argument %zu\n", j);
continue;
}
if (write(sfd, argv[j], len) != len) {
fprintf(stderr, "écriture partielle/échec\n");
exit(EXIT_FAILURE);
}
nread = read(sfd, buf, BUF_SIZE);
if (nread == -1) {
perror("read");
exit(EXIT_FAILURE);
}
printf("%zd octets reçus de : %s\n", nread, buf);
}
exit(EXIT_SUCCESS);
}

VOIR AUSSI

getaddrinfo_a (3), gethostbyname (3), getnameinfo (3), inet (3), gai.conf (5), hostname (7), ip (7)

TRADUCTION

La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Pierre Giraud <jean-pierregiraud@neuf.fr>

Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n’y a aucune RESPONSABILITÉ LÉGALE.

Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org .