Extracting the tcp header from a IPv4/IPv6 packet

Eddie Kohler kohler at icir.org
Tue Oct 15 09:59:47 EDT 2002


Hi Juan Luis,

> With a IPv4 packet a get a seg fault when trying to   
> print/use tcph->th_off. This is the code I use, wich was   
> taken from FtpPortMapper:   
>    
> const click_ip *iph = p->ip_header();   
> const click_tcp *tcph = p->tcp_header();   
> unsigned data_offset = p->transport_header_offset() +   
> (tcph->th_off<<2);   
> const unsigned char *data = p->data() + data_offset;   
> unsigned len = p->length() - data_offset;   

That looks like the correct code, but it will only work if the packet has
gone through a CheckIPHeader or MarkIPHeader element previously. (It
depends on the "IP header annotation".)

> With a IPv6 packet (wich has PASV/PORT commands that needs   
> to be translated to EPSV/EPRT):   
>    
> click_ip6 *ip6 = (click_ip6 *)p->data();   
> const click_tcp *tcph = (click_tcp *)ip6 + 1;   
> const unsigned char *data = (unsigned char *)tcph + 1;   
> unsigned data_offset = (unsigned)data + (tcph->th_off<<2);   
> unsigned len = p->length() - strlen((char *)data);   
>    
> Starting a telnet session, if I print tcph->th_off, it has a   
> value of 0, but in both protocolTranslator's I can see that   
> the value is 40.   

Don't know much about IP6, but I believe there might be other headers
between the IP header and the TCP header. And have you stripped off any
Ethernet header?

Even aside from that, your code is pretty suspect. Don't use strlen(), for
example; the packet data is not a null-terminated string. And you've got
the precedence of casts wrong. To get the TCP header, you want 
(click_tcp *)(ip6 + 1)  not  ((click_tcp *)ip6) + 1  (which is what you
have now). Try something like:

> click_ip6 *ip6 = (click_ip6 *)p->data();   
> click_tcp *tcph = (click_tcp *)(ip6 + 1);
> unsigned char *data = (unsigned char *)tcph + (tcph->th_off << 2);
> unsigned len = (p->data() + p->length()) - data;

E




More information about the click mailing list