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
Post a Comment