‘getaddrinfo’ Function
The gethostbyname and gethostbyaddr functions only support IPv4. The API for resolving IPv6 addresses went through several iterations, as will be described in Section 11.20(See 8.9.20); the final result is the getaddrinfo function.
The POSIX definition of this function comes from an earlier proposal by Keith Sklower for a function named getconninfo. This function was the result of discussions with Eric Allman, William Durst, Michael Karels, and Steven Wise, and from an early implementation written by Eric Allman. The observation that specifying a hostname and a service name would suffice for connecting to a service independent of protocol details was made by Marshall Rose in a proposal to X/Open.
#include
int getaddrinfo (const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result) ;
This function returns through the result pointer a pointer to a linked list of addrinfo structures, which is defined by including .
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
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; /* ptr to canonical name for host */
struct sockaddr *ai_addr; /* ptr to socket address structure */
struct addrinfo *ai_next; /* ptr to next structure in linked list */
};
The members of the hints structure that can be set by the caller are:
- ai_flags (zero or more AI_XXX values OR’ed together)
- ai_family (an AF_xxx value)
- ai_socktype (a SOCK_xxx value)
- ai_protocol
If the function returns success (0), the variable pointed to by the result argument is filled in with a pointer to a linked list of addrinfo structures, linked through the ai_next pointer. There are two ways that multiple structures can be returned:
1.If there are multiple addresses associated with the hostname, one structure is returned for each address that is usable with the requested address family (the ai_family hint, if specified).
2.If the service is provided for multiple socket types, one structure can be returned for each socket type, depending on the ai_socktype hint. (Note that most getaddrinfo implementations consider a port number string to be implemented only by the socket type requested in ai_socktype; if ai_socktype is not specified, an error is returned instead.)
For example, if no hints are provided and if the domain service is looked up for a host with two IP addresses, four addrinfo structures are returned:
- One for the first IP address and a socket type of SOCK_STREAM
- One for the first IP address and a socket type of SOCK_DGRAM
- One for the second IP address and a socket type of SOCK_STREAM
- One for the second IP address and a socket type of SOCK_DGRAM
If we were to enumerate all 64 possible inputs to getaddrinfo (there are six input variables), many would be invalid and some would make little sense. Instead, we will look at the common cases.
- Specify the hostname and service. This is normal for a TCP or UDP client. On return, a TCP client loops through all returned IP addresses, calling socket and connect for each one, until the connection succeeds or until all addresses have been tried. We will show an example of this with our tcp_connect function in Figure 11.10(See 8.9.12).
- For a UDP client, the socket address structure filled in by getaddrinfo would be used in a call to sendto or connect. If the client can tell that the first address doesn’t appear to work (either by receiving an error on a connected UDP socket or by experiencing a timeout on an unconnected socket), additional addresses can be tried.
- If the client knows it handles only one type of socket (e.g., Telnet and FTP clients handle only TCP; TFTP clients handle only UDP), then the ai_socktype member of the hints structure should be specified as either SOCK_STREAM or SOCK_DGRAM.
- A typical server specifies the service but not the hostname, and specifies the AI_PASSIVE flag in the hints structure. The socket address structures returned should contain an IP address of INADDR_ANY (for IPv4) or IN6ADDR_ANY_INIT (for IPv6). A TCP server then calls socket, bind, and listen. If the server wants to malloc another socket address structure to obtain the client’s address from accept, the returned ai_addrlen value specifies this size.
- A UDP server would call socket, bind, and then recvfrom. If the server wants to malloc another socket address structure to obtain the client’s address from recvfrom, the returned ai_addrlen value specifies this size.
- As with the typical client code, if the server knows it only handles one type of socket, the ai_socktype member of the hints structure should be set to either SOCK_STREAM or SOCK_DGRAM. This avoids having multiple structures returned, possibly with the wrong ai_socktype value.
- The TCP servers that we have shown so far create one listening socket, and the UDP servers create one datagram socket. That is what we assume in the previous item. An alternate server design is for the server to handle multiple sockets using select or poll. In this scenario, the server would go through the entire list of structures returned by getaddrinfo, create one socket per structure, and use select or poll.