原始套接字帮助:为什么内核 UDP 不接收原始套接字创建的 UDP 数据包?原始、数据包、内核、不接收

由网友(细数繁华落尽的凄凉)分享简介:我正在研究原始套接字.我使用 IP_HDRINCL 选项来构建我自己的 IP 标头.在 IP 标头之后,我正在构建一个 UDP 标头.然后我将数据包发送到我系统的环回地址.我正在运行另一个程序,它将在 UDP 数据包到来时捕获它们.为了检查数据包是否正确形成和接收,我运行了另一个正在读取原始 IP 数据报的进程.我的问...

我正在研究原始套接字.我使用 IP_HDRINCL 选项来构建我自己的 IP 标头.在 IP 标头之后,我正在构建一个 UDP 标头.然后我将数据包发送到我系统的环回地址.我正在运行另一个程序,它将在 UDP 数据包到来时捕获它们.为了检查数据包是否正确形成和接收,我运行了另一个正在读取原始 IP 数据报的进程.我的问题是,虽然第二个进程(读取原​​始数据报)运行良好(所有 IP 和 UDP 字段似乎都正常),但第一个进程(接收 UDP)没有收到我创建的任何数据包.IP头中的协议字段没问题,端口也匹配...我正在使用 Linux 2.6.35-22.我想知道这在新内核中是否正常?请检查下面的代码是否有任何错误.应该接收数据包的 UDP 进程正在侦听绑定到同一台机器上端口 50000 的套接字...

I am studying raw sockets. I used the IP_HDRINCL option to build my own IP headers. After the IP header, I am building a UDP header. Then I am sending the packet to my system's loopback address. I have another program running which will catch the UDP packets as they come. To check whether the packets are being correctly formed and received, I have another process running which is reading raw IP datagrams. My problem is that although the second process(reading raw datagrams) is working well(all the IP and UDP fields seem to be okay), but the first process(receiving UDP) is not receiving any of the packets that I created. The protocol field in the IP header is okay and the port also matches... I am using Linux 2.6.35-22. I want to know whether this is normal in new kernels? Please check the code below for any bugs. The UDP process which should receive the packets is listening on a socket bound to port 50000 on the same machine...

unsigned short in_cksum(unsigned short *addr, int len)
{
    int nleft = len;
    int sum = 0;
    unsigned short *w = addr;
    unsigned short answer = 0;

    while (nleft > 1) {
        sum += *w++;
        nleft -= 2;
    }

    if (nleft == 1) {
        *(unsigned char *) (&answer) = *(unsigned char *) w;
        sum += answer;
    }

    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    answer = ~sum;
    return (answer);
}


main()
{
    int fd=socket(AF_INET,SOCK_RAW,IPPROTO_UDP);

    int val=1;

    int ret=setsockopt(fd,IPPROTO_IP,IP_HDRINCL,&val,sizeof(val));

    char buf[8192];

    /* create a IP header */

    struct iphdr* ip=(struct iphdr*)buf;//(struct iphdr*) malloc(sizeof(struct iphdr));

    ip->version=4;
    ip->ihl=5;
    ip->tos=0;
    ip->id=0;
    ip->frag_off=0;
    ip->ttl=255;
    ip->protocol=IPPROTO_UDP;
    ip->check=0;
    ip->saddr=inet_addr("1.2.3.4");
    ip->daddr=inet_addr("127.0.0.1");


    struct udphdr* udp=(struct udphdr*)(buf+sizeof(struct iphdr));//(struct udphdr*) malloc(sizeof(struct udphdr));
    udp->source=htons(40000);   
    udp->dest=htons(50000);
    udp->check=0;
    char* data=(char*)buf+sizeof(struct iphdr)+sizeof(struct udphdr);strcpy(data,"Harry Potter and the Philosopher's Stone");
    udp->len=htons(sizeof(struct udphdr)+strlen(data));
    udp->check=in_cksum((unsigned short*) udp,8+strlen(data));

    ip->tot_len=htons(sizeof(struct iphdr)+sizeof(struct udphdr)+strlen(data));

    struct sockaddr_in d;
    bzero(&d,sizeof(d));
    d.sin_family=AF_INET;
    d.sin_port=htons(50000);
    inet_pton(AF_INET,"localhost",&d.sin_addr.s_addr);
    while(1)
     sendto(fd,buf,sizeof(struct iphdr)+sizeof(struct udphdr)+strlen(data),0,(struct sockaddr*) &d,sizeof(d));
}   

推荐答案

UDP校验和的计算好像有问题.

There seems to be a problem with the calculation of the UDP check-sum.

udp->check=in_cksum((unsigned short*) udp,8+strlen(data));

UDP 校验和必须包含一个叫做Pseudo-Header"的东西.在 UDP 标头之前.该代码仅计算 UDP 标头和有效负载的校验和.由于校验和错误,UDP 接收进程可能没有接收到数据包.

UDP check-sum must include something called the "Pseudo-Header" before the UDP header. The code calculates checksum over only the UDP header and the payload. The UDP receiving process might not be receiving the packets because of the wrong check-sums.

在Wireshark中启用校验和验证,检查UDP数据包的校验和字段是否正确.

Enable check-sum validation in Wireshark and check whether the check-sum fields of the UDP packets are correct or not.

请参阅以下内容:

UDP:校验和计算IETF:RFC 768
阅读全文

相关推荐

最新文章