最近疯狂的研究Linux的种种功能,也颇有心得,这里讲述一下Linux下的Net的Hook,使用net的Hook可以实现很多很多非常底层的功能,比如过滤报文,做防火墙,做代理等等。
Now,Let's Go!
使用的是Linux 2.6.19.1的内核代码。
首先是 在./Source/net/netfilter/core.c文件中的函数 nf_register_hook:
static DEFINE_SPINLOCK(nf_hook_lock);
int nf_register_hook(struct nf_hook_ops *reg)
{
struct list_head *i;
spin_lock_bh(&nf_hook_lock);
list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {
if (reg->priority < ((struct nf_hook_ops *)i)->priority)
break;
}
list_add_rcu(®->list, i->prev);
spin_unlock_bh(&nf_hook_lock);
synchronize_net();
return 0;
}
EXPORT_SYMBOL(nf_register_hook);
void nf_unregister_hook(struct nf_hook_ops *reg)
{
spin_lock_bh(&nf_hook_lock);
list_del_rcu(®->list);
spin_unlock_bh(&nf_hook_lock);
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(®[i]);
if (err)
goto err;
}
return err;
err:
if (i > 0)
nf_unregister_hooks(reg, i);
return err;
}
EXPORT_SYMBOL(nf_register_hooks);
void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
{
unsigned int i;
for (i = 0; i < n; i++)
nf_unregister_hook(®[i]);
}
EXPORT_SYMBOL(nf_unregister_hooks);
上面分别是四个函数:
nf_register_hook,nf_unregister_hook,nf_register_hooks,nf_unregister_hooks.
功能是注册Hooks函数
输入的参数是struct nf_hook_ops *reg。
下面让我们看一个验证ARP报文的Hook代码,以表示我们如何使用Hook函数实现这种功能。
unsigned int arphook_snd(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in, const struct net_device *out,int (*okfn)(struct sk_buff*))
{
struct arphdr *arp;
struct net_device *dev;
unsigned char * arp_ptr;
unsigned char *sha, *tha;
u32 sip,tip;
unsigned short arpop;
unsigned int status=NF_DROP;
dev=(*skb)->dev;
arp = (*skb)->nh.arph;
arp_ptr= (unsigned char *)(arp+1);
sha = arp_ptr;
arp_ptr += dev->addr_len;
memcpy(&sip, arp_ptr, 4);
arp_ptr += 4;
tha = arp_ptr;
arp_ptr += dev->addr_len;
memcpy(&tip, arp_ptr, 4);
arpop=ntohs(arp->ar_op);
if(!check_ip(&tip,WABLOCK)) /*check block list*/
{
if(arpop==1) /*sending ARP request*/
{
if(!check_ip(&tip,WAARP)) /*if not in list add it*/
add_ip(&tip,WAARP);
}
status=NF_ACCEPT;
}
return(status);
}
