在編寫linux核心中的網絡子產品時,用到了鈎子函數也就是hook函數。現在來看看linux是如何實作hook函數的。
先介紹一個結構體:
struct nf_hook_ops,這個結構體是實作鈎子函數必須要用到的結構體,其實際的定義為:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iZjZzYhZ2YjJmY2YWOjRTO4kzYxU2Y3QTZ0ImMlJjM18CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
其中的成員資訊為:
hook :是一個函數指針,可以将自定義的函數指派給它,來實作當有資料包到達是調用你自定義的函數。自定義函數的傳回值為:
owner:是子產品的所有者,一般owner = THIS_MODULE ;
pf :是protocol flags,其取值範圍為:
hooknum :中存放的是使用者自定義的鈎子函數的調用時機,其取值為:
其中的每個值的含義為:
priority : 為所定義的鈎子函數的優先級,其取值為份兩種:分别為IPV4 和 IPV6;
priority 的IPV4取值為:
priority 的IPV6取值為:
以上是對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 nf_hook_ops需要用到的函數為:
int nf_register_hook( struct nf_hook_ops *reg )
其實這個 int nf_register_hook()函數在核心中的實作也沒有多麼的複雜,
來看看它是如何實作的:
當不再需要使用這個struct nf_hook_ops時,需要登出這個結構體,其可用的函數為:
void nf_unregister_hook( struct nf_hook_ops *reg )
當一次需要注冊多個struct nf_hook_ops結構體,如:
struct nf_hook_ops myhooks[n]時,使用:
int nf_register_hooks( struct nf_hook_ops *regs, unsigned int n );
同樣,當一次需要登出多個struct nf_hook_ops結構體是,使用:
void nf_unregister_hoos( struct nf_hook_ops *regs, unsigned int n );
總結:
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 );