getaddrinfo.c revision 69fe9aaafdd6a141610e86a777d325db75422070
7d98a1783f222964bcde7d56dab77b822706204dBob Halley * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 1999-2001 Internet Software Consortium.
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * This code is derived from software contributed to ISC by
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * Berkeley Software Design, Inc.
15a44745412679c30a6d022733925af70a38b715David Lawrence * Permission to use, copy, modify, and distribute this software for any
15a44745412679c30a6d022733925af70a38b715David Lawrence * purpose with or without fee is hereby granted, provided that the above
15a44745412679c30a6d022733925af70a38b715David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND BERKELEY SOFTWARE DESIGN, INC.
15a44745412679c30a6d022733925af70a38b715David Lawrence * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
15a44745412679c30a6d022733925af70a38b715David Lawrence * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
15a44745412679c30a6d022733925af70a38b715David Lawrence * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
8f7cae3d7b0c122c3b17e8409bbb80005433acd2Brian Wellington * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley/* $Id: getaddrinfo.c,v 1.45 2005/04/29 00:24:05 marka Exp $ */
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * lwres_getaddrinfo() is used to get a list of IP addresses and port
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * numbers for host hostname and service servname. The function is the
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * lightweight resolver's implementation of getaddrinfo() as defined in
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * RFC2133. hostname and servname are pointers to null-terminated strings
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * or NULL. hostname is either a host name or a numeric host address
5fe5a0c02634eaadfcbc3528bf2c184557110a3bAndreas Gustafsson * string: a dotted decimal IPv4 address or an IPv6 address. servname is
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * either a decimal port number or a service name as listed in
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * If the operating system does not provide a struct addrinfo, the
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * following structure is used:
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * struct addrinfo {
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * int ai_flags; // AI_PASSIVE, AI_CANONNAME
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * int ai_family; // PF_xxx
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * int ai_socktype; // SOCK_xxx
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * int ai_protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * size_t ai_addrlen; // length of ai_addr
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * char *ai_canonname; // canonical name for hostname
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * struct sockaddr *ai_addr; // binary address
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * struct addrinfo *ai_next; // next structure in linked list
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * hints is an optional pointer to a struct addrinfo. This structure can
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * be used to provide hints concerning the type of socket that the caller
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * supports or wishes to use. The caller can supply the following
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * structure elements in *hints:
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson * <li>ai_family:
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * The protocol family that should be used. When ai_family is set
edcd1247ad7e81bb8b430e610d9718f64c70f05dDavid Lawrence * to PF_UNSPEC, it means the caller will accept any protocol
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * family supported by the operating system.</li>
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * <li>ai_socktype:
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * denotes the type of socket -- SOCK_STREAM, SOCK_DGRAM or
8582a1e113c13886ccbd1b534d6c240315767be6Bob Halley * SOCK_RAW -- that is wanted. When ai_socktype is zero the caller
8582a1e113c13886ccbd1b534d6c240315767be6Bob Halley * will accept any socket type.</li>
edcd1247ad7e81bb8b430e610d9718f64c70f05dDavid Lawrence * <li>ai_protocol:
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * indicates which transport protocol is wanted: IPPROTO_UDP or
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * IPPROTO_TCP. If ai_protocol is zero the caller will accept any
edcd1247ad7e81bb8b430e610d9718f64c70f05dDavid Lawrence * protocol.</li>
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley * <li>ai_flags:
c90f5e8d1edbd5c277f2ee320167a12a30ba7c7bMichael Graff * Flag bits. If the AI_CANONNAME bit is set, a successful call to
edcd1247ad7e81bb8b430e610d9718f64c70f05dDavid Lawrence * lwres_getaddrinfo() will return a null-terminated string
c90f5e8d1edbd5c277f2ee320167a12a30ba7c7bMichael Graff * containing the canonical name of the specified hostname in
8582a1e113c13886ccbd1b534d6c240315767be6Bob Halley * ai_canonname of the first addrinfo structure returned. Setting
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson * the AI_PASSIVE bit indicates that the returned socket address
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson * structure is intended for used in a call to bind(2). In this
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson * case, if the hostname argument is a NULL pointer, then the IP
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson * address portion of the socket address structure will be set to
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * address.<br /><br />
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * When ai_flags does not set the AI_PASSIVE bit, the returned
e02c696ea586f8dcc7c6145cc0f143f887960cd4Andreas Gustafsson * socket address structure will be ready for use in a call to
e02c696ea586f8dcc7c6145cc0f143f887960cd4Andreas Gustafsson * connect(2) for a connection-oriented protocol or connect(2),
e02c696ea586f8dcc7c6145cc0f143f887960cd4Andreas Gustafsson * sendto(2), or sendmsg(2) if a connectionless protocol was
e02c696ea586f8dcc7c6145cc0f143f887960cd4Andreas Gustafsson * chosen. The IP address portion of the socket address structure
e02c696ea586f8dcc7c6145cc0f143f887960cd4Andreas Gustafsson * will be set to the loopback address if hostname is a NULL
e02c696ea586f8dcc7c6145cc0f143f887960cd4Andreas Gustafsson * pointer and AI_PASSIVE is not set in ai_flags.<br /><br />
e02c696ea586f8dcc7c6145cc0f143f887960cd4Andreas Gustafsson * If ai_flags is set to AI_NUMERICHOST it indicates that hostname
e02c696ea586f8dcc7c6145cc0f143f887960cd4Andreas Gustafsson * should be treated as a numeric string defining an IPv4 or IPv6
e02c696ea586f8dcc7c6145cc0f143f887960cd4Andreas Gustafsson * address and no name resolution should be attempted.
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * All other elements of the struct addrinfo passed via hints must be
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * A hints of NULL is treated as if the caller provided a struct addrinfo
8582a1e113c13886ccbd1b534d6c240315767be6Bob Halley * initialized to zero with ai_familyset to PF_UNSPEC.
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * After a successful call to lwres_getaddrinfo(), *res is a pointer to a
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * linked list of one or more addrinfo structures. Each struct addrinfo
8582a1e113c13886ccbd1b534d6c240315767be6Bob Halley * in this list cn be processed by following the ai_next pointer, until a
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * NULL pointer is encountered. The three members ai_family, ai_socktype,
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * and ai_protocol in each returned addrinfo structure contain the
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * corresponding arguments for a call to socket(2). For each addrinfo
44fee668021c7ceef4ee1c848031d883a508b359James Brister * structure in the list, the ai_addr member points to a filled-in socket
44fee668021c7ceef4ee1c848031d883a508b359James Brister * address structure of length ai_addrlen.
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * All of the information returned by lwres_getaddrinfo() is dynamically
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * allocated: the addrinfo structures, and the socket address structures
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * and canonical host name strings pointed to by the addrinfostructures.
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * Memory allocated for the dynamically allocated structures created by a
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * successful call to lwres_getaddrinfo() is released by
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * lwres_freeaddrinfo(). ai is a pointer to a struct addrinfo created by
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * a call to lwres_getaddrinfo().
11d435aa4cf77e035445978f7e3776a3589715fdAndreas Gustafsson * \section lwresreturn RETURN VALUES
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * lwres_getaddrinfo() returns zero on success or one of the error codes
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * listed in gai_strerror() if an error occurs. If both hostname and
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * servname are NULL lwres_getaddrinfo() returns #EAI_NONAME.
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * \section lwressee SEE ALSO
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * lwres(3), lwres_getaddrinfo(), lwres_freeaddrinfo(),
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * lwres_gai_strerror(), RFC2133, getservbyname(3), connect(2),
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafsson * sendto(2), sendmsg(2), socket(2).
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson#define SA(addr) ((struct sockaddr *)(addr))
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson#define SIN(addr) ((struct sockaddr_in *)(addr))
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson#define SIN6(addr) ((struct sockaddr_in6 *)(addr))
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson#define SUN(addr) ((struct sockaddr_un *)(addr))
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson/*! \struct addrinfo
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafsson *ai_clone(struct addrinfo *oai, int family),
7193a1762e428cfba06907e51fa9e4bce3b5569aAndreas Gustafssonstatic int get_local(const char *name, int socktype, struct addrinfo **res);
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafssonstatic int add_ipv4(const char *hostname, int flags, struct addrinfo **aip,
a0f6cda5fd9f2fcc4154bb63628f849b639a40caAndreas Gustafssonstatic int add_ipv6(const char *hostname, int flags, struct addrinfo **aip,
5542df09597c479be604da0ece8271cbc6fd9c4aDavid Lawrencestatic void set_order(int, int (**)(const char *, int, struct addrinfo **,
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley#define ISC_AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST)
8582a1e113c13886ccbd1b534d6c240315767be6Bob Halley/*% Get a list of IP addresses and port numbers for host hostname and service servname. */
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halleylwres_getaddrinfo(const char *hostname, const char *servname,
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley const struct addrinfo *hints, struct addrinfo **res)
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley const char *proto;
1687985cdfc3a4c330c5bdb02c131835f8756e3cBob Halley int (*net_order[FOUND_MAX+1])(const char *, int, struct addrinfo **,
return (EAI_NONAME);
return (EAI_BADFLAGS);
return (EAI_SYSTEM);
switch (family) {
case AF_UNSPEC:
case SOCK_STREAM:
case SOCK_DGRAM:
case AF_INET:
case AF_INET6:
case SOCK_STREAM:
case SOCK_DGRAM:
case SOCK_RAW:
return (EAI_SOCKTYPE);
#ifdef AF_LOCAL
case AF_LOCAL:
case SOCK_STREAM:
case SOCK_DGRAM:
return (EAI_SOCKTYPE);
return (EAI_FAMILY);
protocol = 0;
family = 0;
socktype = 0;
flags = 0;
#ifdef AF_LOCAL
if (socktype == 0)
return (EAI_SOCKTYPE);
return (EAI_SERVICE);
return (EAI_SERVICE);
if (socktype == 0) {
port = 0;
return (EAI_MEMORY);
return (EAI_MEMORY);
#ifdef LWRES_HAVE_SIN6_SCOPE_ID
char *p, *ep;
#ifdef LWRES_HAVE_SIN6_SCOPE_ID
if (p != NULL)
scopeid = 0;
scopeid = 0;
goto inet6_addr;
goto common;
#ifdef LWRES_HAVE_SIN6_SCOPE_ID
return (EAI_NONAME);
goto common;
return (EAI_NONAME);
return (EAI_MEMORY);
#if defined(LWRES_HAVE_SIN6_SCOPE_ID)
NULL, 0,
NI_NUMERICHOST) == 0) {
return (EAI_MEMORY);
goto done;
return (EAI_NONAME);
for (i = 0; i < FOUND_MAX; i++) {
if (err != 0)
return (err);
return (EAI_NODATA);
done:
return (NULL);
sc = *s;
*stringp = s;
return (string);
return (string);
int found;
if (family) {
switch (family) {
case AF_INET:
case AF_INET6:
found = 0;
int result = 0;
goto cleanup;
return (result);
int result = 0;
goto cleanup;
return (result);
#ifdef AF_LOCAL
if (socktype == 0)
return (EAI_SOCKTYPE);
return (EAI_MEMORY);
static struct addrinfo *
return (NULL);
return (NULL);
#ifdef LWRES_PLATFORM_HAVESALEN
return (ai);
static struct addrinfo *
return (NULL);
return (ai);
return (ai);
static struct addrinfo *
return (nai);