title: libpcap, payload offset 66 but sizeof(headers) + doff = 62
body: <p>I am spending my sunday on understanding packet sniffing with libpcap and I came so far that I can read packets and metadata. When I was checking my code by sniffing on some packets, I found that I must have an error somewhere.</p>
  
  <p>When I sniff the webpage from my father: <a href="http://www.telpho.de" rel="nofollow">http://www.telpho.de</a> , I get the whole server response back. Starting from 200 OK until ... But on each packet, there are 4 bytes in the beginning which are not ASCII. In the code below, when i change the for loop to (i = 0), the 4 bytes get printed as well. When i leave it at (i = 4), then the payload gets displayed perfectly from the first ASCII character received.</p>
  
  <p>My question now, do I calculate data_offset wrong? Are there any flags which I didnt set? Did i forgot to count the tcp options in ?</p>
  
  <p>I also thought it has maybe to do with padding. The TCP standard says that the TCP header length should be a multiple of 32. But 32 - 20 = 12.. so this are 3 bytes difference.</p>
  
  <p>Could it for example be that the calculation is like this?</p>
  
  <pre><code>TCP_HDR_SIZE = 32
  sizeof(struct tcphdr) = 20
  tcp-&gt;doff = 8    
  
  sizeof(struct tcphdr) + tcp-&gt;doff = 28
  TCP_HDR_SIZE - 28 = 4    &lt;--- the 4 bytes i am looking for??? Maybe options? 
  </code></pre>
  
  <p>Here is the code:</p>
  
  <pre><code>void handle_packet_ip(const struct pcap_pkthdr *header, const u_char* data) {
    struct ip *ip;
    struct tcphdr *tcp;
    int ip_len;
    int data_offset;
    int payload_len;
    int i;
    unsigned char* payload;
  
    ip = (struct ip*)(data + sizeof(struct ether_header));
    ip_len = (ip-&gt;ip_hl &amp; 0x0f) * 4;
  
    tcp = (struct tcphdr*)(data + sizeof(struct ether_header) + ip_len);
    printf("sizeof(ip): %d\n", sizeof(struct ip));
    printf("ip_len: %d\n", ip_len);
    printf("sizeof(ether_header): %d\n", sizeof(struct ether_header));
    printf("sizeof(tcp): %d\n", sizeof(struct tcphdr));
  
    data_offset = sizeof(struct ether_header) + ip_len + sizeof(struct tcphdr) + tcp-&gt;doff;
    payload_len = header-&gt;len - data_offset;
  
    payload = (unsigned char*)(data + data_offset);
  
    printf("IP PACKET\n");
    printf("\tlen: %u\n", ntohs(ip-&gt;ip_len));
    printf("\tsrc: %s\n", inet_ntoa(ip-&gt;ip_src));
    printf("\tdst: %s\n", inet_ntoa(ip-&gt;ip_dst));
    printf("\thl: %d\n", (ip-&gt;ip_hl &amp; 0x0f));
  
    printf("READ TCP\n");
    printf("\tsrc port: %u\n", ntohs(tcp-&gt;source));
    printf("\tdst port: %u\n", ntohs(tcp-&gt;dest));
    printf("\tdata_offset: %d\n", data_offset); 
    printf("\tdoff: %d-%d\n", tcp-&gt;doff, ntohs(tcp-&gt;doff));
    printf("\tpayload len: %d\n", payload_len);
    printf("\tFLAGS\n");
    printf("\t\tFIN: %i\n", tcp-&gt;fin);
    printf("\t\tSYN: %i\n", tcp-&gt;syn);
    printf("\t\tACK: %i\n", tcp-&gt;ack);
    printf("PAYLOAD: \n");
    **for (i = 4; i &lt; payload_len; ++i) {**
      printf("%c", payload[i]);
    }
    printf("\n");
  
    printf("\n");
    printf("END OF PAYLOAD\n");
  }
  </code></pre>
  
  <p>Output:</p>
  
  <pre><code>Grabbed Packet:
  Length: 74
      Capture Length: 74
  sizeof(ip): 20
  ip_len: 20
  sizeof(ether_header): 14
  sizeof(tcp): 20
  IP PACKET
  len: 60
  src: 80.237.132.106
  dst: 192.168.0.17
  hl: 5
  READ TCP
  src port: 80
  dst port: 57662
  data_offset: 62     **this should be 64 ??**
  doff: 8
  payload len: 10
  FLAGS
      FIN: 0
      SYN: 1
      ACK: 1
  </code></pre>