getaddrinfo
Table des matières
Retour à l'index
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).
| Interface | Attribut | Valeur
|
|
getaddrinfo()
| Sécurité des threads | MT-Safe env locale
|
|
freeaddrinfo(),
gai_strerror()
| Sécurité des threads | MT-Safe
|
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, "Usage: %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(hints));
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);
}
freeaddrinfo(result); /* No longer needed */
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
exit(EXIT_FAILURE);
}
/* Read datagrams and echo them back to sender. */
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; /* Ignore failed request */
s = getnameinfo((struct sockaddr *) &peer_addr,
peer_addrlen, host, NI_MAXHOST,
service, NI_MAXSERV, NI_NUMERICSERV);
if (s == 0)
printf("Received %zd bytes from %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, "Error sending response\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, "Usage: %s host port msg...\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Obtain address(es) matching host/port. */
memset(&hints, 0, sizeof(hints));
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);
}
freeaddrinfo(result); /* No longer needed */
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
/* Send remaining command-line arguments as separate
datagrams, and read responses from server. */
for (size_t j = 3; j < argc; j++) {
len = strlen(argv[j]) + 1;
/* +1 for terminating null byte */
if (len > BUF_SIZE) {
fprintf(stderr,
"Ignoring long message in argument %zu\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 %zd bytes: %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 à
Index
- 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
-
This document was created by
man2html,
using the manual pages.
Time: 05:06:14 GMT, September 19, 2025