getnameinfo()

Updated: April 19, 2023

Convert an IP address and port number into node and service names

Synopsis:

#include <sys/types.h>
#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 );

Arguments:

sa
A pointer to either a sockaddr_in structure (for IPv4) or a sockaddr_in6 structure (for IPv6) that holds the IP address and port number.
salen
The length of the sockaddr_in or sockaddr_in6 structure.
host
A pointer to a buffer where the function can store the host name, or NULL if you don't need the name.
hostlen
The length of the host buffer, or 0 if you don't need the name.
serv
A pointer to a buffer where the function can store the service name, or NULL if you don't need the name.
servlen
The length of the serv buffer, or 0 if you don't need the name.
flags
Flags that change the default behavior of the function; zero or more of the following:
NI_NOFQDN
Return only the nodename portion of the FQDN for local hosts.
NI_NUMERICHOST
Return the numeric form of the host's address (i.e., by calling inet_ntop() instead of gethostbyaddr_r()).
NI_NAMEREQD
Indicate an error if the host's name can't be located in the DNS.
NI_NUMERICSERV
Return the numeric form of the service address (i.e., its port number) instead of its name.
NI_DGRAM
Specify that the service is a datagram service. This flag makes the function call getservbyport() with a second argument of udp instead of tcp. This is required for the few ports (512-514) that have different services for UDP and TCP.

You might have to set both NI_NUMERICHOST and NI_NUMERICSERV to support the -n flag that many commands provide.

Library:

libsocket

Use the -l socket option to qcc to link against this library.

Description:

The getnameinfo() function converts a sockaddr structure to a host name and a service name. It's similar to gethostbyaddr_r() and getservbyport(), and is the converse of getaddrinfo().

This function looks up the given IP address and port number in the DNS and system-specific database and fills the host and serv buffers with the associated node name and service name, respectively. If the host's name can't be located, the numeric form is returned instead, unless you specified NI_NAMEREQD in the flags.

You can specify zero for hostlen or servlen if you don't need the corresponding name. Otherwise, you must provide buffers large enough to hold the nodename and the service name, including the terminating null characters.

Most systems don't provide constants that specify the maximum size of either a FQDN or a service name. In order to aid your application in allocating buffers, the following constants are defined in <netdb.h>:

#define NI_MAXHOST  1025
#define NI_MAXSERV    32

This implementation allows numeric IPv6 address notation with scope identifier, as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt. An IPv6 link-local address appears as a string such as fe80::1%ne0. See getaddrinfo() for the notation.

Returns:

0
Success.
EAI_AGAIN
The name couldn't be resolved at this time. Future attempts may succeed.
EAI_BADFLAGS
The value of flags is invalid.
EAI_FAIL
A nonrecoverable error occurred.
EAI_FAMILY
The address family wasn't recognized, or the address length was invalid for the specified family.
EAI_MEMORY
There was a memory allocation failure.
EAI_NONAME
The name doesn't resolve for the supplied parameters. NI_NAMEREQD is set and the host's name can't be located, or both the nodename and service name were null.
EAI_SYSTEM
A system error occurred (errno is set).

Examples:

The following code gets the numeric hostname and the service name for a given socket address. Note that there's no hardcoded reference to a particular address family.

struct sockaddr *sa;    /* input */
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
   sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
   errx(1, "could not get numeric hostname");
   /*NOTREACHED*/
   }
   printf("host=%s, serv=%s\n", hbuf, sbuf);

The following version checks if the socket address has reverse address mapping:

struct sockaddr *sa;    /* input */
char hbuf[NI_MAXHOST];

if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
   NI_NAMEREQD)) {
   errx(1, "could not resolve hostname"); /*NOTREACHED*/
   }
   printf("host=%s\n", hbuf);

Classification:

POSIX 1003.1

Safety:  
Cancellation point Yes
Interrupt handler No
Signal handler No
Thread Yes