在这个函数中,有两个重点的地方值得注意,一个是hash表的相关变量的初始化、内存空间的分析等等,另一个是协议的注册。
连接跟踪由于针对每种协议的处理,都有些细微不同的地方,举个例子,我们前面讲到数据包至tuple的转换,TCP的转换与ICMP的转换肯定不同的,因为ICMP连端口的概念也没有,所以,对于每种协议的一些特殊处理的函数,需要进行封装,structip_conntrack_protocol结构就实现了这一封装,在初始化工作中,针对最常见的TCP、UDP和ICMP协议,定义了ip_conntrack_protocol_tcp、ip_conntrack_protocol_udp和ip_conntrack_protocol_icmp三个该类型的全局变量,初始化函数中,将它们封装至ip_ct_protos数组,这些,在后面的数据包处理后,就可以根据包中的协议值,使用ip_ct_protos[协议值],找到注册的协议节点,就可以方便地调用协议对应的处理函数了,我们在后面将看到这一调用过程。
3.2 钩子函数的注册
init_or_cleanup函数在创建/proc文件系统完成后,会调用nf_register_hook函数注册钩子,进行连接跟踪,按优先级和Hook不同,注册了多个钩子:
ret = nf_register_hook(&ip_conntrack_defrag_ops);
if (ret < 0) {
printk("ip_conntrack: can't register pre-routing defrag hook.\n");
goto cleanup_proc_stat;
}
ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
if (ret < 0) {
printk("ip_conntrack: can't register local_out defrag hook.\n");
goto cleanup_defragops;
}
……
整个Hook注册好后,如下图所示:
上图中,粗黑体标识函数就是连接跟踪注册的钩子函数,除此之外,用于处理分片包和处理复杂协议的钩子函数在上图中没有标识出来。处理分片包的钩子用于重组分片,用于保证数据在进入连接跟踪模块不会是一个分片数据包。例如,在数据包进入NF_IP_PRE_ROUTINGHook点,主要的连接跟踪函数是ip_conntrack_in,然而,在它之前,还注册了ip_conntrack_defrag,用于处理分片数据包:
static unsigned int ip_conntrack_defrag(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* Gather fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
*pskb = ip_ct_gather_frags(*pskb,
hooknum == NF_IP_PRE_ROUTING ?
IP_DEFRAG_CONNTRACK_IN :
IP_DEFRAG_CONNTRACK_OUT);
if (!*pskb)
return NF_STOLEN;
}
return NF_ACCEPT;
}
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-31885-5.html
甚至对我们示好
我的心碎了太棒了