Programming Interfaces Guide

inetd Daemon

The inetd(1M) daemon is invoked at startup time and gets the services for which the daemon listens from the /etc/inet/inetd.conf file. The daemon creates one socket for each service that is listed in /etc/inet/inetd.conf, binding the appropriate port number to each socket. See the inetd(1M) man page for details.

The inetd(1M) daemon polls each socket, waiting for a connection request to the service corresponding to that socket. For SOCK_STREAM type sockets, inetd(1M) accepts (accept(3SOCKET)) on the listening socket, forks (fork(2)), duplicates (dup(2)) the new socket to file descriptors 0 and 1 (stdin and stdout), closes other open file descriptors, and executes (exec(2)) the appropriate server.

The primary benefit of using inetd(1M) is that services not in use do not consume machine resources. A secondary benefit is that inetd(1M) does most of the work to establish a connection. The server started by inetd(1M) has the socket connected to its client on file descriptors 0 and 1. The server can immediately read, write, send, or receive. Servers can use buffered I/O as provided by the stdio conventions, as long as the servers use fflush(3C) when appropriate.

The getpeername(3SOCKET) routine returns the address of the peer (process) connected to a socket. This routine is useful in servers started by inetd(1M). For example, you could use this routine to log the Internet address such as fec0::56:a00:20ff:fe7d:3dd2, which is conventional for representing the IPv6 address of a client. An inetd(1M) server could use the following sample code:

struct sockaddr_storage name;
int namelen = sizeof (name);
char abuf[INET6_ADDRSTRLEN];
struct in6_addr addr6;
struct in_addr addr;

if (getpeername(fd, (struct sockaddr *) &name, &namelen) == -1) {
    perror("getpeername");
    exit(1);
} else {
    addr = ((struct sockaddr_in *)&name)->sin_addr;
    addr6 = ((struct sockaddr_in6 *)&name)->sin6_addr;
    if (name.ss_family == AF_INET) {
            (void) inet_ntop(AF_INET, &addr, abuf, sizeof (abuf));
    } else if (name.ss_family == AF_INET6 &&
               IN6_IS_ADDR_V4MAPPED(&addr6)) {
            /* this is a IPv4-mapped IPv6 address */
            IN6_MAPPED_TO_IN(&addr6, &addr);
            (void) inet_ntop(AF_INET, &addr, abuf, sizeof (abuf));
    } else if (name.ss_family == AF_INET6) {
            (void) inet_ntop(AF_INET6, &addr6, abuf, sizeof (abuf));

    }
    syslog("Connection from %s\n", abuf);
}