简体   繁体   English

C套接字编程:将ip header的id设置为0?

[英]C socket programming: Set ip header's id to 0?

I want to send raw IP packets, which works perfectly fine, except for one field in the IP header. 我想发送原始IP数据包,除了IP头中的一个字段外,它工作得很好。

I need to set the IP id to 0. I tried it the following way: 我需要将IP ID设置为0.我尝试了以下方式:

    struct iphdr ip;

ip.version = 4;                               // Ipv4
ip.frag_off = 0;                              // IP Fragmentation
ip.tos     = 0;                               // Type of Service - We don't need this
ip.ttl = 64;                                  // Maxmimum value
ip.protocol = IPPROTO_UDP;                    // DHCP uses UDP
ip.check = 0;                                 // The checksum needs to be 0 before being calculated

// We don't yet have an IP Address
if((ip.saddr = inet_addr("0.0.0.0")) == -1) {
    perror("Failed to convert IP address");
    exit(1);
}

ip.daddr = inet_addr("255.255.255.255");      // we have to do a broadcast
ip.id = 0;                                    //  
ip.ihl = 5;                                   // Header length - 5 means no additional options are being sent in the IP header
ip.tot_len = sizeof(struct packet);           // The total length of the Packet

I then create a RAW_SOCKET with the IP_HDRINCL option set: 然后我创建一个RAW_SOCKET并设置IP_HDRINCL选项:

      if ((sockd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) {
      perror("Failed to create socket");
      exit(1);
  }
int hdrincl = 1;
if (setsockopt(sockd, IPPROTO_IP, IP_HDRINCL, &hdrincl, sizeof(hdrincl)) == -1) {
    perror("Failed to set IP_HDRINCL");
    exit(1);
}

I then create a buffer, containing my IP header, UDP header and the payload and send it out. 然后我创建一个缓冲区,包含我的IP头,UDP头和有效负载并发送出去。

However, the network stack keeps changing my id in the IP header. 但是,网络堆栈会不断更改IP标头中的ID。 I need to include the IP header, but I also need to disable fragmentation and / or set the IP id to 0. How do I achieve this? 我需要包含IP头,但我还需要禁用碎片和/或将IP ID设置为0.我该如何实现?

EDIT: I am on Linux 编辑:我在Linux上

On linux, you can use AF_PACKET with SOCK_DGRAM sockets instead of AF_INET with SOCK_RAW and fill an sockaddr_ll . 在linux上,你可以使用带有SOCK_DGRAM套接字的AF_PACKET代替带有SOCK_RAWAF_INET并填充sockaddr_ll

Something like that: 像这样的东西:

socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))

However, to make you program work with Windows too, you should use libpcap . 但是,为了使您的程序也适用于Windows,您应该使用libpcap

Keep in mind that you should resolve the destination's physical address by yourself (On linux, you can try using the rtnetlink interface for that). 请记住,您应该自己解决目标的物理地址(在Linux上,您可以尝试使用rtnetlink接口)。

See more on packet(7) and rtnetlink(7) . 有关packet(7)rtnetlink(7)更多信息,请参阅。 If your project is Open Source, you can use my old project that doing some of these things (for more information, contact me). 如果您的项目是开源项目,您可以使用我的旧项目执行某些操作(有关更多信息,请与我联系)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM