socketsicmpraw-socketsrecvfrom

ICMP RAW Socket Incomplete Receive


I have implemented a RAW Socket in linux to send and receive ICMP Packets, I have created RAW Socket using socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) and start receiving the Packets using recvfrom. Initially i was receiving the packets with buffer len set to 1000 in recvfrom and then typecast the packets according to the ICMP and IP headers.

But when i start receiving the packets header and data individually (first receive the 20 necessary bytes for IP Headers and then finding the data len from that header and receive that much bytes of data using recvfrom ). I was not been able to receive the data part as i am not been able to receive the second data part.

First Method :

n=recvfrom(sockfd,buf,1000,0,(struct sockaddr *)&cliaddr,&clilen);
struct iphdr *ip_hdr = (struct iphdr *)buf;
struct icmphdr *icmp_hdr = (struct icmphdr *)((char *)ip_hdr + (4 * ip_hdr->ihl));

Second Method :

struct iphdr ip_hdr;
struct icmphdr icmp_hdr;
n=recvfrom(sockfd, &ip_hdr, 20 ,0,(struct sockaddr *)&cliaddr,&clilen);
len = ip_hdr->tot_len - ip_hdr.ihl*4 ;
n=recvfrom(sockfd, &icmp_hdr, len ,0,(struct sockaddr *)&cliaddr,&clilen);

In Second Case, the second receive do not receive anything.


Solution

  • Raw sockets don't provide a "stream" paradigm. Hence you can receive as much of the packet as you want in the initial recvfrom call. But whatever part of it you didn't receive will then be dropped. So your first method is the way to go: provide a large enough buffer to receive the IP header and its ICMP payload. Then parse it after you've received it.

    The same is true of UDP packets. Reference this question and this one. UDP is obviously a different protocol, but all the same considerations apply.