作者:gfree.wind@gmail.com
博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net
博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
======================================================================================================
向netfilter添加新的hook有两个函数,nf_register_hook和nf_register_hooks。其中后者是通过调用前者实现的。
下面看nf_register_hook
- int nf_register_hook(struct nf_hook_ops *reg)
-
{
-
struct nf_hook_ops *elem;
-
int err;
-
-
err = mutex_lock_interruptible(&nf_hook_mutex);
-
if (err < 0)
-
return err;
-
list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
-
if (reg->priority < elem->priority)
-
break;
-
}
-
list_add_rcu(®->list, elem->list.prev);
-
mutex_unlock(&nf_hook_mutex);
-
return 0;
-
}
-
-
int nf_register_hook(struct nf_hook_ops *reg)
-
{
-
struct nf_hook_ops *elem;
-
int err;
-
-
err = mutex_lock_interruptible(&nf_hook_mutex);
-
if (err < 0)
-
return err;
/*
通过reg->pf即协议,和reg->hooknum即挂载点,来确定二维数组nf_hooks的节点。
每个节点为某一协议的某一挂载点的netfiler匹配规则的链表。
*/
-
list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
- /* 匹配规则按优先级排序,数值越小,优先级越高 */
-
if (reg->priority < elem->priority)
-
break;
-
}
- /* 将新的规则hook加入到list中 */
-
list_add_rcu(®->list, elem->list.prev);
-
mutex_unlock(&nf_hook_mutex);
-
return 0;
- }
这个注册函数很简单,找个例子看看,文件net/ipv4/netfilter/nf_defrag_ipv4.c中:
- /* 定义两个hook结构实例 */
- static struct nf_hook_ops ipv4_defrag_ops[] = {
-
{
-
.hook = ipv4_conntrack_defrag,
-
.owner = THIS_MODULE,
-
.pf = PF_INET,
-
.hooknum = NF_INET_PRE_ROUTING,
-
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-
},
-
{
-
.hook = ipv4_conntrack_defrag,
-
.owner = THIS_MODULE,
-
.pf = PF_INET,
-
.hooknum = NF_INET_LOCAL_OUT,
-
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
-
},
-
};
-
-
static int __init nf_defrag_init(void)
-
{
- /* 通过该函数,加入两个新的hook,在PF_INET下的pre_routing和local out两个挂载点 */
-
return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
- }
下面看一下ipv4_defrag_ops作为一个hook函数的例子。
- static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
-
struct sk_buff *skb,
-
const struct net_device *in,
-
const struct net_device *out,
-
int (*okfn)(struct sk_buff *))
-
{
-
struct sock *sk = skb->sk;
-
struct inet_sock *inet = inet_sk(skb->sk);
-
- /* 对应的socket为PF_INET,且指定该socket为nodefrag,则hook返回NF_ACCEPT */
-
if (sk && (sk->sk_family == PF_INET) &&
-
inet->nodefrag)
-
return NF_ACCEPT;
-
-
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-
#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)
-
/* Previously seen (loopback)? Ignore. Do this before
-
fragment check. */
-
if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
-
return NF_ACCEPT;
-
#endif
-
#endif
-
/* Gather fragments. */
- /*
- 当IP报文中的标志中的IP_MF或者IP_OFFSET被置位,则表示该IP报文为分片。
- 第一个分片,IP_MF为1,IP_OFFSET为0;
- 中间的分片,IP_MF和IP_OFFSET均不为0;
- 最后一个分片,IP_MF为0,IP_OFFSET不为0;
- */
-
if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
-
enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb);
-
if (nf_ct_ipv4_gather_frags(skb, user))
-
return NF_STOLEN; //哦~~,这里出现了NF_STOLEN,不过今天没时间了
-
}
-
return NF_ACCEPT;
- }
今天看到的netfilter的代码都比较简单——其实netfilter的代码都比较简单。争取再有一两篇博文,基本上netfilter就可以结束了。