Rate this page

Flattr this

Convert an IP address to the corresponding domain name in C

Tested on

Debian (Lenny, Squeeze)
Ubuntu (Lucid, Precise, Trusty)

Objective

To convert an IPv4 or IPv6 address to the corresponding domain name (if there is one) in C

Scenario

Suppose you have used the getpeername function to obtain the remote address to which a particular TCP socket is connected:

struct sockaddr_storage addr;
socklen_t addr_len=sizeof(addr);
int err=getpeername(sock_fd,(struct sockaddr*)&addr,&addr_len);
if (err!=0) {
    die("failed to fetch remote address (errno=%d)",errno);
}

The remote address has been written to a buffer called addr. This buffer is of type struct sockaddr_storage, but the address stored within it will be of type struct sockaddr_in or sockaddr_in6. The length of the address has been recorded in the variable addr_len. Note that:

You wish to convert the IP address contained within addr to the corresponding domain name (if there is one), or failing that to a human-readable numeric representation.

Method

One way to perform the required conversion is to call the getnameinfo function:

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

#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif

// ...

char buffer[NI_MAXHOST];
int err=getnameinfo((struct sockaddr*)&addr,addr_len,buffer,sizeof(buffer),0,0,0);
if (err!=0) {
    die("failed to convert address to string (code=%d)",err);
}
printf("Remote address: %s\n",buffer);

If the IP address cannot be resolved to a hostname then it will instead be converted to a human-readable numeric format (for example 192.168.0.1 or 2001:db8::1).

POSIX does not define any fixed upper limit on the size of buffer that might be needed, however implementations often provide a macro called NI_MAXHOST for this purpose. For portability you should test whether this macro exists and provide your own value if it does not. The value used by glibc at the time of writing was 1025.

See also

Further reading

Tags: c | dns | posix