Netfilter框架分析

nf_register_hook() -->
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(&reg->list, i->prev);
 spin_unlock_bh(&nf_hook_lock);
 synchronize_net();
 return 0;
}
struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
#define NPROTO  32  /* should be enough for now.. */
/* Largest hook number + 1 */
#define NF_MAX_HOOKS 8
reg->hooknum
/* IP Hooks */
/* After promisc drops, checksum checks. */
#define NF_IP_PRE_ROUTING 0
/* If the packet is destined for this box. */
#define NF_IP_LOCAL_IN  1
/* If the packet is destined for another interface. */
#define NF_IP_FORWARD  2
/* Packets coming from a local process. */
#define NF_IP_LOCAL_OUT  3
/* Packets about to hit the wire. */
#define NF_IP_POST_ROUTING 4
#define NF_IP_NUMHOOKS  5
reg->priority
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_BRIDGE_SABOTAGE_FORWARD = -175,
 NF_IP_PRI_MANGLE = -150,
 NF_IP_PRI_NAT_DST = -100,
 NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
 NF_IP_PRI_FILTER = 0,
 NF_IP_PRI_NAT_SRC = 100,
 NF_IP_PRI_SELINUX_LAST = 225,
 NF_IP_PRI_LAST = INT_MAX,
};
 
在来看一下NF_HOOK宏
ip_forward() return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, rt->u.dst.dev,
         ip_forward_finish);
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)   \
(list_empty(&nf_hooks[(pf)][(hook)])     \
 ? (okfn)(skb)        \
 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
   struct net_device *indev,
   struct net_device *outdev,
   int (*okfn)(struct sk_buff *),
   int hook_thresh){
struct list_head *elem;
elem = &nf_hooks[pf][hook];
next_hook:
 verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev,
        outdev, &elem, okfn, hook_thresh);
 if (verdict == NF_QUEUE) {
  NFDEBUG("nf_hook: Verdict = QUEUE.\n");
  if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn))
   goto next_hook;
 }
 switch (verdict) {
 case NF_ACCEPT:
  ret = okfn(skb);
  break;
 case NF_DROP:
  kfree_skb(skb);
  ret = -EPERM;
  break;
 }
 rcu_read_unlock();
 return ret;
}
static unsigned int nf_iterate(struct list_head *head,
          struct sk_buff **skb,
          int hook,
          const struct net_device *indev,
          const struct net_device *outdev,
          struct list_head **i,
          int (*okfn)(struct sk_buff *),
          int hook_thresh)
{
 /*
  * The caller must not block between calls to this
  * function because of risk of continuing from deleted element.
  */
 list_for_each_continue_rcu(*i, head) {
  struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
  if (hook_thresh > elem->priority)
   continue;
  /* Optimization: we don't need to hold module
                   reference here, since function can't sleep. --RR */
  switch (elem->hook(hook, skb, indev, outdev, okfn)) {
  case NF_QUEUE:
   return NF_QUEUE;
  case NF_STOLEN:
   return NF_STOLEN;
  case NF_DROP:
   return NF_DROP;
  case NF_REPEAT:
   *i = (*i)->prev;
   break;
#ifdef CONFIG_NETFILTER_DEBUG
  case NF_ACCEPT:
   break;
  default:
   NFDEBUG("Evil return from %p(%u).\n",
    elem->hook, hook);
#endif
  }
 }
 return NF_ACCEPT;
}
源码net\ipv4目录下 grep NF_HOOK *.c 可以看到内核使用了如下HOOK点
arp.c:  NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
arp.c:  return NF_HOOK(NF_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
igmp.c: return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
igmp.c: return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
ip_forward.c:   return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, rt->u.dst.dev,
ip_input.c:     return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
ip_input.c:     return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
ipmr.c: NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev,
ip_output.c:    return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
ip_output.c:    return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
ip_output.c:                            NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL,
ip_output.c:                    NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL,
ip_output.c:    return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
ip_output.c:    err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
raw.c:  err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
 

posted on 2010-12-14 16:13 lstar 阅读(323) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2020年2月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
1234567

统计

常用链接

留言簿

文章档案

搜索

最新评论