C Programming/POSIX Reference/netdb.h/getaddrinfo

The getaddrinfo() and getnameinfo() functions are part of the POSIX standard application programming interface (API) for converting domain name system (DNS) hostnames and IP addresses between their human-readable text representations and structured binary formats for the operating system's networking API.

getaddrinfo() and getnameinfo() are inverse functions of each other.

This set of functions is fully network protocol agnostic and supports both IPv4 and IPv6. It is the recommended interface for name resolution in building protocol independent applications and for transitioning legacy IPv4 code to the IPv6 Internet.

struct addrinfo

edit

The C data structure used to represent addresses and hostnames within the networking API is the following:

struct addrinfo {
    int     ai_flags;
    int     ai_family;
    int     ai_socktype;
    int     ai_protocol;
    size_t  ai_addrlen;
    struct  sockaddr *ai_addr;
    char    *ai_canonname;     /* canonical name */
    struct  addrinfo *ai_next; /* this struct can form a linked list */
};

In recent operating systems the type of ai_addrlen has been changed from size_t to socklen_t. Most socket functions, such as accept and getpeername, require a socklen_t* parameter and programmers often pass the address to the ai_addrlen element of the addrinfo structure. If the types are incompatible, e.g., on a big-endian 64-bit Solaris 9 system where size_t is 8 bytes and socklen_t is 4 bytes, then run-time errors may result.

getaddrinfo()

edit

getaddrinfo() converts human-readable text strings representing hostnames or IP addresses into a dynamically allocated linked list of struct addrinfo structures. An application can deallocate these linked lists with the freeaddrinfo() function. The function prototypes for these functions are specified as follows:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int getaddrinfo(const char *node,
                const char *service,
                const struct addrinfo *hints,
                struct addrinfo **res);

void freeaddrinfo(struct addrinfo *res);

getnameinfo()

edit

getnameinfo() converts the internal binary representation of an IP address in the form of a struct sockaddr pointer into text strings consisting of the hostname or, if the address cannot be resolved into a name, a textual IP address representation, as well as the service port name or number. The function prototype is specified as follows:

#include <sys/socket.h>
#include <netdb.h>

int getnameinfo(const struct sockaddr *sa, socklen_t salen,
                char *host, size_t hostlen,
                char *serv, size_t servlen,
                int flags);

Example

edit

The following example uses getaddrinfo() to resolve the domain name www.example.com into its list of addresses and then calls getnameinfo() on each result to return the canonical name for the address. In general, this will produce the original hostname, unless the particular address has multiple names, in which case the canonical name is returned. In this example, the domain name will be printed three times, once for each of the three results obtained.

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>

#ifndef   NI_MAXHOST
#define   NI_MAXHOST 1025
#endif

int main(void)
{
    struct addrinfo *result;
    struct addrinfo *res;
    int error;

    /* resolve the domain name into a list of addresses */
    error = getaddrinfo("www.example.com", NULL, NULL, &result);
    if (error != 0)
    {   
        fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
        return EXIT_FAILURE;
    }   

    /* loop over all returned results and do inverse lookup */
    for (res = result; res != NULL; res = res->ai_next)
    {   
        char hostname[NI_MAXHOST] = "";

        error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0); 
        if (error != 0)
        {
            fprintf(stderr, "error in getnameinfo: %s\n", gai_strerror(error));
            continue;
        }
        if (*hostname != '\0')
            printf("hostname: %s\n", hostname);
    }   

    freeaddrinfo(result);
    return EXIT_SUCCESS;
}
edit
  • RFC 3493, Basic Socket Interface Extensions for IPv6