[comp.protocols.tcp-ip] Follow-up to my ICMP_UNREACH_PORT question

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