Connected UDP and ICMP messages

  • Thread starter Thread starter Paul D.Smith
  • Start date Start date
P

Paul D.Smith

Can anyone suggest why I don't seem to detect ICMP "unreachable" errors on a
connected UDP socket running on Windows 2000?

Thanks,
Paul DS.
 
Paul D.Smith said:
Can anyone suggest why I don't seem to detect ICMP "unreachable" errors on a
connected UDP socket running on Windows 2000?

something is confusing here. udp doesn't 'connect', its a broadcast
protocol. and icmp is a different protocol than udp so why would you expect
those errors from udp?
 
Firstly, there is the concept of "connected UDP" and it is supported both by
Windows and UNIX. This provides two things:

1. The ability to use send() instead of sendto(); i.e. the socket remembers
where you want the datagrams to go.
2. A "collector" for errors such as "there's no host" that are triggered by
ICMP messages that TCP handles but which standard unconnected UDP does not.

Note that "connected UDP" does NOT create any additional flows "on the wire"
and there is no difference between unconnected/unconnected,
connected/unconnected and connected/connected pairs of sockets if you follow
the data flows using Ethereal.

Secondly, ICMP is the method through which "this address is unreachable",
and other errors, are reported to most IP stacks. The stack uses these to,
for example, generate a connect() error if using TCP.

By using connected UDP, UNIX allows the following behaviour.

- First UDP send "just goes". There have been no earlier data flows so the
sender has no idea whether the datagram will reach the destination or not.
- Subsequent send() request MAY fail if an ICMP has told the IP stack that
the first UDP datagram could not be routed.

This functionality means that UDP based protocols, which often have
"retransmit until I get a response" strategies, have a way of detected "the
target address ain't listening" without having to wait for lengthy timeouts.

Unfortunately, this doesn't seem to work on MS Windows so I'm trying to find
out whether there is some special option that needs to be set.

Paul DS.
 
from send() AND sendto() error list:
WSAECONNRESET The virtual circuit was reset by the remote side
executing a "hard" or "abortive" close. For UPD sockets, the remote host was
unable to deliver a previously sent UDP datagram and responded with a "Port
Unreachable" ICMP packet. The application should close the socket as it is
no longer usable.


the only apparent difference between using a 'connected' udp socket and a
plain one is your #1 below... the connect() call on a udp socket just
remembers the destination address... it appears on a quick check that the
error returns are the same. are you perhaps not checking for the right error
code on the send/sendto calls?
 
Oh if only! I both bind() and connect() my UDP socket but the return codes
from all my attempts to send() indicate that there is no error at all,
despite Ethereal revealing correct ICMP flows indicating "unreachable".

Paul DS.
 
Solved it, sort of.

It seems that this is a Windows "feature". For pre-Windows 2000, there were
basically no errors resulting from ICMP with connected UDP (despite the MSDN
information that we both found). However, for Windows 2000 onwards, you can
see the error if you attempt a read() (yes readfrom()!). So what you need
is the following...


sendto() - 1st one always succeeds
recvfrom(receive 0 bytes!) - might work, might not.
.... a little later, the send is retried if the first send/receive seemed
OK...
sendto() - will still work
recvfrom(receive 0 bytes!) - will fail if an ICMP message had been received.

Crap? Yes, but it works!

For information, look search MSDN for the expected error code WSAECONNRESET
and you will find an INFO: and two articles, one explaining this new
"feature" of Windows 2000, and the other explaining how pre Windows 2000
"worked".

Paul DS.
 
were you checking for errors after the first send() or the second one? the
first one with udp will probably never show the error, it would only be the
second one that could return an error code, and then probably only if it was
after a long enough delay that the icmp response could be returned... which
could be a bit of a delay depending on how far the router was along the
route that knew the address was unreachable.
 
Both. As you did, I expected the first send() to work and the second to
fail. I tried leaving a little time between the two sends (up to 5
seconds!) but this had no affect. The second send() always succeeded.

If you like, send me your e-mail address and I will happily send you my test
code, just no comments about the quality since "hacked together" is a good
description ;-).

Paul DS.
(e-mail address removed)
 
Back
Top