hoopajoo.net
Quick and dirty daemons with inetd
Quick and dirty daemons with inetd
⇐ Back to Networking

Questions, comments, or corrections? Send me a message.

Almost every linux distribtion (and many Unix flavours) have an inetd superserver in the form of inetd, xinetd, or whatever. Most people don't get beyond using it to install services, but for the more network savvy it is useful to know how and why it works.

If you aren't familiar with inetd, first have a look at your /etc/inetd.conf file. It should contain lines like:

ftp    stream  tcp     nowait  root    /usr/sbin/wu.ftpd  wu.ftpd -l -i -a

While it may seem cryptic, if you understand some fundamental parts of networking it's really pretty simple. The first part, ftp designates the port, or in this case service listed in /etc/services, that this is bound to. This can be the symbolic name listed in /etc/services or the actual port number. The next, few chunks, stream/tcp/nowait tell the parameters for this service, and this is usually what you want. For more details, read up on the man page. The root says who to run the binary as when a client connects to the port. The next part /usr/sbin/wu.ftpd specifies the binary to run and all other arguments are the argument list, including argv[ 0 ], which will be the name of the binary.

Now all this seem like a lot of work for just setting up a daemon, right? Well, here's the magic part. All inetd does when a connection is present, is attach STDIN and STDOUT to the socket, so essentially anything that the socket receives is used as input for the command and anything it prints is pushed out the socket. While that might not seems all that neat, it really is. You can bind ANY command the a port this way.

Lets say you want to be able to get a process list without having to telnet in all the time. You could use a line like this:
9999 stream tcp nowait root /bin/ps ps ax

Then 'killall -HUP inetd' to tell it to reread it configuration. Now if you telnet to port 9999 by doing 'telnet localhost 9999' you should see a printout of your current process list. Pretty neat, eh? You could even use /bin/bash and connect a shell to a port, with no authentication! (hint, while cool it's a bad idea)

There are some security issues to address. First off, you probably don't want to be giving out any sensitive information, since anyone can connect and look. Tcp Wrappers comes in to play and can help some here. If you've ever worked with /etc/hosts.deny and hosts.allow then you've worked with tpcwrappers. Remember earlier I mentioned you pass all arguments, even argv[ 0 ] to the program to execute? Well, this is what tcpwrappers uses to determine what program to really call after checking the acl for the client. So, the ftp line might look like this instead:
ftp stream tcp nowait root /usr/sbin/tcpd wu.ftpd -l -i -a

This tells inetd to run tcpd whel someone connects, but since you are passing the argv[ 0 ] as wu.ftpd then tcpd knows that you really want to call wu.ftpd and will do so, after verifying the client is allowed to connect.

This really just scratches the surface, not only can you use inetd to make quick services for your local network, I'm sure you programmers have figured out that this can save you a heck of a lot of work in the 'accept(); fork();' loop that is so common in many daemons, essentially you don't need to write one for a custom daemon. For more information, consult your friendly man pages.

<plut>For a look at a simple file server, look at my simple remote update server. It uses inetd on the server side with a little perl script on the client side.