原始套接字帮助:为什么内核 UDP 不接收原始套接字创建的 UDP 数据包? [英] Raw Socket Help: Why UDP packets created by raw sockets are not being received by kernel UDP?

查看:32
本文介绍了原始套接字帮助:为什么内核 UDP 不接收原始套接字创建的 UDP 数据包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究原始套接字.我使用 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 不接收原始套接字创建的 UDP 数据包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆