wayne@ultra.UUCP (Wayne Hathaway) (05/04/89)
Well, I got several responses to my question the other day of "Why does UDP bother returning an ICMP_UNREACH_PORT and why does IP care about ports anyway?" Some were copied to tcp-ip and (apparently) some were not, so bits of the following may be obscure. 1) I was in fact aware of TCP's RST; having a catch-all "something is wrong" built into the protocol does NOT preclude sending additional information, in this case via ICMP. Especially since RST means a lot of things OTHER than "nobody listening on the port" -- check pages 33-37 of RFC 793 some time. (I'll admit I have trouble seeing how the information would always get back to the correct user, but then see item 3 below.) 2) On the other hand, it sure seems to me that the TCP protocol IS the correct place for the basic RST function, and in fact I would argue that UDP is the correct place for its equivalent. In other words, why didn't the UDP designers include a "UCMP" that operated at the correct level? Several commenters alluded to "layering violations" and "warts" and the like, and it seems to me it basically boils down to a choice of having a small but more specific wart built into every protocol or having a small number of big catch-all warts that various layers may or may not be able to use. No particular argument as to which approach is better, just the observation that either one is likely to get very dirty. Philosopher A: Every protocol that provides delivery based on something like a port should include some mechanism WITHIN THE PROTOCOL for notifying senders of delivery errors. Philosopher B: But UDP is a pure datagram protocol; it has no concept of notifying senders of ANYTHING. Philosopher A: Then why does it try to use ICMP to do something that wasn't important enough to include in UDP itself? Philosopher B: Because it is there?!? Hmm ... 3) Several commenters pointed out that what is expected is that the receiving UDP, noticing that there is nobody to receive the datagram, sends the ICMP_UNREACH_PORT back to through the various IPs to the sending UDP, whose responsibility it is to notify the sending application. In fact, one person pointed me to section 4.1.3.3 of the draft Host Requirements RFC, where it states that "UDP MUST pass ICMP error messages that it receives from the IP layer transparently up to the application layer." [Emphasis in the original.] Here I have a couple of problems, one minor and one major. The minor problem: What does "transparently" mean? That I must pass EXACTLY the bits of the ICMP message itself, which would require that every application be able to parse ICMP messages, or can I translate it into something more reasonable for my environment (such as a few coded parameters or an errno or even a signal)? The major problem: How on earth is the sending UDP going to know what application sent the original datagram??? Sure, it has the sending port number, but what's to stop the following: Process A: socket(); bind(local_port_X); sendto(...); <----| exit(); | | Process B: socket(); | bind(local_port_X); | | Along about now an ICMP_UNREACH_PORT from here comes roaring in -- exactly what does UDP do with it? Poor Process B is definitely NOT going to be expecting it, and if (as one commenter suggested) it generates a SIGPIPE, boy is Process B gonna be surprised! [A couple of the comments mentioned this as well.] Based on this, I would like to recommend that the authors of the Host Requirements RFC reconsider section 4.1.3.3. Also they should add precise definitions of terms like "transparently." 4) Finally, a nit but an important one (if that makes any sense!). In one response, ames!earth.cray.com!droid (Andy Nicholson) says "TCP and UDP protocols make a lot of assumptions about how IP works in order to gain some performance improvements, like sticking in a partially filled IP header at the front of the TCP or UDP packet that is passed on to IP." I must strongly disagree: the TCP and UDP *PROTOCOLS* do NOT make any such assumptions; certain *IMPLEMENTATIONS* may well do so. Clearly the idea of preallocated skeleton headers and the like is implementation, not protocol. Anyway, an interesting bit of repartee; I think the bottom line is that error notification is not pretty regardless of how it is done, and there are arguments to support both sides. Cheers. Wayne Hathaway Ultra Network Technologies domain: wayne@Ultra.COM 101 Daggett Drive Internet: ultra!wayne@Ames.ARC.NASA.GOV San Jose, CA 95134 uucp: ...!ames!ultra!wayne 408-922-0100 PS: Actually, I do have one continuing question: Could some BSD guru out there please tell me if the BSD UDP in fact DOES notify anyone when it gets an ICMP_UNREACH_PORT, and how? I've got the 4.3 source but not the familiarity to answer this definitively. I don't SEE any such notification, and there is no EPORTUNREACH sys/errno.h, but ... Thanks! PPS: Note that I believe that "PORT unreachable" is fundamentally different from "HOST unreachable" or "NETWORK unreachable." For "port unreachable" the message HAS gotten to the appropriate protocol layer in the correct host; true peer-to-peer communication IS taking place, so the peers themselves CAN discuss the error with no outside help. (As mentioned, whether they SHOULD do so is subject to discussion.) For the other two, there is NO peer-to-peer communication so any error reporting MUST involve outside help. Nuff (too much?) said.
djm@lupine.UUCP (Dave Mackie) (05/09/89)
> PS: Actually, I do have one continuing question: Could some BSD guru > out there please tell me if the BSD UDP in fact DOES notify anyone > when it gets an ICMP_UNREACH_PORT, and how? I've got the 4.3 source > but not the familiarity to answer this definitively. I don't SEE any > such notification, and there is no EPORTUNREACH sys/errno.h, but ... This isn't pretty! IP receives the ICMP message and eventually calls udp_ctlinput(). UDP then use inetctlerrmap[] (ip_input.c) to map the ICMP type to a BSD error number. In this case ICMP PORT UNREACHABLE gets mapped to ECONNREFUSED. The routine in_pcbnotify() then gets called to find the correct pcb to deliver the error to. If your just using sendto() then there is no pcb with the correct source/destination address pair in the pcb list, and so the error message gets dropped. Dave Mackie Network Computing Devices djm@ncd.com