linux内核中的hook函数详解,linux 内核 hook函数介绍

在编写linux内核中的网络模块时,用到了钩子函数也就是hook函数。现在来看看linux是如何实现hook函数的。

typedef unsigned int nf_hookfn(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)); struct nf_hook_ops { struct list_head list; /* User fills in from here down. */ nf_hookfn *hook; struct module *owner; u_int8_t pf; unsigned int hooknum; /* Hooks are ordered in ascending priority. */ int priority; };

其中的成员信息为:

/* Responses from hook functions. */ #define NF_DROP 0 #define NF_ACCEPT 1 #define NF_STOLEN 2 #define NF_QUEUE 3 #define NF_REPEAT 4 #define NF_STOP 5 #define NF_MAX_VERDICT NF_STOP

owner:是模块的所有者,一般owner = THIS_MODULE ;

enum { NFPROTO_UNSPEC = 0, NFPROTO_IPV4 = 2, NFPROTO_ARP = 3, NFPROTO_BRIDGE = 7, NFPROTO_IPV6 = 10, NFPROTO_DECNET = 12, NFPROTO_NUMPROTO, };

hooknum :中存放的是用户自定义的钩子函数的调用时机,其取值为: enum nf_inet_hooks { NF_INET_PRE_ROUTING, NF_INET_LOCAL_IN, NF_INET_FORWARD, NF_INET_LOCAL_OUT, NF_INET_POST_ROUTING, NF_INET_NUMHOOKS };

df4a6ff1c400ab5b10ee89fd9d55ac0d.png

enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, NF_IP_PRI_CONNTRACK_DEFRAG = -400, NF_IP_PRI_RAW = -300, NF_IP_PRI_SELINUX_FIRST = -225, NF_IP_PRI_CONNTRACK = -200, NF_IP_PRI_MANGLE = -150, NF_IP_PRI_NAT_DST = -100, NF_IP_PRI_FILTER = 0, NF_IP_PRI_SECURITY = 50, NF_IP_PRI_NAT_SRC = 100, NF_IP_PRI_SELINUX_LAST = 225, NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, NF_IP_PRI_LAST = INT_MAX, };

所在文件:linux\netfilter_ipv4.h

enum nf_ip6_hook_priorities { NF_IP6_PRI_FIRST = INT_MIN, NF_IP6_PRI_CONNTRACK_DEFRAG = -400, NF_IP6_PRI_RAW = -300, NF_IP6_PRI_SELINUX_FIRST = -225, NF_IP6_PRI_CONNTRACK = -200, NF_IP6_PRI_MANGLE = -150, NF_IP6_PRI_NAT_DST = -100, NF_IP6_PRI_FILTER = 0, NF_IP6_PRI_SECURITY = 50, NF_IP6_PRI_NAT_SRC = 100, NF_IP6_PRI_SELINUX_LAST = 225, NF_IP6_PRI_LAST = INT_MAX, };

以上是对struct nf_hook_ops结构体中的每个字段的详解;

struct nf_hook_ops my_hook = { .hook = myfunction, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NET_INET_FORWARD, .priority = NF_IP4_PRI_FIRST }; unsigned int myfunction( unsigend int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) {}

如上面的代码一样,当定义一个struct nf_hook_ops结构体,并且对其完成了初始化以后,需要将这个结构体进行注册,之后这个结构体以及其中的自定义函数才会其作用。

来看看它是如何实现的: struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly; EXPORT_SYMBOL(nf_hooks); static DEFINE_MUTEX(nf_hook_mutex); 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(&reg->list, elem->list.prev); mutex_unlock(&nf_hook_mutex); return 0; } EXPORT_SYMBOL(nf_register_hook);

所在文件:net\netfilter\core.c

当不再需要使用这个struct nf_hook_ops时,需要注销这个结构体,其可用的函数为: void nf_unregister_hook(struct nf_hook_ops *reg) { mutex_lock(&nf_hook_mutex); list_del_rcu(&reg->list); mutex_unlock(&nf_hook_mutex); synchronize_net(); } EXPORT_SYMBOL(nf_unregister_hook);

int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n) { unsigned int i; int err = 0; for (i = 0; i < n; i++) { err = nf_register_hook(&reg[i]); if (err) goto err; } return err; err: if (i > 0) nf_unregister_hooks(reg, i); return err; } EXPORT_SYMBOL(nf_register_hooks);

同样,当一次需要注销多个struct nf_hook_ops结构体是,使用: void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) { while (n-- > 0) nf_unregister_hook(&reg[n]); } EXPORT_SYMBOL(nf_unregister_hooks);

总结: struct nf_hook_ops int nf_register_hook( struct nf_hook_ops *reg ); void nf_unregister_hook( struct nf_hook_ops *reg ); int nf_register_hooks( struct nf_hook_ops *regs, unsigend int n ); void nf_unregister_hooks( struct nf_hook_ops *regs, unsigned int n );

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值