[syslinux] Issue with running tftpd-hpa in inetd mode?

Jeffrey Hutzelman
Thu, 30 Jan 2014 18:25:31 -0000

On Thu, 2014-01-30 at 11:25 -0500, Dan Swartzendruber
wrote:
> Hopefully I'm not out to lunch here.  I ported tftp-hpa to our
proprietary
> OS, VOS (at stratus.com).  We've always runs the old legacy tftpd from
> inetd, so I wanted to continue doing so with tftp-hpa.  It seems to work
> okay, but I noticed that the code in tftpd.c has a 'while (1)' loop
that
> has this at the end:
>
>         /*
>          * Now that we have read the request packet from the UDP
>          * socket, we fork and go back to listening to the socket.
>          */
>         pid = fork();
>         if (pid < 0) {
>             syslog(LOG_ERR, "fork: %m");
>             exit(EX_OSERR);     /* Return to inetd, just in case */
>         } else if (pid == 0)
>             break;              /* Child exit, parent loop */
>     }
>
>     /* Child process: handle the actual request here */
>
> What I noticed was, every request I did would work okay, but would leave
> the parent process waiting for data on the socket.  Note that xinetd
> already forks, so it is no longer waiting for us, and can (and will) field
> the next request just fine.  After 900 seconds (the timeout passed to the
> select call), the parent tftpd process terminates.  Maybe I am dense, but
> I don't understand how this loop can ever make sense if tftpd is
running
> out of xinetd?  You get a request, fork, the child breaks out of the loop
> and handles the request and exits.  The parent, however, is sitting there
> waiting for another request?

Correct.  Like most UDP-based inetd services, tftpd is intended to be
run in 'wait' mode.  When the first request arrives, inetd starts the
service but does not read the incoming packet (it can't, because it has
no way to pass it along to the server).  After that, inetd ignores that
socket until the server exits.  This isn't critical for tftp, but it
does help to keep down the number of times the server program is started
(an expensive operation) on a busy server.  For some other services, it
is critical, because the server must be able to exchange packets with
the client on the same port on which the original request arrived.

In fact, some inetd implementations simply cannot correctly handle a
udp/nowait service, so UDP-based services pretty much have to be
prepared to run in wait mode.

-- Jeff