Search code examples
clinuxmmappacket

Reading tpacket3_hdr from Packet MMAP and getting payload body


I have a tpacket3_hdr *ppd pointer object. I know how to extract iphdr and tcphdr but what if I need the body part of a packet. I am trying like this

  struct iphdr *ip = (struct iphdr *) ((uint8_t *) eth + ETH_HLEN);
  struct tcphdr *tcp=(struct tcp *)((uint8_t *)ip+sizeof(struct iphdr));
  char *payload_body=(char *)(tcp+sizeof(struct tcphdr));
  printf("%s\n",payload_body);//Printing wrong Not containing what I am checking by simply downloading html

I dont think its the right way of doing this. Full code from Rx Ring from MMAP is given here https://elixir.bootlin.com/linux/latest/source/tools/testing/selftests/net/psock_tpacket.c


Solution

  • [Adapted from Cormen and Stevens, 10.4 TCP Segment Format]

        /* The offset of the payload data (in 32bit words))
        ** is tucked into the upper 4 bits of an unsigned character.
        ** Typically (0x5x & 0xf0) >>2 := 0x20
        */
    
    #define TCP_HLEN(p) (((p)->tcp_offset & 0xf0) >> 2)
    
    char *payload_body=(char *)((uint8_t *)tcp + TCP_HLEN(tcp)) ;
    

    The ip struct has a similar length field in its ip_verlen field(version:=4 bits , lengh_in_words:= 4 bits).

    For IP the corresponding calculation would be:

    #define IPMHLEN 20 /* minimum IP header length (in bytes) */
    #define IP_HLEN(pip) (((pip)->ip_verlen & 0xf) <<2)
    

    So that is the offset (in bytes) where the TCP header would start. The space between offsets IPMHLEN and IPHLEN(pip) (if any) is occupied by IP-options.

    RFCs:

    IP structure

    TCP structure


    This is the layout of a raw segment, as it travels on the net. I am assuming that your file stores this format as-is.

    [I would not use sizeof in any offset/size calculation, since the in-memory structures could contain padding and alignment.]