Chinaunix首页 | 论坛 | 博客
  • 博客访问: 541395
  • 博文数量: 140
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 650
  • 用 户 组: 普通用户
  • 注册时间: 2012-12-11 19:00
文章存档

2015年(5)

2014年(135)

分类: LINUX

2014-03-10 23:22:32

       先看一下,NF_HOOK函数是如何调用每个回调函数的。
       NF_HOOK --> NF_HOOK_THRESH --> nf_hook_thresh --> nf_hook_slow.  nf_hook_slow函数才是处理回调函数的关键。
       代码如下:
/* Returns 1 if okfn() needs to be executed by the caller,
 * -EPERM for NF_DROP, 0 otherwise. */
int nf_hook_slow(u_int8_t 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;        //四个字节,高16位为queue-num,低16位是NF_QUEUE.
        int ret = 0;

        /* 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);         //verdict是回调函数的返回值,比如返回一个NF_QUEUE.
        if (verdict == NF_ACCEPT || verdict == NF_STOP) {
                ret = 1;
        } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
                kfree_skb(skb);
                ret = NF_DROP_GETERR(verdict);
                if (ret == 0)
                        ret = -EPERM;
        } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
                int err = nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
                                                verdict >> NF_VERDICT_QBITS);          //将数据包传递给上层,并等待消息
                if (err < 0) {
                        if (err == -ECANCELED)
                                goto next_hook;
                        if (err == -ESRCH &&
                           (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
                                goto next_hook;
                        kfree_skb(skb);
                }
        }
        rcu_read_unlock();
        return ret;
}
EXPORT_SYMBOL(nf_hook_slow);

回调函数直接返回NF_QUEUE, 然后交给上层的应用程序去处理。应用程序处理完毕,返回处理意见。这样就没iptable什么事情了。

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