The following code is a program designed to send ICMP echo requests and receive replies.
/*
Forgive my lack of error handling :)
*/
SOCKET ASOCKET = INVALID_SOCKET;
struct sockaddr saddr;
struct sockaddr_in *to = (struct sockaddr_in *) &saddr;
struct sockaddr_in from;
int fromsize = sizeof(from);
std::string ip = "[arbitrary ip address]";
struct ICMP {
USHORT type;
USHORT code;
USHORT cksum;
USHORT id;
USHORT seq;
}*_ICMP;
char sendBuffer[sizeof(struct ICMP)];
char recvBuffer[256];
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
memset(&saddr, NULL, sizeof(saddr));
ASOCKET = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
// Configure timeout
DWORD timeoutmilsec = 3000;
setsockopt(ASOCKET, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeoutmilsec, sizeof(timeoutmilsec));
to->sin_family = AF_INET;
inet_pton(AF_INET, ip.c_str(), &(to->sin_addr));
_ICMP = new ICMP();
_ICMP->type = 8;
_ICMP->code = 0;
_ICMP->cksum = 0;
_ICMP->id = rand();
_ICMP->seq++;
// I have omitted my declaration of checksum() for simplicity
_ICMP->cksum = checksum((u_short *)_ICMP, sizeof(struct ICMP));
memcpy(sendBuffer, _ICMP, sizeof(struct ICMP));
if (sendto(ASOCKET, sendBuffer, sizeof(sendBuffer), NULL, (sockaddr *)&saddr, sizeof(saddr)) == SOCKET_ERROR)
{
printf("sendto() failed with error: %u\n", WSAGetLastError());
return false;
}
if (recvfrom(ASOCKET, recvBuffer, sizeof(recvBuffer), NULL, (sockaddr *)&from, &fromsize) == SOCKET_ERROR)
{
if (WSAGetLastError() == TIMEOUTERROR)
{
printf("Timed out\n\n");
return false;
}
printf("recvfrom() failed with error: %u\n", WSAGetLastError());
return false;
}
My issue is that my recvfrom()
call does not receive any data and returns TIMEOUTERROR (10060) despite the fact that the ping has been replied to (Wireshark captures the request and reply being sent). sendto()
works but recvfrom()
behaves weirdly and I can't figure out what the problem is.
What I find interesting is recvfrom()
will receive data only when the gateway tells me that a host is unreachable; it won't if the host is reachable and has responded to the ping.
It turns out the whole time it was my firewall blocking the responses. The only error in my code was the size of my ICMP struct (mentioned by cshu).
Thanks for all the help everyone.