linux2.6中xfrm框架的dst_output的处理过程

原文链接:http://bbs.chinaunix.net/thread-2014756-1-1.html


Linux内核中ipsec的dst_output处理过程,当执行第一个dst_output时,这时会进入 xfrm4_outpot,下面是这个函数的代码:

int xfrm4_output(struct sk_buff *skb)
{
        return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
                            xfrm4_output_finish,
                            !(IPCB(skb)->flags & IPSKB_REROUTED));
}


static int xfrm4_output_finish(struct sk_buff *skb)
{
        int err;

#ifdef CONFIG_NETFILTER
        if (!skb->dst->xfrm) {
                IPCB(skb)->flags |= IPSKB_REROUTED;
                return dst_output(skb);
        }
#endif
        while (likely((err = xfrm4_output_one(skb)) == 0)) {
                nf_reset(skb);

                err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL,
                              skb->dst->dev, dst_output);
                if (unlikely(err != 1))
                        break;

                if (!skb->dst->xfrm)
                        return dst_output(skb);

                err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
                              skb->dst->dev, xfrm4_output_finish);
                if (unlikely(err != 1))
                        break;
        }

        return err;
}

static int xfrm4_output_one(struct sk_buff *skb)
{
        struct dst_entry *dst = skb->dst;
        struct xfrm_state *x = dst->xfrm;
        int err;
      
        if (skb->ip_summed == CHECKSUM_HW) {
                err = skb_checksum_help(skb, 0);
                if (err)
                        goto error_nolock;
        }

        if (x->props.mode) {
                err = xfrm4_tunnel_check_size(skb);
                if (err)
                        goto error_nolock;
        }

        do {
                spin_lock_bh(&x->lock);
                err = xfrm_state_check(x, skb);
                if (err)
                        goto error;

                xfrm4_encap(skb);

                err = x->type->output(x, skb);
                if (err)
                        goto error;

                x->curlft.bytes += skb->len;
                x->curlft.packets++;

                spin_unlock_bh(&x->lock);
      
                if (!(skb->dst = dst_pop(dst))) {
                        err = -EHOSTUNREACH;
                        goto error_nolock;
                }
                dst = skb->dst;
                x = dst->xfrm;
        } while (x && !x->props.mode);

        IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
        err = 0;

out_exit:
        return err;
error:
        spin_unlock_bh(&x->lock);
error_nolock:
        kfree_skb(skb);
        goto out_exit;
}

这段代码中嵌套调用了很多NF_HOOK_COND nf_hook函数,他最终是怎么推出循环调用到最后的ip_output的呢?在xfrm4_output_finish首先运行 xfrm4_output_one执行了esp_output和ah_output进行了完整性认证,为什么后面还可以调用 nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL,
                              skb->dst->dev, dst_output);和nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
                              skb->dst->dev, xfrm4_output_finish);进行NAT操作?我觉得在这里没必要调用nf_hook函数去走重新遍历hook链表。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值