GETADDRINFO(3)GETADDRINFO(3)NAME
getaddrinfo, freeaddrinfo, gai_strerror - nodename-to-address translation
in a protocol-independent manner
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int getaddrinfo(const char *nodename, const char *servname,
const struct addrinfo *hints, struct addrinfo **res);
void freeaddrinfo(struct addrinfo *ai);
const char *gai_strerror(int ecode);
DESCRIPTION
Getaddrinfo function is defined for protocol-independent nodename-to-
address translation. It performs the functionality of gethostbyname(3N)
and getservbyname(3N), but in a more sophisticated manner.
The addrinfo structure is defined as a result of including the <netdb.h>
header:
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME,
AI_NUMERICHOST , AI_ALL etc */
int ai_family; /* AF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /*0 or IPPROTO_xxx for IPv4 and IPv6*/
socklen_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for nodename */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /*next structure in linked list*/
};
The nodename and servname arguments are pointers to null-terminated
strings or NULL. One or both of these two arguments must be a non-NULL
pointer. In the normal client scenario, both the nodename and servname
are specified. In the normal server scenario, only the servname is
specified. A non-NULL nodename string can be either a node name or a
numeric host address string i.e., a dotted-decimal IPv4 address or an
IPv6 hex address. A non-NULL servname string can be either a service name
or a decimal port number.
The caller can optionally pass an addrinfo structure, pointed to by the
third argument, to provide hints concerning the type of socket that the
caller supports. In this hints structure all members other than
ai_flags, ai_family, ai_socktype, and ai_protocol must be zero or a NULL
pointer. A value of AF_UNSPEC for ai_family means the caller will accept
any protocol family. A value of 0 for ai_socktype means the caller will
accept any protocol. For example, if the caller handles only TCP and not
UDP, then the ai_socktype member of the hints structure should be set to
Page 1
GETADDRINFO(3)GETADDRINFO(3)
SOCK_STREAM and the ai_protocol member should be set to IPPROTO_TCP when
getaddrinfo() is called. If the caller handles only IPv4 and not IPv6,
then the ai_family member of the hints structure should be set to AF_INET
when getaddrinfo() is called. If the third argument to getaddrinfo() is
a NULL pointer, this is the same as if the caller had filled in an
addrinfo structure initialized to zero with ai_family set to AF_UNSPEC.
The ai_flags field to which hints parameter points must have the value
zero or be the bitwise OR of one or more of the values AI_PASSIVE,
AI_CANONNAME, AI_NUMERICHOST, AI_NUMERICSERV, AI_V4MAPPED, AI_ALL, and
AI_ADDRCONFIG.
If the AI_PASSIVE bit is set in the ai_flags member of the hints
structure, then the caller plans to use the returned socket address
structure in a call to bind(). In this case, if the nodename argument is
a NULL pointer, then the IP address portion of the socket address
structure will be set to INADDR_ANY for an IPv4 address or
IN6ADDR_ANY_INIT for an IPv6 address.
If the AI_PASSIVE bit is not set in the ai_flags member of the hints
structure, then the returned socket address structure will be ready for a
call to connect() (for a connection-oriented protocol) or either
connect(), sendto(), or sendmsg() (for a connectionless protocol). In
this case, if the nodename argument is a NULL pointer, then the IP
address portion of the socket address structure will be set to the
loopback address.
If the AI_CANONNAME bit is set in the ai_flags member of the hints
structure, then upon successful return the ai_canonname member of the
first addrinfo structure in the linked list will point to a
null-terminated string containing the canonical name of the specified
nodename. If the canonical name is not available, then ai_canonname will
refer to the nodename argument or a string with the same contents.
If the AI_NUMERICHOST bit is set in the ai_flags member of the hints
structure, then a non-NULL nodename string must be a numeric host address
string. Otherwise an error of EAI_NONAME is returned. This flag
prevents any type of name resolution service (e.g., the DNS) from being
called.
If the flag AI_NUMERICSERV is specified then a non-null servname string
must be a numeric port string. Otherwise an error EAI_NONAME is
returned. This flag prevents any type of name resolution service (for
example, NIS+) from being invoked.
If the AI_V4MAPPED flag is specified along with an ai_family of AF_INET6,
then the caller will accept IPv4-mapped IPv6 addresses. That is, if no
AAAA or A6 records are found then a query is made for A records and any
found are returned as IPv4-mapped IPv6 addresses (ai_addrlen will be 16).
The AI_V4MAPPED flag is ignored unless ai_family equals AF_INET6.
Page 2
GETADDRINFO(3)GETADDRINFO(3)
The AI_ALL flag should be used in conjunction with the AI_V4MAPPED flag,
and is only used with an ai_family of AF_INET6. When AI_ALL is logically
or'd with AI_V4MAPPED flag then the caller will accept all addresses:
IPv6 and IPv4-mapped IPv6. A query is first made for AAAA/A6 records and
if successful, the IPv6 addresses are returned. Another query is then
made for A records and any found are returned as IPv4-mapped IPv6
addresses (ai_addrlen will be 16). This flag is ignored unless ai_family
equals AF_INET6. When ai_family is not specified (AF_UNSPEC),
AI_V4MAPPED and AI_ALL flags will only be used if AF_INET6 is supported.
If the AI_ADDRCONFIG flag is specified then a query for AAAA or A6
records occurs only if the node has at least one IPv6 source address
configured and a query for A records occurs only if the node has at least
one IPv4 source address configured. The loopback address is not
considered for this case as valid as a configured sources address.
The ai_socktype field to which argument hints points specifies the socket
type for the service. If a specific socket type is not given (for
example, a value of zero) and the service name could be interpreted as
valid with multiple supported socket types, this implementation will
attempt to resolve the service name for all supported socket types and,
all successful results will be returned. A non-zero socket type value
will limit the returned information to values with the specified socket
type.
Upon successful return of getaddrinfo(), the location to which res points
refers to a linked list of addrinfo structures, each of which specifies a
socket address and information for use in creating a socket with which to
use that socket address. The caller can process each addrinfo structure
in this list by following the ai_next pointer, until a NULL pointer is
encountered. In each returned addrinfo structure the three members
ai_family, ai_socktype, and ai_protocol are the corresponding arguments
for a call to the socket() function. In each addrinfo structure the
ai_addr member points to a filled-in socket address structure whose
length is specified by the ai_addrlen member.
All of the information returned by getaddrinfo() is dynamically
allocated: the addrinfo structures, the socket address structures, and
canonical node name strings pointed to by the addrinfo structures. To
return this information to the system the function freeaddrinfo() is
called. The freeaddrinfo() function frees one or more addrinfo
structures returned by getaddrinfo(), along with any additional storage
associated with those structures. If the ai_next field of the structure
is not null, the entire list of structures is freed. The freeaddrinfo()
function supports the freeing of arbitrary sublists of an addrinfo list
originally returned by getaddrinfo().
Functions getaddrinfo() and freeaddrinfo() are thread-safe.
Page 3
GETADDRINFO(3)GETADDRINFO(3)
To aid applications in printing error messages based on the EAI_xxx codes
returned by getaddrinfo(), gai_strerror() is defined. The argument is
one of the EAI_xxx values defined earlier and the return value points to
a string describing the error. If the argument is not one of the EAI_xxx
values, the function still returns a pointer to a string whose contents
indicate an unknown error.
EXAMPLES
The following code tries to connect to "www.company.example" service
"ftp" via stream socket. It loops through all the addresses available,
regardless of the address family. If the destination resolves to IPv4
address, it will use AF_INET socket. Similarly, if it resolves to IPv6,
AF_INET6 socket is used. Observe that there is not hardcoded reference
to particular address family.
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
main(){
struct addrinfo hints, *res, *res0;
int error;
int s;
const char *cause = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo("www.company.example", "ftp",
&hints, &res0);
if(error){
fprintf(stderr, "%s", gai_strerror(error));
exit(1);
}
s = -1;
for (res = res0; res; res = res->ai_next) {
s = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
if (s < 0) {
cause = "Error: socket";
continue;
}
if(connect(s, res->ai_addr, res->ai_addrlen) < 0 ) {
cause = "Error: connect";
close(s);
s = -1;
continue;
}
cause = "Success";
break; /* okay we got one */
Page 4
GETADDRINFO(3)GETADDRINFO(3)
}
fprintf(stderr, cause);
freeaddrinfo(res0);
} /* end of main */
The following example tries to open wildcard listening socket onto
service "ftp", for all the address families available.
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#define MXSOCK 5
main(){
struct addrinfo hints, *res, *res0;
int error;
int s[MXSOCK];
int n;
const char *cause = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
error = getaddrinfo(NULL, "ftp", &hints, &res0);
if(error) {
fprintf(stderr, "%s", gai_strerror(error));
exit(1);
}
n = 0;
for (res = res0; res && n < MXSOCK; res = res->ai_next){
s[n] = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
if(s[n] < 0) {
cause = "Error: socket";
continue;
}
if (bind(s[n], res->ai_addr, res->ai_addrlen) < 0) {
cause = "Error: bind";
close(s[n]);
continue;
}
if (listen(s[n], SOMAXCONN) < 0) {
cause = "Error: listen";
close(s[n]);
continue;
}
cause = "Success";
n++;
Page 5
GETADDRINFO(3)GETADDRINFO(3)
}
fprintf(stderr, cause);
freeaddrinfo(res0);
}
FILES
/etc/hosts
/etc/ipnodes
/etc/resolv.conf
DIAGNOSTICS
Error return status from getaddrinfo() is zero on success and non-zero on
errors. Non-zero error codes are defined in <netdb.h>, and as follows:
EAI_ADDRFAMILY Address family for nodename not supported.
EAI_AGAIN Temporary failure in name resolution.
EAI_BADFLAGS Invalid value for ai_flags.
EAI_FAIL Non-recoverable failure in name resolution.
EAI_FAMILY ai_family not supported.
EAI_MEMORY Memory allocation failure.
EAI_NODATA No address associated with nodename.
EAI_NONAME nodename nor servname provided, or not known.
EAI_SERVICE servname not supported for ai_socktype.
EAI_SOCKTYPE ai_socktype not supported.
EAI_SYSTEM System error returned in errno.
If called with proper argument, gai_strerror() returns a pointer to a
string describing the given error code. If the argument is not one of
the EAI_xxx values, the function still returns a pointer to a string
whose contents indicate an unknown error.
SEE ALSOgetnameinfo(3), gethostbyname(3), getipnodebyname(3), getservbyname(3),
hosts(5), services(5), socket(3), connect(3).
STANDARDS
The getaddrinfo(), freeaddrinfo(), and gai_strerror() functions are
defined in IEEE POSIX 1003.1g draft specification, draft-ietf-ipngwg-
rfc2553bis-03.txt, and documented in "Basic Socket Interface Extensions
for IPv6" (RFC2553).
Page 6