2017-07-28 18 views
1

rawソケットスニペットをsiteから再利用し、TCP部分を削除し、ICMP部分を追加してエコーを要求しました。両方のマシンが同じLAN上にあり、Ubuntu 32ビットを実行しています。 私はチェックサム機能私のICMP-ポインタを与えたが、それは正しいチェックサムを計算するために失敗しました:それは働いまでICMPポインタとチェックサム

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

は、その後、私はオフセットとして、いくつかの生の数値を試してみた:私もチェックし

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

をポインタの位置及びIPヘッダ-構造体のサイズ:あなたが見ることができるように

Datagram-Pointer: 0xbff94680 
IP-Pointer: 0xbff94680 
ICMP-Pointer: 0xbff94694 

は、ICMP-ポインタが離れDatagram-とIP-ポインタから20です。なぜ10人がその仕事をしますか?

ありがとうございます。

PS:

**/* 
    Raw TCP packets 
    Silver Moon ([email protected]) 
*/ 
#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 - the error number 
#include<netinet/tcp.h> //Provides declarations for tcp header 
#include<netinet/ip.h> //Provides declarations for 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 a raw socket 
    int s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); 

    if(s == -1) 
    { 
     //socket creation failed, may be because of non-root privileges 
     perror("Failed to create socket"); 
     exit(1); 
    } 

    //Datagram to represent the packet 
    char datagram[sizeof(struct iphdr) + sizeof(struct icmp_header)] , source_ip[32]; 

    //zero out the 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 the 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 this packet 
    iph->frag_off = 0; 
    iph->ttl = 255; 
    iph->protocol = 1; //Use ICMP afterwards 
    iph->check = 0;  //Set to 0 before calculating checksum 
    iph->saddr = inet_addr (source_ip); //Spoof the source ip address 
    iph->daddr = sin.sin_addr.s_addr; 

    //Ip checksum 
    iph->check = csum ((unsigned short *) datagram, iph->tot_len); 

    //Fill in the ICMP Header 
    icmph->icmp_type = 8; //Ping Request 
    icmph->icmp_code = 0; 
    icmph->icmp_sum = 0; //Set to 0 before calculating checksum 
    icmph->icmp_ident = 0x4142; //Just some Numbers 
    icmph->icmp_seq = 0x4142; //Just some Numbers 

    icmph->icmp_sum = csum((unsigned short *) datagram + 10, sizeof(struct icmp_header));//? Why 10 and 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 to tell the kernel that headers are included in the packet 
    int one = 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 successfully 
    else 
    { 
     printf ("Packet Send. Length : %d \n" , iph->tot_len); 
    } 
    return 0; 
} 

//Complete** 

答えて

2

sizeofあなたバイトでのサイズではなく、いくつかの任意の "言葉" を与える:ここでは、コードです。つまり、最初の選択肢に16バイトの語句20のオフセットを追加します。

あなたがunsigned shortのサイズによってsizeofの結果を分割する必要があります: `(符号なしshort *)((CHAR *)グラム+のsizeof:` char`サイズ単位で加算を行う、あるいは

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

(struct iphdr)) 'を実行します。 –

+0

ありがとう@TobySpeight私はこのアプローチが好きです。 – user3880174

関連する問題