UDP, TFTP, and IPC design

Bob Walsh walsh at bbn-labs-b.ARPA
Thu Feb 7 08:08:23 AEST 1985


I've recently noticed a problem using TFTP on 4.2BSD.  The scenario goes
like:

		8.1.0.8		128.11.98.98
	BBN-VAX				X
		10.1.0.82

machine X tries to receive a file from BBN-VAX using TFTP.  The tftpd on
bbn-vax is in the state

	local host = 0, local port = TFTP, foreign host = 0, foreign port = 0

Upon reception of a TFTP RRQ packet on interface 8.1.0.8, the tftpd does a
connect to the remote system.  Since the local address is not bound, the
connect system call will pick one for the process, basing it upon the route
to be used to get to the destination.  (Well, actually the distributed
4.2 code uses an arbitrary interface but the effect is the same.)  If the
interface happens to be 8.1.0.8, then all is fine and dandy.  If the
interface is 10.1.0.82, then problems occur because the tftp process on
machine X will try to send packets to 8.1.0.8 and the tftpd will never
receive them.

In TFTP, only the first packet goes to the advertised TFTP server port.
The rest of the communication progresses with the server using another
port.  "O.k., when the tftp process on X updates the remote server port, it
can update the remote address that it talks to as well," you say.

		8.1.0.8		128.11.1.2
	BBN-VAX				X	
		10.1.0.82	12.1.2.3

This doesn't work if machine X is also multi-homed, since the kernel on X
may pick a new source address based on the route to the new remote
address.


The crux of the problem is that the design of the datagram IPC facilities
does not tell a datagram recipient to what address a datagram was sent.
There is a work around - never connect in /etc/tftpd.  But then, some
of the utility associated with using connect on datagram sockets is lost.
And there really isn't a strong reason to duplicate at the application
level information that is present for the transport layer.

The advantages of using connect() and bind() with datagram sockets are:
1.  waking up the process only for packets it was interested in, and
2.  time saved since addresses used by recv() and send() don't have to
	be copied into and out of the kernel all the time.
3.  Routing may also be done less frequently.

Has anyone ever wondered why the SO_REUSEADDR privilege may be
requested by a program (possibly a liar) rather than must be granted by
the original process at the address (presumably reasonable or secure)?

grist for the mill,
bob walsh



More information about the Comp.unix.wizards mailing list