10.1 The Internet Super-Server

As in most other Unix systems, networking services are implemented as daemons in Linux. Each networking daemon responds to requests on a particular port. The Telnet service, for example, operates on port 23. For networking services to function properly, some process must be alive and listening on each corresponding port. Instead of starting all the networking daemons so that each would listen to its own port, however, most systems make use of an internet "super-server." This super-server is a special daemon that listens to the ports of all the enabled networking services. When a request comes in from a particular port, the corresponding networking daemon is started, and the request is passed on to it for service.

There are two main benefits to this scheme. First, only the minimal set of needed daemons is active at all times, and therefore, no system resources are wasted. Second, there is a centralized mechanism for managing and monitoring network services.

Though many networking services can be managed by the internet super-server, some services such as an HTTP server or an SNMP agent are almost always set up to have direct control of their ports for reasons of scalability and reliability. In fact, the daemons providing such services will not require an internet super-server to operate properly. For each networking service discussed in the following sections, we will consider whether the service depends on the super-server.

There are two main internet super-servers available for Linux, inetd and xinetd. Though inetd used to be the standard super-server for most Linux distributions, it is gradually being replaced by xinetd, which contains more features. But because inetd contains fewer features than xinetd, it is also smaller and may be better for an embedded Linux system.

10.1.1 inetd

inetd is part of one of the netkit packages available from ftp://ftp.uk.linux.org/pub/linux/Networking/netkit/. Netkit is a set of packages that provide various networking capabilities. inetd is part of the netkit-base package, which also contains ping. Like other netkit packages, netkit-base is distributed under the terms of a BSD license. In this section and throughout this chapter, I will use an ARM-based system as my system management (SYSM) module[1] to present the operations you need to carry out.

[1] See Section 1.3 for details about the components in my example system.

First, download netkit-base and extract it into your ${PRJROOT}/sysapps directory. For my SYSM module, I used netkit-base Version 0.17. Now, move to the directory where netkit-base was extracted:

$ cd ${PRJROOT}/sysapps/netkit-base-0.17

Before you begin configuring netkit-base, you need to modify the configure script to prevent it from trying to run test programs on your host. Because you are instructing it to use the compiler you built for the target, the test programs it compiles will be fit only for your target. Hence, these test programs will fail to run on the host, and the configure script fails to complete if it is not modified. To avoid these problems, edit the configure script and comment all the lines that attempt to execute the compiled binary by adding a # symbol at the beginning of each line. The actual test programs configure tries to run are all called _ _conftest. Here is an example commented line:

# ./_ _conftest || exit 1;

To build, inetd requires either glibc or uClibc. To link it against uClibc, however, you need to make sure that RPC support was enabled in uClibc. If uClibc was built with RPC disabled, which is the default, you must reinstall uClibc.

Once the configure script has been properly edited, configure and compile netkit-base:

$ CC=arm-linux-gcc ./configure --prefix=${TARGET_PREFIX}
$ make

Netkit-base builds quite rapidly. The binary generated is 24 KB in size when linked dynamically with glibc and stripped. When linked statically with glibc and stripped, the size of the binary is around 460 KB. With uClibc, the stripped binary is 24 KB when linked dynamically and 85 KB when linked statically. Regardless of the actual link method you choose, the resulting inetd binary is much smaller than the xinetd binary, as we shall see in the next section.

The file sizes provided throughout this chapter correspond to my own setup and you are likely to obtain slightly different sizes. Use the numbers provided here as an indication only, because your actual binaries are likely to have different sizes from mine. ARM code, for instance, and RISC code in general, is usually larger than x86 code.

In contrast with other packages we've built in other chapters, don't use make install, because the Makefiles were not properly built for cross-platform development. Among other things, they attempt to use the host's strip command to strip the binaries of their symbol tables.

To install inetd, copy the inetd binary and the sample configuration file manually to your target's root filesystem:

$ cp inetd/inetd ${PRJROOT}/rootfs/usr/sbin
$ cp etc.sample/inetd.conf ${PRJROOT}/rootfs/etc

Edit the inetd.conf file according to your own setup. In addition to inetd.conf, the etc.sample directory contains other file samples that may be used in your target's /etc directory, such as resolv.conf and services. For my SYSM module, for example, here's the inetd.conf entry for the Telnet daemon discussed in Section 10.3:

telnet  stream  tcp     nowait  root    /usr/sbin/telnetd

Once inetd is copied and configured, edit your target's /etc/inittab file to add a line for inetd. Here is an example line for my SYSM module that uses BusyBox's init:

::respawn:/usr/sbin/inetd -i

The -i option instructs inetd not to start as a daemon. Hence, init can respawn inetd if it dies for some unexpected reason.[2]

[2] The super-server is not normally subject to crashing. The reliance on init is therefore just an extra precaution.

Because netkit-base also includes ping, you will find a ping binary in the ping directory. You don't need to use this binary if you are already using BusyBox, however, since BusyBox includes a ping command.

For more information regarding the use of inetd, have a look at the man pages included in the netkit-base package under the inetd directory.

10.1.2 xinetd

xinetd is preferable to inetd on some systems, because it allows some secure authorization, provides extensive logging abilities, and can prevent denial-of-access attacks, among other things. Though the FAQ available from the xinetd project web site contains a complete list of advantages over inetd, suffice it to say that you should use the xinetd super-server if your embedded system is designed to provide extensive networking services or live in a hostile networking environment such as the Internet.

xinetd is distributed at http://www.xinetd.org/ under a BSD-like license. For my SYSM module, I used xinetd Version 2.3.9. Download and extract the xinetd package into your ${PRJROOT}/sysapps directory, and move into the package's directory for the rest of the manipulations:

$ cd ${PRJROOT}/sysapps/xinetd-2.3.9

As with inetd, xinetd can't be compiled with uClibc if it lacks certain features. In particular, xinetd will fail to build with uClibc if it doesn't support RPC and C99. In addition to the C library, xinetd depends on the math library (libm) and the cryptography library (libcrypt).

Configure, compile, and install xinetd:

$ CC=arm-linux-gcc ./configure --host=$TARGET --prefix=${TARGET_PREFIX}
$ make
$ make install

xinetd builds quite rapidly. The stripped dynamically linked binary itself is quite large, being 130 KB in size with either uClibc or glibc. When statically linked and stripped, the binary's size is 615 KB with glibc and 210 KB with uClibc. The xinetd package installs its components in the ${TARGET_PREFIX} directory. The build also installs manpages. The xinetd binary itself is installed in ${TARGET_PREFIX}. Copy it from that directory to your target's root filesystem and strip it:

$ cp ${TARGET_PREFIX}/sbin/xinetd ${PRJROOT}/rootfs/usr/sbin
$ arm-linux-strip ${PRJROOT}/rootfs/usr/sbin/xinetd

A sample configuration file is provided with xinetd, xinetd/sample.conf. Use this sample as the basis for configuring your target. Copy it to your target's root filesystem and edit it according to your needs:

$ cp xinetd/sample.conf ${PRJROOT}/rootfs/etc/xinetd.conf

Here is the entry in my SYSM module's xinetd.conf for the Telnet daemon discussed in Section 10.3:

service telnet
        socket_type             = stream
        wait                    = no
        user                    = root
        server                  = /usr/sbin/telnetd
        bind                    =
        log_on_failure         += USERID

Finally, edit your target's /etc/inittab file to add a line for xinetd. As for inetd, I had to add a line for xinetd in my SYSM module's inittab:


Unlike inetd, xinetd can be started only as a daemon. Therefore, it cannot be respawned by init if it dies.

For more information regarding the use and configuration of xinetd, look at the manpages included in the xinetd directory of the xinetd package. The project's web site also includes an FAQ and a mailing list.