下面是一个钩子函数的示例。它仅打印出数据包的信息。当 Netfilter 调用钩子函数时,它会将三个参数传递给该函数,其中包括一个指向实际数据包的指针(skb)。在下面的代码中,第 🄰 行展示了如何从 state 参数中检索钩子编号。第 🄱 行使用 ip_hdr() 数获取 IP 头的指针,第 🄲 行通过 %pI4 格式打印出源和目标 IP 地址。

// 钩子函数示例
unsigned int printInfo(void *priv, struct sk_buff *skb,  
                       const struct nf_hook_state *state)
{
   struct iphdr *iph;
   char *hook;

   switch (state->hook){          🄰
     case NF_INET_LOCAL_IN:
          printk("*** LOCAL_IN"); break;
     .. (代码省略) ...
   }

   iph = ip_hdr(skb);             🄱          
   printk("    %pI4  --> %pI4\n", &(iph->saddr), &(iph->daddr)); 🄲
   return NF_ACCEPT;
}

如果需要获取其他协议的头部信息,可以使用以下定义在头文件中的函数。这些头部的结构定义可以在 /lib/modules/5.4.0-54-generic/build/include/uapi/linux 文件夹中找到,其中路径中的版本号由命令 "uname -r" 的结果决定,因此如果内核版本不同,路径也可能不同。

struct iphdr   *iph   = ip_hdr(skb)    // 需要包含 <linux/ip.h>
struct tcphdr  *tcph  = tcp_hdr(skb)   // 需要包含 <linux/tcp.h>
struct udphdr  *udph  = udp_hdr(skb)   // 需要包含 <linux/udp.h>
struct icmphdr *icmph = icmp_hdr(skb)  // 需要包含 <linux/icmp.h>
最后修改: 2025年05月9日 星期五 22:59