Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.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
C 未接收到从tap接口发送的广播数据包_C_Linux_Sockets_Tun - Fatal编程技术网

C 未接收到从tap接口发送的广播数据包

C 未接收到从tap接口发送的广播数据包,c,linux,sockets,tun,C,Linux,Sockets,Tun,我正在制作一个类似simpletun的程序 应用程序向tap接口发送UDP广播 在tap接口上收听的节目(类似于simpletun)接收数据包,并将其作为广播再次回音 我可以在wireshark上看到这两个数据包,但应用程序没有收到它。看起来内核正在删除它们 如果从不同的机器发送相似的数据包。它很好用 tun/tap代码:- char datagram[4096]; struct pseudo_header { u_int32_t source_address;

我正在制作一个类似simpletun的程序

  • 应用程序向tap接口发送UDP广播

  • 在tap接口上收听的节目(类似于simpletun)接收数据包,并将其作为广播再次回音

  • 我可以在wireshark上看到这两个数据包,但应用程序没有收到它。看起来内核正在删除它们

  • 如果从不同的机器发送相似的数据包。它很好用

  • tun/tap代码:-

    char datagram[4096];
    struct pseudo_header
    {
            u_int32_t source_address;
            u_int32_t dest_address;
            u_int8_t placeholder;
            u_int8_t protocol;
            u_int16_t udp_length;
    };
    struct pseudo_header psh;
    char *pseudogram;
    
     nread = cread(tap_fd, buffer, BUFSIZE);
    
        memcpy(&source_port,(char *)(buffer+14+20),2);  
    
        memset (datagram, 0, 4096);
    
        memcpy(datagram,buffer,14); //copy eth-header
        datagram[6] = 0xXX;//change mac address
        datagram[7] = 0xXX;
        datagram[8] = 0xXX;
        //IP header
        struct iphdr *iph = (struct iphdr *) (datagram +14);
        //TCP header
        struct udphdr *udph = (struct udphdr *) (datagram + 14 + sizeof (struct iphdr));
    
        data = datagram + sizeof(struct iphdr) + sizeof(struct udphdr) +14;     
        strcpy(data,"Any string");
        iph->ihl = 5;
        iph->version = 4;
        iph->tos = 0;
        iph->tot_len = sizeof (struct iphdr) + sizeof (struct udphdr) + strlen(data);
        iph->id = htonl (54321);        //Id of this packet
        iph->frag_off = 0;
        iph->ttl = 255;
    
        iph->protocol = IPPROTO_UDP;
        iph->check = 0;         //Set to 0 before calculating checksum
    
        strcpy(source_ip , "192.168.0.99");
        iph->saddr = inet_addr ( source_ip );   //Spoof the source ip address
        strcpy(destination_ip , "255.255.255.255");
        iph->daddr = inet_addr (destination_ip);
    
    
         udph->source = htons(5933);
        //udph->dest = htons(source_port);
        udph->dest = (source_port);
        udph->len = htons(sizeof(struct udphdr) + strlen(data));
    
    
        //Now the UDP checksum
        psh.source_address = inet_addr( source_ip );
        psh.dest_address = inet_addr(destination_ip);
        psh.placeholder = 0;
        psh.protocol = IPPROTO_UDP;
        psh.udp_length = htons(sizeof(struct udphdr) + strlen(data) );
    
        int psize = sizeof(struct pseudo_header) + sizeof(struct udphdr) + strlen(data);
        pseudogram = malloc(psize);
    
        memcpy(pseudogram , (char*) &psh , sizeof (struct pseudo_header));
        memcpy(pseudogram + sizeof(struct pseudo_header) , udph , sizeof(struct udphdr) + strlen(data));
        memcpy(pseudogram + sizeof(struct pseudo_header) + sizeof(struct udphdr), data , strlen(data));
    
        udph->check = 0;
        udph->check = csum( (unsigned short*) pseudogram , psize);
        //Ip checksum
        iph->check = csum ((unsigned short *) datagram, iph->tot_len);
    
        //writeback
        cwrite(tap_fd,datagram,iph->tot_len +14);
    
    当使用原始套接字读写从另一台机器运行时,上述代码运行良好。(不带eth标题)

    接收申请代码:-

    int broadcast =1;
    
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
          err("socket");
    
    setsockopt(sockfd,SOL_SOCKET,SO_BINDTODEVICE,"tun0",5);
    
    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(PORT);
    memset(&my_addr.sin_addr.s_addr,255,sizeof(my_addr.sin_addr.s_addr));
    
    ret = setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&broadcast,sizeof(broadcast));
        if(ret<0)
          printf("setsockopt bindto failed");
    
        if (sendto(sockfd,buf,500,0, (struct sockaddr*)&my_addr,slen_len) == -1)
            err("send()");
    
        recvfrom(sockfd, buf, 500, 0, (struct sockaddr*)&cli_addr, &slen);
    
    int广播=1;
    if((sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))=-1)
    错误(“套接字”);
    setsockopt(sockfd,SOL_SOCKET,SO_BINDTODEVICE,“tun0”,5);
    bzero(&my_addr,sizeof(my_addr));
    我的地址sin家庭=AFINET;
    my_addr.sin_port=htons(端口);
    memset(&my_addr.sin_addr.s_addr,255,sizeof(my_addr.sin_addr.s_addr));
    ret=setsockopt(sockfd、SOL_SOCKET、SO_BROADCAST和BROADCAST、sizeof(BROADCAST));
    
    如果(ret您是否检查了主机防火墙规则?

    在黑暗中拍摄猜测:


    但是,当它将IP目的地视为广播IP(255.255.255.255)时,您可以尝试更改TUN/TAP代码,将目的地MAC地址设置为广播(FF:FF:FF:FF:FF:FF)地址。

    通过对IP头的tot\U len使用正确的校验和字节顺序来解决此问题

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

    iph->id=htons(54321);//此数据包的id

    iph->check=htons(csum((无符号短*)数据报,sizeof(struct ip_hdr));
    **其中,csum是计算校验和的常用函数

    由于内核的网络堆栈正在重新计算iph->tot_len和ip校验和,所以从另一台机器接收到了数据包,因此数据包的格式正确


    在更正应用程序收到tot_len数据包的校验和和字节顺序后,使用my tun接口。

    防火墙被禁用
    服务ufw stop
    ,则可能您没有在特定计算机上使用原始套接字的良好权限。例如,Windows不允许您创建完整的原始套接字。您可以在其中调用setsockopt带SO_广播-广播的类型和初始化值是什么变量?广播设置为1。仅添加了代码的相关部分。
    int broadcast=1;
    这应该是正确的。这只是一种预感。嘿,感谢支持我并促使我更正进出tun/tap接口的两个数据包中的dest mac和dest ip。我在这一行中所做的更改
    数据报[6]=0xXX;//更改mac地址
    仅是回显数据包时的源mac