Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ICMP指针和校验和_C_Pointers_Ping_Icmp_Raw Sockets - Fatal编程技术网

ICMP指针和校验和

ICMP指针和校验和,c,pointers,ping,icmp,raw-sockets,C,Pointers,Ping,Icmp,Raw Sockets,我重用了这个原始套接字片段,删除了TCP部分,并添加了ICMP部分以请求回显。我的两台机器都在同一个局域网上,运行32位Ubuntu。 我给了校验和函数我的ICMP指针,但它无法计算正确的校验和: icmph->icmp_sum = csum( (unsigned short *) datagram + sizeof(struct iphdr), sizeof(struct icmp_header)); 然后我尝试了一些原始数字作为偏移量,直到结果出来: icmph->icmp_s

我重用了这个原始套接字片段,删除了TCP部分,并添加了ICMP部分以请求回显。我的两台机器都在同一个局域网上,运行32位Ubuntu。 我给了校验和函数我的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指针与数据报和IP指针的距离为20。为什么10个人会做这项工作

先谢谢你

注:以下是代码:

**/*
    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 - 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**
**/*
原始TCP数据包
银月(m00n。silv3r@gmail.com)
*/
#包括//用于printf
#include//memset
#当然包括//插座
#包括//用于退出(0);
#包含//For errno-错误号
#include//提供tcp头的声明
#include//提供ip头的声明
//ICMP报头
结构icmp_头
{
u_字符icmp_类型;
u_字符icmp_代码;
短icmp和;
u_短icmp_标识;
u__short icmp_seq;
};
/*
通用校验和计算函数
*/
无符号短csum(无符号短*ptr,整数字节)
{
注册长和;
无符号短奇字节;
注册简短回答;
总和=0;
而(n字节>1){
总和+=*ptr++;
nbytes-=2;
}
如果(n字节==1){
oddbyte=0;
*((u_char*)和oddbyte)=*(u_char*)ptr;
sum+=oddbyte;
}
总和=(总和>>16)+(总和&0xffff);
总和=总和+(总和>>16);
答案=(短)~sum;
返回(回答);
}
内部主(空)
{
//创建原始套接字
int s=插座(AF_INET、SOCK_RAW、IPPROTO_RAW);
如果(s==-1)
{
//套接字创建失败,可能是由于非根权限
perror(“未能创建套接字”);
出口(1);
}
//表示数据包的数据报
char数据报[sizeof(struct iphdr)+sizeof(struct icmp_header)],source_ip[32];
//将数据包缓冲区归零
memset(数据报,0,sizeof(结构iphdr)+sizeof(结构icmp_头));
//IP报头
结构iphdr*iph=(结构iphdr*)数据报;
//TCP报头
结构icmp_头*icmph=(结构icmp_头*)(数据报+sizeof(结构iphdr));
sin中的结构sockaddr_;
//一些地址解析
strcpy(来源ip,“10.0.2.5”);
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=inet_addr(“10.0.2.4”);
//填写IP头
iph->ihl=5;
iph->version=4;
iph->tos=0;
iph->tot_len=sizeof(结构iphdr)+sizeof(结构icmp_头);
iph->id=htonl(54321);//此数据包的id
iph->frag_off=0;
iph->ttl=255;
iph->协议=1;//之后使用ICMP
iph->check=0;//在计算校验和之前设置为0
iph->saddr=inet\u addr(source\u ip);//欺骗源ip地址
iph->daddr=sin.sin\u addr.s\u addr;
//Ip校验和
iph->check=csum((无符号短*)数据报,iph->tot_len);
//填写ICMP标题
icmph->icmp_type=8;//Ping请求
icmph->icmp_代码=0;
icmph->icmp_sum=0;//在计算校验和之前设置为0
icmph->icmp_ident=0x4142;//只是一些数字
icmph->icmp_seq=0x4142;//只是一些数字
icmph->icmp_sum=csum((无符号短*)数据报+10,sizeof(结构icmp_头));/?为什么是10而不是sizeof(结构iphdr)=20?
//用于调试
printf(“数据报指针:%p\n”,(void*)数据报);
printf(“IP指针:%p\n”,(void*)iph);
printf(“ICMP指针:%p\n\n”,(void*)icmph);
printf(“IP结构大小:%d\n”,大小为(结构iphdr));
//IP_HDRINCL告诉内核数据包中包含头
int-one=1;
常量int*val=&one;
如果(设置锁定选项(s、IPPROTO_IP、IP_HDRINCL、val、尺寸(一个))<0)
{
perror(“错误设置IP_HDRINCL”);
出口(0);
}
//森登
if(发送到(s,数据报,iph->tot_len,0,(struct sockaddr*)和sin,sizeof(sin))<0)
{
perror(“发送失败”);
}
//数据发送成功
其他的
{
printf(“数据包发送。长度:%d\n”,iph->tot_len);
}
返回0;
}
//完整的**

sizeof
提供以字节为单位的大小,而不是一些任意的“字”。这意味着您在第一个备选方案中添加了一个偏移量
20
16字节的字

您应该将
sizeof
的结果除以
无符号短字符的大小

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

或者,添加
char
大小的单位:
(无符号短*)((char*)数据报+sizeof(struct iphdr))
。谢谢@TobySpeight我喜欢这种方法。