Getting TCP options (beyond tcphdr->doff) out of * char eth/ip/tcp packer representation

StackOverflow https://stackoverflow.com/questions/4221448

  •  26-09-2019
  •  | 
  •  

Question

Playing around with http://www.tcpdump.org/sniffex.c to get packet options.

void payload (char *data) { // data contains full copied packet source without ethernet header.
 char *ptr = NULL;
 //ptr = data;
 //struct ip *pip = (struct ip *) ptr;

 ptr = data + sizeof(struct ip);
 struct tcphdr *thdr = (struct tcphdr *) ptr;

 ptr = data + sizeof(struct ip) + (thdr->doff*4);
 char *txt = (char *) ptr;
 // *txt can be fprint/cout'ed, returned OK.
}
  1. data + struct ip points to TCP header in (pointer) (unsigned char) memory
  2. data + struct ip + thdr->doff*4 points to end of TCP options = beginning of the data

Given the following structure,

typedef u_int tcp_seq;

struct sniff_tcp {
        u_short th_sport;               /* source port */
        u_short th_dport;               /* destination port */
        tcp_seq th_seq;                 /* sequence number */
        tcp_seq th_ack;                 /* acknowledgement number */
        u_char  th_offx2;               /* data offset, rsvd */
#define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
        u_char  th_flags;
        #define TH_FIN  0x01
        #define TH_SYN  0x02
        #define TH_RST  0x04
        #define TH_PUSH 0x08
        #define TH_ACK  0x10
        #define TH_URG  0x20
        #define TH_ECE  0x40
        #define TH_CWR  0x80
        #define TH_FLAGS        (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
        u_short th_win;                 /* window */
        u_short th_sum;                 /* checksum */
        u_short th_urp;                 /* urgent pointer */
};

Also there is a reference in TCPDump code:

 tp = (struct tcphdr *)bp; // packet header.
  hlen = TH_OFF(tp) * 4;    // data length?

  if (hlen > sizeof(*tp)) {
                 register const u_char *cp;
                 register u_int i, opt, datalen;
                 register u_int len;
                 hlen -= sizeof(*tp);

So, to read a part of packet, where options lie, it is needed to:

  1. Assume that length specified in packet is > than a structure length
  2. Read N bytes after (ethernet + ip + tcphdr) structure's length?
  3. Drop those bytes off, now read payload.

Correct? It simply boils me off to read a random payload's byte sequence instead of actual data.

Was it helpful?

Solution

The options lie between data + sizeof(struct ip) + sizeof(struct tcphdr) and txt. There may be no options, in which case these pointers will be equal.

OTHER TIPS

The comment "// data length?" is incorrect and should be "// TCP header length in bytes". The if (hlen > sizeof(*tp)) stmt checks if there are any options and also handles the case where random bits are misinterpreted as a TCP header, since that can produce a TH_OFF()*4 less than the min size of the header. After subtracting sizeof(*tp) from hlen, it now contains the size of the TCP options in bytes. The code can then proceed to walk the options. At no point does it read "a random payload's byte sequence instead of actual data", or at least not given what I think you mean...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top