为什么80%的码农都做不了架构师?>>>   

Hook被注册后,它就会在那里守株待兔,等待自动送上门的数据包,那么内核是如何调用到注册的Hook的呢?在分析NF_HOOK的时候说过,如果指定协议的指定钩子类型上注册了钩子函数数,会调用nf_hook_slow函数:

CODE:
/* Returns 1 if okfn() needs to be executed by the caller,
* -EPERM for NF_DROP, 0 otherwise. */
int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
    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;

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

#ifdef CONFIG_NETFILTER_DEBUG
if (unlikely((*pskb)->nf_debug & (1 << hook))) {
printk("nf_hook: hook %i already set.\n", hook);
nf_dump_skb(pf, *pskb);
}
(*pskb)->nf_debug |= (1 << hook);
#endif
/*取得对应的链表首部*/
elem = &nf_hooks[pf][hook];
next_hook:
/*调用对应的钩子函数*/
verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
      outdev, &elem, okfn, hook_thresh);
/*判断返回值,做相应的处理*/
if (verdict == NF_ACCEPT || verdict == NF_STOP) {
ret = 1; /*前面提到过,返回1,则表示装继续调用okfn函数指针*/
goto unlock;
} else if (verdict == NF_DROP) {
kfree_skb(*pskb); /*删除数据包,需要释放skb*/
ret = -EPERM;
} else if (verdict == NF_QUEUE) {
NFDEBUG("nf_hook: Verdict = QUEUE.\n");
if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn))
goto next_hook;
}
unlock:
rcu_read_unlock();
return ret;
}

内核的数据转发函数,调用宏NF_HOOK时,会告诉它协议簇和Hook类型,nf_hook_slow函数根据这两个要素,可以很轻易地从nf_hooks 中取得对应的前面注册好的Hook链表的首部:
elem = &nf_hooks[pf][hook];
然后,就调用函数nf_iterate ,遍历Hook链表,调用链用上所有的Hook函数

2、nf_iterate 函数

CODE:
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)
{
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) { /*遍历所有注册的Hook*/
/*取得当前遍历的Hook*/
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 */
/*调用Hook 的函数*/
` verdict = elem->hook(hook, skb, indev, outdev, okfn);
if (verdict != NF_ACCEPT) {
#ifdef CONFIG_NETFILTER_DEBUG
if (unlikely(verdict > 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;
}

我们可以看到,函数在一个链表的遍历过程中,不断地调用对应的Hook函数:
verdict = elem->hook(hook, skb, indev, outdev, okfn);
以执行我们注册好的Hook,对数据包进行我们想要的处理。函数的返回值verdict决定了封包的命令,接受或丢弃,Netfilter共有6 个值:

CODE:
/* Responses from hook functions. */
#define NF_DROP 0     丢弃该数据包
#define NF_ACCEPT 1     保留该数据包
#define NF_STOLEN 2     记掉该数据包
#define NF_QUEUE 3     将该数据包插入到用户空间
#define NF_REPEAT 4              再次调用该Hook函数
#define NF_STOP 5     停止检测,不再进行下一个Hook函数

逐 个分析每一个Hook函数,就可以了解整个Netfilter的运行机理,这是我后面的重点内容。现在需要回答的问题是,如果同时注册了N个Hook,它 们对封包的处理,有的是ACCEPT,有的是DROP,那么如果前一个DROP了它,后面的Hook函数还会被执行吗?来看返回值的处理代码:

CODE:
if (verdict != NF_ACCEPT)
{
if (verdict != NF_REPEAT)
return verdict;
*i = (*i)->prev;
}

很明显,如果是ACCEPT动作,那么还会继续调用下一个Hook,否则,当是REPEAT时,再返回前一个Hook,至于其它动作,则直接返回,不再断续调用下一个Hook,换句话讲,就是如果数据包已经被前一个Hook函数丢弃,当然不会再被交给下一个Hook函数。

转载于:https://my.oschina.net/rickie/blog/14331

nf_hook_slow函数相关推荐

  1. 洞悉linux下的Netfilteriptables

    原网址:http://blog.chinaunix.net/uid-23069658-id-3160506.html (一)洞悉linux下的Netfilter&iptables:什么是Net ...

  2. Netfilter 详解

    其他不错的文章: http://bbs.chinaunix.net/thread-2196854-1-1.html 引用: http://blog.chinaunix.net/uid-24977843 ...

  3. linux内核netfilter模块分析之:HOOKs点的注册及调用

    1: 为什么要写这个东西? 最近在找工作,之前netfilter 这一块的代码也认真地研究过,应该每个人都是这样的你懂 不一定你能很准确的表达出来. 故一定要化些时间把这相关的东西总结一下. 0:相关 ...

  4. Netfilter分析

    一.概述 1. Netfilter/IPTables框架简介 Netfilter/IPTables是继2.0.x的IPfwadm.2.2.x的IPchains之后,新一代的Linux防火墙机制.Net ...

  5. Linux就这个范儿 第12章 一个网络一个世界

    Linux就这个范儿 第12章 一个网络一个世界 与Linux有缘相识还得从一项开发任务说起.十八年前,我在Nucleus  OS上开发无线网桥AP,需要加入STP生成树协议(SpanningTree ...

  6. netfilter编程实例——一个简单的防火墙

    一.iptables防火墙netfilter介绍 Linux 防火墙包含两部分,内核 netfilter 和用户空间工具 iptables.管理员通过 iptables 工具集和内核打交道,将防火墙规 ...

  7. netfilter——独孤九剑

    一.主函数 init为初始化函数,主要完成表的注册,然后再注册与表相对应的HOOK  //初始化函数为init:  module_init(init); //init 函数负责注册filter表和默认 ...

  8. [原创]Netfilter源码分析-我来抛砖,望能引玉

    from: http://linux.chinaunix.net/bbs/viewthread.php?tid=670248&extra=&page=1 前段时间 贴了一篇<ip ...

  9. Netfilter源码分析

      Netfilter源码分析(1)(ZT) 收藏 <script type="text/javascript"></script> 一.主函数 init为 ...

最新文章

  1. Pytorch:使用DCGAN实现数据复制
  2. 计算机基础-计算机硬件
  3. oracle11g 多了个 client,Oracle10g Client Oracle11g DB同时安装发生OCI Error
  4. 全球首款碳纳米管通用计算芯片问世!RISC-V架构,5倍于摩尔定律,Nature连发三文推荐...
  5. CentOS6安装redmine
  6. Top命令找出CPU占用较高的Java线程信息
  7. 【HTML】底部弹窗插件代码
  8. php 企业邮箱,PHPMailer可能被全球邮(企业邮箱提供)拉黑
  9. 判断字符串最后两个字符
  10. Spring @RequestMapping注解示例
  11. Linu的sftp环境搭建
  12. Unity3D游戏开发从零单排(三) - 极速创建狂拽酷炫的游戏地形
  13. 耐用的蓝牙耳机推荐,现在比较好的蓝牙耳机点评
  14. 酒店BI成就创业者管理升级
  15. 安卓flash播放器支持Android 12方案
  16. 联通托管服务器为什么打不开网页,为什么有些网页联通宽带打不开,移动4G能打开?...
  17. Your application has presented a UIAlertController of style UIAlertControllerStyleActionSheet.
  18. 教你如何实现网页自由!
  19. windows改键软件——sharpkeys
  20. 全球隔离,生出不少坏毛病

热门文章

  1. uLua中遇到的问题
  2. Python多线程thread与threading实现
  3. 一个很好的 emacs 配置文件范例
  4. asp.net .ashx文件使用server.mappath解决方法
  5. 开源Wiki系统:XWiki 2.0.2 发布
  6. intellij IDEA怎样打war包
  7. dede首页调用栏目内容{dedefield.content}的方法
  8. MATLAB 图像的平滑和边缘检测
  9. 项目源码分享之[条码扫描后台监控程序]
  10. Solr调优参考-续