Subject: Re: Linux ip codeReply-to: (fwd)
To: Ken Hornstein <kenh@cmf.nrl.navy.mil>
From: Greg Hudson <ghudson@MIT.EDU>
List: current-users
Date: 05/06/1995 00:24:47
>>> o	Broken UDP error handling.

I think this refers to how BSD networking code handles ICMP port
unreachable and other such messages in response to UDP packets.  BSD
will only report the error to the application (interrupting select()
and handing an error return to the next UDP operation)if the UDP
socket is connect()ed to the address where the port unreachable came
from, whereas Linux will forward the error even if the socket is not
connected.  Mind you, this is somewhat useless, since it's impossible
to tell *which* address you got the port unreachable for (you could
imagine filling this in for a recvfrom(), I guess, but Linux doesn't
appear to do this).  Nevertheless, Alan Cox believes that this
violates RFC 1122, presumably the following section:

         4.1.3.3  ICMP Messages

            UDP MUST pass to the application layer all ICMP error
            messages that it receives from the IP layer.  Conceptually
            at least, this may be accomplished with an upcall to the
            ERROR_REPORT routine (see Section 4.2.4.1).

            DISCUSSION:
                 Note that ICMP error messages resulting from sending a
                 UDP datagram are received asynchronously.  A UDP-based
                 application that wants to receive ICMP error messages
                 is responsible for maintaining the state necessary to
                 demultiplex these messages when they arrive; for
                 example, the application may keep a pending receive
                 operation for this purpose.  The application is also
                 responsible to avoid confusion from a delayed ICMP
                 error message resulting from an earlier use of the same
                 port(s).

Here's the Linux code dealing with this issue (from net/inet/udp.c):

	/*
	 *	Various people wanted BSD UDP semantics. Well they've come 
	 *	back out because they slow down response to stuff like dead
	 *	or unreachable name servers and they screw term users something
	 *	chronic. Oh and it violates RFC1122. So basically fix your 
	 *	client code people.
	 */
	 
#ifdef CONFIG_I_AM_A_BROKEN_BSD_WEENIE
	/*
	 *	It's only fatal if we have connected to them. I'm not happy
	 *	with this code. Some BSD comparisons need doing.
	 */
	 
	if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) 
	{
		sk->err = icmp_err_convert[err & 0xff].errno;
		sk->error_report(sk);
 	}
#else
	if (icmp_err_convert[err & 0xff].fatal)
	{
		sk->err = icmp_err_convert[err & 0xff].errno;
		sk->error_report(sk);
	}
#endif