Network Interface Guide

Standard Routines

You might need to locate and construct network addresses. This section describes the routines that manipulate network addresses. Unless otherwise stated, functions presented in this section apply only to the Internet family.

Locating a service on a remote host requires many levels of mapping before client and server communicate. A service has a name for human use. The service and host names must be translated to network addresses. Finally, the address is used to locate and route to the host. The specifics of the mappings can vary between network architectures. Preferably, a network does not require that hosts be named, thus protecting the identity of their physical locations. It is more flexible to discover the location of the host when it is addressed.

Standard routines map host names to network addresses, network names to network numbers, protocol names to protocol numbers, and service names to port numbers, and the appropriate protocol to use in communicating with the server process. The file netdb.h must be included when using any of these routines.

Host and Service Names

The interfaces getaddrinfo(3SOCKET), getnameinfo(3SOCKET), and freeaddrinfo(3SOCKET) provide a simplified method of translating between the names and addresses of a service on a host. For IPv6, these interfaces can be used instead of calling getipnodebyname(3SOCKET) and getservbyname(3SOCKET) and then figuring out how to combine the addresses. Similarly, for IPv4, these interfaces can be used instead of gethostbyname(3NSL) and getservbyname(3SOCKET). Both IPv6 and IPv4 addresses are handled transparently.

getaddrinfo(3SOCKET) returns the combined address and port number of the specified host and service names. Since all of the information returned by getaddrinfo(3SOCKET) is dynamically allocated, it must be freed by freeaddrinfo(3SOCKET) to prevent memory leaks.getnameinfo(3SOCKET) returns the host and services names associated with a specified address and port number. To print error messages based on the EAI_xxx codes returned by getaddrinfo(3SOCKET) and getnameinfo(3SOCKET), call gai_strerror(3SOCKET).

An example of using getaddrinfo(3SOCKET) follows:

    struct addrinfo         *res, *aip;
    struct addrinfo         hints;
    int                     sock = -1;
    int                     error;

    /* Get host address.  Any type of address will do. */
    bzero(&hints, sizeof (hints));
    hints.ai_flags = AI_ALL|AI_ADDRCONFIG;
    hints.ai_socktype = SOCK_STREAM;

    error = getaddrinfo(hostname, servicename, &hints, &res);
    if (error != 0) {
        (void) fprintf(stderr, "getaddrinfo: %s for host %s service %s\n",
                 gai_strerror(error), hostname, servicename);
        return (-1);
    }
 

After processing the information returned by getaddrinfo(3SOCKET) in the structure pointed to by res, the storage should be released by

        freeaddrinfo(res);

getnameinfo(3SOCKET) is particularly useful in identifying the cause of an error as in the following example:

    struct sockaddr_storage faddr;
    int                     sock, new_sock;
    socklen_t               faddrlen;
    int                     error;
    char                    hname[NI_MAXHOST];
    char                    sname[NI_MAXSERV];

     ...
         faddrlen = sizeof (faddr);
         new_sock = accept(sock, (struct sockaddr *)&faddr, &faddrlen);
         if (new_sock == -1) {
             if (errno != EINTR && errno != ECONNABORTED) {
                 perror("accept");
             }
             continue;
         }        
         error = getnameinfo((struct sockaddr *)&faddr, faddrlen, hname, 
                     sizeof (hname), sname, sizeof (sname), 0);
         if (error) {
             (void) fprintf(stderr, "getnameinfo: %s\n",
                         gai_strerror(error));
         } else {
             (void) printf("Connection from %s/%s\n", hname, sname);
         }

hostent - Host Names

An Internet host-name-to-address mapping is represented by the hostent structure:

struct hostent {
	   char  *h_name;            /* official name of host */
	   char  **h_aliases;        /* alias list */
	   int   h_addrtype;         /* hostaddrtype(e.g.,AF_INET6) */
	   int   h_length;           /* length of address */
	   char  **h_addr_list;      /* list of addrs, null terminated */
};
/*1st addr, net byte order*/
#define h_addr h_addr_list[0]

getipnodebyname(3SOCKET) maps an Internet host name to a hostent structure, getipnodebyaddr(3SOCKET) maps an Internet host address to a hostent structure, freehostent(3SOCKET) frees the memory of a hostent structure, and inet_ntop(3SOCKET) maps an Internet host address to a displayable string.

The routines return a hostent structure containing the name of the host, its aliases, the address type (address family), and a NULL-terminated list of variable length addresses. The list of addresses is required because a host can have many addresses. The h_addr definition is for backward compatibility, and is the first address in the list of addresses in the hostent structure.

netent - Network Names

The routines to map network names to numbers and back return a netent structure:

/*
 * Assumes that a network number fits in 32 bits.
 */
struct netent {
   char     *n_name;      /* official name of net */
   char     **n_aliases;  /* alias list */
   int      n_addrtype;   /* net address type */
   int      n_net;        /* net number, host byte order */
};

getnetbyname(3SOCKET), getnetbyaddr_r(3SOCKET), and getnetent(3SOCKET) are the network counterparts to the host routines described above.

protoent - Protocol Names

The protoent structure defines the protocol-name mapping used with getprotobyname(3SOCKET), getprotobynumber(3SOCKET), and getprotoent(3SOCKET):

struct protoent {
   char     *p_name;          /* official protocol name */
   char     **p_aliases       /* alias list */
   int      p_proto;          /* protocol number */
};

servent - Service Names

An Internet family service resides at a specific, well-known port and uses a particular protocol. A service-name-to-port-number mapping is described by the servent structure:

struct servent {
   char     *s_name;         /* official service name */
   char     **s_aliases;     /* alias list */
   int      s_port;          /* port number, network byte order */
   char     *s_proto;        /* protocol to use */
};
getservbyname(3SOCKET) maps service names and, optionally, a qualifying protocol to a servent structure. The call:
sp = getservbyname("telnet", (char *) 0);
returns the service specification of a telnet server using any protocol. The call:
sp = getservbyname("telnet", "tcp");

returns the telnet server that uses the TCP protocol. getservbyport(3SOCKET) and getservent(3SOCKET) are also provided. getservbyport(3SOCKET) has an interface similar to that of getservbyname(3SOCKET); an optional protocol name can be specified to qualify lookups.

Other Routines

In addition to address-related database routines, there are several other routines that simplify manipulating names and addresses. Table 2-3 summarizes the routines for manipulating variable-length byte strings and byte-swapping network addresses and values.

Table 2-3 Runtime Library Routines

Call 

Synopsis 

memcmp(3C)

Compares byte-strings; 0 if same, not 0 otherwise

memcpy(3C)

Copies n bytes from s2 to s1

memset(3C)

Sets n bytes to value starting at base

htonl(3SOCKET)

32-bit quantity from host into network byte order 

htons(3SOCKET)

16-bit quantity from host into network byte order 

ntohl(3SOCKET)

32-bit quantity from network into host byte order 

ntohs(3SOCKET)

16-bit quantity from network into host byte order 

The byte-swapping routines are provided because the operating system expects addresses to be supplied in network order. On some architectures, the host byte ordering is different from network byte order, so programs must sometimes byte-swap values. Routines that return network addresses do so in network order. Byte-swapping problems occur only when interpreting network addresses. For example, the following code formats a TCP or UDP port:

printf("port number %d\n", ntohs(sp->s_port));

On certain machines, where these routines are not needed, they are defined as null macros.