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 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. 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. 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 */ } 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++; } 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 ALSO getnameinfo(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