I have an application that uses sendto() with UDP to check resources on different ports. How can I get the ICMP port unreachable packet using recvfrom()?
My recvfrom() is like this:
SOCKADDR_STORAGE saFrom;
int nFromLen = sizeof( SOCKADDR_STORAGE );
nReceived = recvfrom ( Socket, Buffer, BufferSize, 0, ( struct sockaddr * ) &saFrom, (socklen_t *)&nFromLen );
When an ICMP port unreachable occurs, nReceived = -1, and WSAGetLastError() returns WSAECONNRESET(10054).
But since I'm checking on different ports, I'd like a way of determining which port triggered the ICMP port unreachable message. How can I determine that? (Maybe I can set some socket options?)
Edit:
As per Len's suggestion(use ICMP only), I tried to create a socket by socket (AF_INET, SOCK_RAW, IPPROTO_ICMP), then call recvfrom() on it. recvfrom() returns 10022(WSAEINVAL) error because the socket is not bound. How should I fix that?
Best Answer
You can't, see my blog posting on the subject here: http://www.lenholgate.com/blog/2007/12/bug-in-overlapped-udp-port-unreachable-errors.html
If you're on XP, then you can use
SIO_UDP_CONNRESET
withWSAIoctl
to control if you getERROR_PORT_UNREACHABLE
reported rather thanWSAECONNRESET
but even with that set (or on an OS where this is the default) you still do not get the address of the remote port where the ICMP port unreachable happened.I suggest you use one socket per port you're checking, that way you'll be able to determine where the error came from. Or use ICMP directly.