Skip to content
Advertisement

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.

I need to set the IP id to 0. I tried it the following way:

    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:

      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.

However, the network stack keeps changing my id in the IP header. 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?

EDIT: I am on Linux

Advertisement

Answer

On linux, you can use AF_PACKET with SOCK_DGRAM sockets instead of AF_INET with SOCK_RAW and fill an 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.

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).

See more on packet(7) and 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).

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement