Chinaunix首页 | 论坛 | 博客
  • 博客访问: 19284
  • 博文数量: 4
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 40
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-15 15:32
文章分类
文章存档

2013年(4)

我的朋友

分类: LINUX

2013-08-27 11:08:15

1、netfilter的核心数据结构为nf_hooks
    struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
    一维表示协议号,二维表示钩子点,每个元素都是一个双向链表。
   实际的钩子点结构体   

    struct nf_hook_ops {
     struct list_head list;//用于嵌入到nf_hooks

     /* 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;//优先级
     atomic_t counter;//被引用次数
    };


2、netfilter使用NF_HOOK宏在协议栈的不同位置获取skb
    1> 函数的不同返回值,表示不同的意思:(在NF_HOOK封装的nf_hook_slow中实现)
        NF_DROP(0)           数据包被丢弃。即不被下一个钩子函数处理,同时也不再被协议栈处理,并释放掉该数据包。协议栈将处理下一个数据包。
        NF_ACCEPT(1)        数据包允许通过。即交给下一个钩子函数处理、或交给协议栈继续处理(okfn())。
        NF_STOLEN(2)        数据包被停止处理。即不被下一个钩子函数处理,同时也不被协议栈处理,但也不释放数据包。协议栈将处理下一个数据包。
        NF_QUEUE(3)          将数据包交给nf_queue子系统处理。即不被下一个钩子函数处理,也不被协议栈处理,也不释放数据包。协议栈将处理下一个数据包。
        NF_REPEAT(4)        数据包将被该返回值的钩子函数再次处理一遍。
        NF_STOP(5)           数据包停止被该HOOK点的后续钩子函数处理,并交给协议栈继续处理(okfn())
        1-1-1-2-1记忆方法。
    2> NF_HOOK函数
         NF_HOOK本身是一个宏函数;
              -> NF_HOOK_THRESH -> nf_hook_thresh -> nf_hook_slow
         #define NF_HOOK(pf, hook, skb, indev, outdev, okfn)  NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, INT_MIN)
        
            #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)        \
            ({int __ret;               \
            if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, thresh, 1)) == 1)\
             __ret = (okfn)(skb);             \
             __ret;})

            static inline int nf_hook_thresh(int pf, unsigned int hook,
             struct sk_buff *skb,
             struct net_device *indev,
             struct net_device *outdev,
             int (*okfn)(struct sk_buff *), int thresh,
             int cond)
            {
             if (!cond)
              return 1;
            #ifndef CONFIG_NETFILTER_DEBUG
             if (list_empty(&nf_hooks[pf][hook]))
              return 1;
            #endif
             return nf_hook_slow(pf, hook, skb, indev, outdev, okfn, thresh);
            }

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;
 unsigned int verdict;
 int ret = 0;

#ifdef CONFIG_NET_NS
 struct net *net;

 net = indev == NULL ? dev_net(outdev) : dev_net(indev);
 if (net != &init_net)
  return 1;
#endif

 /* We may already have this, but read-locks nest anyway */
 rcu_read_lock();

 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_ACCEPT || verdict == NF_STOP) {
  ret = 1;
  goto unlock;
 } else if (verdict == NF_DROP) {
  kfree_skb(skb);
  ret = -EPERM;
 } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
  if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
         verdict >> NF_VERDICT_BITS))
   goto next_hook;
 }
unlock:
 rcu_read_unlock();
 return ret;
}

  可以看出nf_iterate是其核心,这里将对nf_iterate返回值(也就是相应的钩子函数的返回值)NF_ACCEPT、NF_STOP、NF_DROP、NF_QUEUE进行处理。

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)
{
 unsigned int verdict;

 /*
  * 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 */
  verdict = elem->hook(hook, skb, indev, outdev, okfn);
  if (verdict != NF_ACCEPT) {
#ifdef CONFIG_NETFILTER_DEBUG
   if (unlikely((verdict & NF_VERDICT_MASK)
       > NF_MAX_VERDICT)) {
    NFDEBUG("Evil return from %p(%u).\n",
     elem->hook, hook);
    continue;
   }
#endif
   if (verdict != NF_REPEAT)
    return verdict;
   *i = (*i)->prev;
  }
 }
 return NF_ACCEPT;
}
#define list_for_each_continue_rcu(pos, head) \
 for ((pos) = rcu_dereference((pos)->next); \
  prefetch((pos)->next), (pos) != (head); \
  (pos) = rcu_dereference((pos)->next))

nf_iterate的核心是list_for_each_continue_rcu,这是一个for循环;将满足条件的:协议 + hook_thresh优先级以上 + hook点 的钩子函数执行;处理特殊的钩子函数返回值NF_REPEAT。



对skb的主要处理在nf_hook_slow函数中:

                   

阅读(1359) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~