I am learning RAW sockets. In the below code i am trying to print all ICMP packets headers information. Looks like some error in the code. Can anyone please help me where i am wrong.
# include <unistd.h>
# include <sys/socket.h>
# include <sys/types.h>
# include <string.h>
# include <netinet/in.h>
# include <stdio.h>
# include<stdlib.h>
main(){
int sockfd,retval,n;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
char buf[10000];
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0){
perror("sock:");
exit(1);
}
clilen = sizeof(struct sockaddr_in);
while(1){
printf(" before recvfrom\n");
n=recvfrom(sockfd,buf,10000,0,(struct sockaddr *)&cliaddr,&clilen);
printf(" rec'd %d bytes\n",n);
buf[n]='\0';
printf(" msg from client = %s\n",buf);
}
}
o/p
before recvfrom
rec'd 60 bytes
msg from client = E
before recvfrom
rec'd 52 bytes
You are trying to print raw packet data (including headers) as a string. In this case,
E
which is ascii0x45
is the first byte of the IP header. The upper 4 bits mean "IPv4" and the lower 4 bits is the IHL (number of 32-bit words in the IP header) which is 5*4 = 20 bytes.To properly access this data you should use the IP/ICMP header structs provided by linux. I've updated your code a little to illustrate:
Now, if I run that and
ping 127.0.0.1
: you see output like this:Here this shows a msgtype 8 (echo request) and msgtype 0 (echo reply). Beware that when accessing data this way from an array you can run into alignment problems (x86/x64 are happy to handle it for you, but other architectures may not be so generous). I'll leave that as an exercise to the reader ;).