首页 > 解决方案 > skb_header_pointer 和 skb_transport_header 的区别?

问题描述

我正在尝试实现一个 netfilter 模块,在处理 sk_buff 时我发现了两种可能的方法来检索 TCP 标头:

struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);
struct tcphdr *tcp_header = (struct tcphdr *)skb_transport_header(skb);

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);

我应该使用哪一个?

标签: clinuxtcplinux-kernelnetfilter

解决方案


您应该使用ip_hdr()from /include/linux/ip.htcp_hdr()from /include/linux/tcp.h以防您知道此处无法分页skb

struct iphdr *ip_header = ip_hdr(skb);
if (ip_header->protocol == IPPROTO_TCP) {
    struct tcphdr *tcp_header = tcp_hdr(skb);
    //...

skb_header_pointer()应该在可能出现 paged- 的情况下使用skb。示例:IPTCPICMP等。
因此,如果标头在分页数据中(全部或部分) -skb_header_pointer()将正确处理它。
还要记得检查 的返回值skb_header_pointer()它可以返回 NULL。

有用的链接:1 , 2


推荐阅读