Network Interface Guide

inetd(1M) Daemon

One of the daemons provided with the system is inetd(1M). It is invoked at start-up time, and gets the services for which it listens from the /etc/inet/inetd.conf file. The daemon creates one socket for each service listed in /etc/inet/inetd.conf, binding the appropriate port number to each socket. See the inetd(1M) man page for details.

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

The primary benefit of inetd(1M) is that services that are not in use are not taking up 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, and can immediately read(2), write(2), send(3SOCKET), or recv(3SOCKET). Servers can use buffered I/O as provided by the stdio conventions, as long as they use fflush(3C) when appropriate.

getpeername(3SOCKET) returns the address of the peer (process) connected to a socket; it is useful in servers started by inetd(1M). For example, 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:

    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);
    }