Stefan
Stefan

Reputation: 1307

no member th_seq in struct tcphdr (working with pcap)

I'm working on an assignment of which one part involves capturing packets with pcap. I followed a tutorial, and am now trying some code i found here, which is similiar to this:

//#define __USE_BSD
//#define __FAVOR_BSD
#define MAXBYTES2CAPTURE 2048
#define SIZE_ETHERNET 14
#include <stdio.h>
#include <stdlib.h>
#include <libnet.h>
#include <string.h>
#include <pcap.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>

int main(){
    int count = 0;
    bpf_u_int32 netaddr=0, mask=0;
    pcap_t *descr = NULL;
    struct bpf_program filter;
    struct ip *iphdr = NULL;
    struct tcphdr *tcphdr = NULL;
    struct pcap_pkthdr pkthdr;
    const unsigned char *packet = NULL;
    char pcap_errbuf[PCAP_ERRBUF_SIZE];

    descr = pcap_open_live("eth0", MAXBYTES2CAPTURE, 0, 512, pcap_errbuf );
    pcap_lookupnet("eth0", &netaddr, &mask, pcap_errbuf );
    pcap_compile( descr, &filter, "port 111", 1, mask );
    pcap_setfilter( descr, &filter);

    packet = pcap_next(descr, &pkthdr );
    iphdr = (struct ip *)(packet+14);
    tcphdr = (struct tcphdr *)(packet+14+20);
    printf("SEQ: %d:\n", ntohl(tcphdr->th_seq) );
    pcap_close(descr);
    return(0);
}

The problem is that I get a compile error:

‘struct tcphdr’ has no member named ‘th_seq’.

I found more people asking about this and some replies suggested to include:

#define __USE_BSD
#define __FAVOR_BSD

but I get the error regardless of whether I add that. th_seq is supposed to be included in netinet/tcp.h right? I tested the code on Ubuntu 12.04 and linux 3.2, both give the error.

Anyone knows how to fix this?

Upvotes: 1

Views: 2738

Answers (2)

Richard Wicks
Richard Wicks

Reputation: 11

This is an ancient question, but I can answer it, within your OWN code, use tcphdr->th_off if __FAVOR_BSD is defined (don't define it yourself) or use tcphdr->doff if it's not. Like so:

#if (defined (__FAVOR_BSD))
  len -= sizeof (uint32_t) * tcp->th_off;
  packet += sizeof (uint32_t) * tcp->th_off;
#else
  len -= sizeof (uint32_t) * tcp->doff;
  packet += sizeof (uint32_t) * tcp->doff;
#endif

You might be running into licensing issues if you do this, but for the stuff I'm doing, I don't care - this is internal code, not part of a product, and if we ever had to GPL it, we'd be happy to do it.

Both versions of tcphdr works just fine, they're just named differently, for some reason. You can also just make macros if you're doing this an awful lot. I'm just skipping over headers until I get to the data within a packet for inspection.

Upvotes: 1

user862787
user862787

Reputation:

Anyone knows how to fix this?

Well, tcpdump solves this by not depending on the OS's headers to define packet layouts; it has its own headers, or defines the layouts in the source file.

You might want to do the same thing, copying headers from an OS with the appropriate license (tcpdump is BSD-licensed and got its headers from a BSD; if you want your program to be GPL-licensed, you might want to see what headers Linux has), and editing them as necessary, or writing your own structure definitions.

Upvotes: 0

Related Questions