c - ICMP pointer and checksum -


i reused raw socket snippet site , removed tcp part , added icmp part request echo. both machines on same lan, running ubuntu 32 bit. gave checksum function icmp-pointer failed calculate correct checksum:

icmph->icmp_sum = csum( (unsigned short *) datagram + sizeof(struct iphdr), sizeof(struct icmp_header)); 

then tried out raw numbers offsets until worked out:

icmph->icmp_sum = csum( (unsigned short *) datagram + 10, sizeof(struct icmp_header)); 

i checked position of pointers , size of ip-header-struct:

datagram-pointer: 0xbff94680 ip-pointer: 0xbff94680 icmp-pointer: 0xbff94694 

as can see, icmp-pointer 20 away datagram- , ip-pointer. why 10 job?

thank in advance.

ps: here code:

**/*     raw tcp packets     silver moon (m00n.silv3r@gmail.com) */ #include<stdio.h> //for printf #include<string.h> //memset #include<sys/socket.h>    //for socket ofcourse #include<stdlib.h> //for exit(0); #include<errno.h> //for errno - error number #include<netinet/tcp.h>   //provides declarations tcp header #include<netinet/ip.h>    //provides declarations ip header   //icmp header struct icmp_header {     u_char icmp_type;     u_char icmp_code;     u_short icmp_sum;     u_short icmp_ident;     u_short icmp_seq; };  /*     generic checksum calculation function */ unsigned short csum(unsigned short *ptr,int nbytes)  {     register long sum;     unsigned short oddbyte;     register short answer;      sum=0;     while(nbytes>1) {         sum+=*ptr++;         nbytes-=2;     }     if(nbytes==1) {         oddbyte=0;         *((u_char*)&oddbyte)=*(u_char*)ptr;         sum+=oddbyte;     }      sum = (sum>>16)+(sum & 0xffff);     sum = sum + (sum>>16);     answer=(short)~sum;      return(answer); }  int main (void) {     //create raw socket     int s = socket (af_inet, sock_raw, ipproto_raw);      if(s == -1)     {         //socket creation failed, may because of non-root privileges         perror("failed create socket");         exit(1);     }      //datagram represent packet     char datagram[sizeof(struct iphdr) + sizeof(struct icmp_header)] , source_ip[32];      //zero out packet buffer     memset (datagram, 0, sizeof(struct iphdr) + sizeof(struct icmp_header));      //ip header     struct iphdr *iph = (struct iphdr *) datagram;      //tcp header     struct icmp_header *icmph = (struct icmp_header *) (datagram + sizeof (struct iphdr));     struct sockaddr_in sin;       //some address resolution     strcpy(source_ip , "10.0.2.5");     sin.sin_family = af_inet;     sin.sin_addr.s_addr = inet_addr ("10.0.2.4");      //fill in ip header     iph->ihl = 5;     iph->version = 4;     iph->tos = 0;     iph->tot_len = sizeof (struct iphdr) + sizeof (struct icmp_header);     iph->id = htonl (54321); //id of packet     iph->frag_off = 0;     iph->ttl = 255;     iph->protocol = 1; //use icmp afterwards     iph->check = 0;      //set 0 before calculating checksum     iph->saddr = inet_addr ( source_ip );    //spoof source ip address     iph->daddr = sin.sin_addr.s_addr;      //ip checksum     iph->check = csum ((unsigned short *) datagram, iph->tot_len);      //fill in icmp header     icmph->icmp_type = 8; //ping request     icmph->icmp_code = 0;     icmph->icmp_sum = 0; //set 0 before calculating checksum      icmph->icmp_ident = 0x4142; //just numbers     icmph->icmp_seq = 0x4142; //just numbers      icmph->icmp_sum = csum( (unsigned short *) datagram + 10, sizeof(struct icmp_header));//? why 10 , not sizeof(struct iphdr)=20?      //for debugging      printf("datagram-pointer: %p\n", (void*) datagram);       printf("ip-pointer: %p\n", (void*) iph);      printf("icmp-pointer: %p\n\n", (void*) icmph);       printf("ip-struct size: %d\n",  sizeof(struct iphdr));       //ip_hdrincl tell kernel headers included in packet     int 1 = 1;     const int *val = &one;     if (setsockopt (s, ipproto_ip, ip_hdrincl, val, sizeof (one)) < 0)     {         perror("error setting ip_hdrincl");         exit(0);     }      //senden     if (sendto (s, datagram, iph->tot_len ,  0, (struct sockaddr *) &sin, sizeof (sin)) < 0)     {         perror("sendto failed");     }     //data send     else     {         printf ("packet send. length : %d \n" , iph->tot_len);     }     return 0; }  //complete** 

sizeof gives size in bytes, not arbitrary "word". means add offset of 20 16-byte words in first alternative.

you should divide result of sizeof size of unsigned short:

icmph->icmp_sum = csum( (unsigned short *) datagram + sizeof(struct iphdr) / sizeof(unsigned short), sizeof(struct icmp_header)); 

Comments

Popular posts from this blog

javascript - Create a stacked percentage column -

Optimising Firebase database by automatically overwriting data -

javascript - Angular UI-Grid customTemplate directive causing rows to load slowly/? -