I'm trying to implement a netfilter module, while processing sk_buff I found two possible ways to retrieve TCP header:
struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);
struct tcphdr *tcp_header = (struct tcphdr *)skb_transport_header(skb);
And
struct iphdr *ip_header = skb_header_pointer(skb, 0, sizeof(struct iphdr), &_iph)
struct tcphdr *tcp_header = skb_header_pointer(skb, ip_header->ihl * 4, sizeof(struct tcphdr), &_tcph);
Which one should I use?
You should use ip_hdr()
from /include/linux/ip.h and tcp_hdr()
from /include/linux/tcp.h in case you know that there cannot be paged-skb
here:
struct iphdr *ip_header = ip_hdr(skb);
if (ip_header->protocol == IPPROTO_TCP) {
struct tcphdr *tcp_header = tcp_hdr(skb);
//...
skb_header_pointer()
should be used in case the appearance of paged-skb
is possible. Examples: IP, TCP, ICMP, etc.
So if the header is in paged data (fully or partially) - skb_header_pointer()
will correctly handle it.
Also remember to check the return value of skb_header_pointer()
, it can return NULL.