0

I'm using pcap to capture packets and now want to calculate IP checksum manually.

struct sniff_ip {
    u_char  ip_vhl;                 /* version << 4 | header length >> 2 */
    u_char  ip_tos;                 /* type of service */
    u_short ip_len;                 /* total length */
    u_short ip_id;                  /* identification */
    u_short ip_off;                 /* fragment offset field */
    #define IP_RF 0x8000            /* reserved fragment flag */
    #define IP_DF 0x4000            /* dont fragment flag */
    #define IP_MF 0x2000            /* more fragments flag */
    #define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */
    u_char  ip_ttl;                 /* time to live */
    u_char  ip_p;                   /* protocol */
    u_short ip_sum;                 /* checksum */
    struct  in_addr ip_src,ip_dst;  /* source and dest address */
};



 struct sniff_ip_16bit {
    u_short a;
    u_short b;
    u_short c;
    u_short d;
    u_short e;
    u_short f;
    u_short g;
    u_short h;
    u_short i;
    u_short j;

};

I have to divide the IP header into 16 bits, ones complement sum them, and ones complement the result.

I did following to cast them into 16bit fragments, and finally just sum all those elements.

   ip->ip_sum = 0;
    sniff_ip_16bit* ip_crc = reinterpret_cast<sniff_ip_16bit*>(&ip);
    u_short ip_crc_calculated = ip_crc->a+ip_crc->b+ip_crc->c+ip_crc->d+ip_crc->e+ip_crc->f+ip_crc->g+ip_crc->h+ip_crc->i+ip_crc->j;
    std::cout << "MNL CRC:" << std::bitset<16>(~ip_crc_calculated) << std::endl;

But yet I get wrong CRC results, the last two lines.

    Packet number 4:
IP Header length : 20
       From: 127.0.0.1
         To: 127.0.0.1
   Protocol: TCP
Len : 66 CLen: 66
Seq: 3415166211
Ack: 458071927
   Src port: 45878
   Dst port: 8080
Payload empty
CRC TCP: 0010100011111110
IP ID: 55139
CRC IP: 1110101011011000 //original
MNL CRC:0100011001111000
katoge
  • 33
  • 4
  • IIRC, the addition is also one's complement addition. – user253751 Mar 04 '20 at 12:30
  • And, you are adding the u_char fields together instead of treating them as 16 bits. – user253751 Mar 04 '20 at 12:32
  • I have tested it on a seperat programm, I can add u_char and u_short together and they will output correct result outputting 16 bits with bitset<16>. But I think that might be the problem, I treat them as normal addition, not ones complement addition. – katoge Mar 04 '20 at 12:43
  • You are supposed to divide the IP header into 16 bits. Dividing it into ip_vhl and ip_tos is dividing it into 8 bits. Not 16 like it should be. – user253751 Mar 04 '20 at 12:53
  • Oh, I finanlly understand. Do you think I should create a struct with 16 bit members, and cast the ip-struct to that 16 bit struct? Im still wondering how I can solve the onescomplement addition, maybe I have to create a function for this. – katoge Mar 04 '20 at 13:06
  • I think 1's-complement addition is just normal addition but with `% 0xFFFF` at the end. – user253751 Mar 04 '20 at 13:07

0 Answers0