zoukankan      html  css  js  c++  java
  • netfiler源代码分析之框架介绍

    netfiler框架是在内核协议栈实现的基础上完成的,在报文从网口接收,路由等方法实现基础上使用NF_HOOK调用相应的钩子来进入netfiler框架的处理,如

    ip_rcv之后会调用NF_HOOK(NF_IP_PRE_ROUTING)

    NF_HOOK宏定义如下:

     

    #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 **pskb,
    				 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, pskb, indev, outdev, okfn, thresh);
    }
    

     

    重点介绍下nf_hook_slow方法。

     

    nf_hook_slow针对调用NF_HOOK时的hook点,遍历所有的钩子函数并判断匹配(match)及完成相应处理(target)

     

    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();
    
    	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;
    		goto unlock;
    	} else if (verdict == NF_DROP) {
    		kfree_skb(*pskb);
    		ret = -EPERM;
    	} else if ((verdict & NF_VERDICT_MASK)  == NF_QUEUE) {
    		NFDEBUG("nf_hook: Verdict = QUEUE.
    ");
    		if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn,
    			      verdict >> NF_VERDICT_BITS))
    			goto next_hook;
    	}
    unlock:
    	rcu_read_unlock();
    	return ret;
    }

     

    选择hook对应的钩子函数时,使用了 nf_hooksstruct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]二维数组,其中行定义了协议簇类型,最大为NPROTO33),列定义了不同的hook,具体内容如下所示(参考netfilter_ipv4.h)

     

    #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

     

    下面针对每个HOOK点列举下协议栈中的调用

    1. ip_rcv中调用NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,ip_rcv_finish)

    网卡接收ip报文后经过pre_routing hook点处理。此hook点一般是用来做DNAT。

    2. ip_local_deliver中调用NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,ip_local_deliver_finish)

    ip报文被本地网卡接收后,经过local_in hook点处理

    3. ip_forward中调用NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, rt->u.dst.dev, ip_forward_finish)

    路由查询后不是本地数据,需要做转发处理,经过forward hook点处理

    4. ip_push_pending_frames中调用NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,dst_output)

    此处理是将ip分片报文重组后送出去

    5. ip_output中调用NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,ip_finish_output,!(IPCB(skb)->flags & IPSKB_REROUTED))

    如果报文中没有设置IPSKB_REROUTED标志,则报文会过post_routing hook点处理。此hook点一般是用来做SNAT的。

     

    NEXT: 后面会介绍netfilter框架如何注册hook钩子。

     

  • 相关阅读:
    写的好的功能参考地址
    碰撞检测原理
    懒加载原理的实现
    jQuery图片延迟加载插件jQuery.lazyload 的使用
    电子工厂生产楼职位解析
    打印条码方式
    条码打印二
    条码打印三
    CSS实现圆角矩形
    条码打印四
  • 原文地址:https://www.cnblogs.com/haoqingchuan/p/6240483.html
Copyright © 2011-2022 走看看