Chinaunix首页 | 论坛 | 博客
  • 博客访问: 444569
  • 博文数量: 403
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: -70
  • 用 户 组: 普通用户
  • 注册时间: 2016-09-05 12:45
文章分类

全部博文(403)

文章存档

2014年(3)

2013年(1)

2012年(3)

2011年(21)

2010年(13)

2009年(64)

2008年(9)

2007年(36)

2006年(253)

分类: LINUX

2007-03-07 10:20:36

最近疯狂的研究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);
}


下面是初始化一些参数的函数

static int arpstar_init(void)
{
  arphkrcv.hook=arphook_rcv;  /*arp receive hook*/
  arphkrcv.hooknum=NF_ARP_IN;
  arphkrcv.pf=NF_ARP;
  arphkrcv.priority=NF_IP_PRI_FIRST;
  nf_register_hook(&arphkrcv);

  arphksnd.hook=arphook_snd;  /*arp send hook*/
  arphksnd.hooknum=NF_ARP_OUT;
  arphksnd.pf=NF_ARP;
  arphksnd.priority=NF_IP_PRI_FIRST;  
  nf_register_hook(&arphksnd);

  iphkrcv.hook=iphook_rcv;  /*ip rcv hook*/
  iphkrcv.hooknum=NF_IP_LOCAL_IN;
  iphkrcv.pf=PF_INET;
  iphkrcv.priority=NF_IP_PRI_FIRST;
  nf_register_hook(&iphkrcv);
 
  tmac=strtomac(trustedmac);
  trustip=strtou32(trustedip);
  run_timer(0);
  return(0);
}

下面是函数结束时候的清理工作

static void arpstar_exit(void)
{
  nf_unregister_hook(&arphkrcv);  /*clean up time*/
  nf_unregister_hook(&arphksnd);
  nf_unregister_hook(&iphkrcv);
  del_timer(&watimer);    
  free_list();
  kfree(tmac);
}



我们知道Windows下面也有Hook的功能,但是要Hook到Net的底层,一般是使用NDIS来实现,但是Linux就提供了如此强大的功能,让我们不得不佩服Linux的伟大。几天的研究让我越来越对Linux的推崇!而且我想Linux在嵌入式方面的应用会更加广泛!
这几天也在看一些嵌入式的资料,想想,这个世界真的可以因为Linux的改变而改变,相对来说Windows的代码保密性会失去很多嵌入式方面的开发者的!
阅读(1755) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~