[comp.protocols.tcp-ip] why UDP send ICMP port unreachable message?

guenther@irafs2.ira.uka.de (Guenther Schreiner) (03/02/91)

In article <9103011243.AA10028@ucbvax.Berkeley.EDU>,
TAYBENGH@NUSDISCS.BITNET writes:
> Hi netlanders,
>         After reading thru the implementation of TCP/IP from
> the book The Design and Implementation of the 4.3BSD OS (published by
> Addison-Wesley) and the source code of BSD4.3 TCP/IP, I am puzzled of
> the purpose of ICMP Port Unreachable error message sent by UDP that appeared
> in the routine udp_input(). According to my understanding, this ICMP message
> is never received by UDP, nor is reported to the user if the user send a
> UDP message to a non-existent server (destination port). So why it is sent
> by the UDP? Did I misunderstand sth?

 Even if it sounds strange, it is possible to establish a UDP "connection".
 If you do so (with the system call connect() and I/O with send()/recvfrom()),
  the I/O system calls will return EADDRNOTAVAIL, ENETDOWN and ENETUNREACH
  after an appropriate incoming ICMP message.
 In opposite to this the I/O calls will NOT return an error if you use a loose
  UDP connection (with sendto() and recvfrom() calls without a connect()).

 Hope this helps,
  Guenther

--
 Guenther Schreiner			University of Karlsruhe, West Germany
  c/o Fakultaet fuer Informatik		Phone: (0721) 608-2749
  Am Fasanengarten 5			UUCP:  ...!seismo!unido!uka!guenther
  7500 Karlsruhe 1			CSNET: guenther@ira.uka.de
					EARN:  GUENTHER at DKAUNI0I
--

rstevens@noao.edu (Rich Stevens) (03/02/91)

In article <9103011243.AA10028@ucbvax.Berkeley.EDU> TAYBENGH@NUSDISCS.BITNET writes:
> According to my understanding, this ICMP message
> is never received by UDP, nor is reported to the user if the user send a
> UDP message to a non-existent server (destination port).

UDP does indeed receive this message.  It's not documented well,
so you really need to go to the sources to see what's going on.
The publicly available "BSD Networking Release" suffices.

The sequence of events is:  icmp_input() receives the ICMP error.
The ICMP "type" is ICMP_UNREACH and the ICMP "code" is "port
unreachable".  This code is converted to PRC_UNREACH_PORT and
udp_ctlinput() is called to process the error.  udp_ctlinput()
calls in_pcbnotify(), converting the PRC_UNREACH_PORT error
into the ECONNREFUSED errno value, using the table inetctlerrmap[]
(in the file ip_input.c).  A 32-bit internet address is passed to
udp_ctlinput() and this address is passed again to in_pcbnotify().
This address is the address that the datagram was sent to that
generated the ICMP error.  The routine in_pcbnotify() is interesting
because it looks at this address and finds *every* socket that is
connect()ed to this address and sends those sockets the asynchronous
error ECONNREFUSED.

So there are three caveats: (1) you'll only know about the error if
you've done a connect(); (2) not only will you find out about the
error, but *every* process on your host that is UDP "connect()ed"
to the host that sends the ICMP port unreachable gets a ECONNREFUSED
error; (3) you usually don't find out about the error when you send()
the datagram to the port that no one is reading from, in most cases
you'll find out when you do a recv() on that socket (assuming the
classic send-a-datagram, receive-a-datagram scenario).

	Rich Stevens (rstevens@noao.edu)

TAYBENGH@NUSDISCS.BITNET (03/02/91)

Hi netlanders,
        After reading thru the implementation of TCP/IP from
the book The Design and Implementation of the 4.3BSD OS (published by
Addison-Wesley) and the source code of BSD4.3 TCP/IP, I am puzzled of
the purpose of ICMP Port Unreachable error message sent by UDP that appeared
in the routine udp_input(). According to my understanding, this ICMP message
is never received by UDP, nor is reported to the user if the user send a
UDP message to a non-existent server (destination port). So why it is sent
by the UDP? Did I misunderstand sth?
        Also did TCP use this message to inform the client when it tries to
initiate a connection to a non-existent server?
        Could somebody please explain this? Thanks a lot.

- Beng Hang (email: taybengh@nusdiscs.bitnet)
  Dept of Information Systems and Computer Science
  National University of Singapore

barmar@think.com (Barry Margolin) (03/02/91)

In article <9103011243.AA10028@ucbvax.Berkeley.EDU> TAYBENGH@NUSDISCS.BITNET writes:
>I am puzzled of
>the purpose of ICMP Port Unreachable error message sent by UDP that appeared
>in the routine udp_input().

Others have already given adequate answers to this question (I am quite
disheartened if the assertion that the port unreachable message is sent to
all sockets connected to the host that sent the ICMP, i.e. that it doesn't
restrict it to sockets connected to the unreachable port).

>        Also did TCP use this message to inform the client when it tries to
>initiate a connection to a non-existent server?

TCP doesn't use ICMP Port Unreachable.  Instead, the remote host responds
to the SYN with a RST instead of a SYN.  UDP needs to use ICMP because
there is no built-in handshake in the protocol, whereas TCP uses a
handshake to establish a connection and can include the error report as
part of the handshake.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

guy@auspex.auspex.com (Guy Harris) (03/03/91)

>The routine in_pcbnotify() is interesting because it looks at this
>address and finds *every* socket that is connect()ed to this address
>and sends those sockets the asynchronous error ECONNREFUSED.

The routine "in_pcbnotify()" is buggy.  It is *not* supposed to be doing
that.  It appears to be fixed in 4.3-reno and in SunOS 4.1, and may be
fixed in other systems as well.