net/core/dev.c,Line1035),这个函数被高 层协议的实例使用,以数据结构 struct sk_buff *skb 的形式在
网络设备上发送数 据报。
2. HOOK 的调用
HOOK 的调用是通过宏 NF_HOOK 实现的,其定义位于 include/
linux/Netfilter.h,Line122: #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) / (list_empty(&;nf_hooks[(pf)][(hook)]) / ? (okfn)(skb) / : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn))) 这里先调用 list_empty 函数检查 HOOK 点存储数组 nf_hooks 是否为空,为 空则表示没有 HOOK 注册,则直接调用 okfn 继续处理。如果不为空,则转入 nf_hook_slow()函数。 nf_hook_slow()函数(位于 net/core/netfilter.c,Line449)的
工作主要是读 nf_hook 数组遍历所有的 nf_hook_ops 结构, 并调用 nf_hookfn()处理各个数据报。 即 HOOK 的调用过程如图 blog.chinaunix.net/photo/24896_061206192356.jpg 所示 下面说明一下 NF_HOOK 的各个参数:
?
pf:协议
族标识,相关的有效协议族
列表位于 include/linux/socket.h,Line 178。对于 IPv4,应该使用协议族 PF_I
NET;
? ?
hook:HOOK 标识,即前面所说 5 个 HOOK 对应的 hooknum; skb:是含有需要被处理包的 sk_buuff 数据结构的指针。sk_buff 是 Linux 网络缓存,指那些 linux 内核处理 IP 分组报文的缓存,即套接字缓冲区。
网卡收到 IP 分组报文后,将它们放入 sk_buff,然后再传送给网络堆栈,网络堆 栈几乎一直要用到 sk_buff。其定义在 include/linux/skbuff.h,Line 129,下面列出 我认为对分析有意义的部分成员:
? o o o
o o
`struct sock *sk;`:指向创建分组报文的 socket; `struct timeval stamp;`:分组报文到达
系统的时间; 下面是三个 union,存放的是各层中各种协议的报文头指针: h 对应传输层的报头 nh 对应网络层的报头 mac 对应 MAC 层的报头 `unsigned int len;`:套接字缓存所代表的报文长度,即从`unsigned char *data;`的位置算起的当前有效报文长度。 `unsigned char pkt_type,`:表示报文的类型,具体类型定义在 include/linux/if_packet.h,Line24:
#define PACKET_HOST 0 // 发送到本机的报文 #define PACKET_BROADCAST 1 // 广播报文 #define PACKET_MULTICAST 2 // 多播报文 #define PACKET_OTHERHOST 3 // 表示目的地非本机但被本机 接收的报文 #define PACKET_OUTGOING 4 // 离开本机的报文 /* These ones are invisible by user level */ #define PACKET_LOOPBACK 5 // 本机发给自己的报文 #define PACKET_FASTROUTE 6 // 快速路由报文
?
?
indev:输入设备,收到数据报的网络设备的 net_device 数据结构指针,即 数据报到达的接口。 o 用于 NF_IP_PRE_ROUTING 和 NF_IP_LOCAL_IN 两个 HOOK outdev:输出设备,数据报离开本地所要使用的网络设备的 net_device 数 据结构指针。 o 用于 NF_IP_LOCAL_OUT 和 NF_IP_POST_ROUTING 两个 HOOK o 注意:在通常情况下,在一次 HOOK 调用中,indev 和 outdev 中只 有一个参数会被使用
?
okfn: 下一步要处