Linux2.6中xfrm框架的dst_output的处理过程
Linux2.6中xfrm框架的dst_output的处理过程
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链表。
--------------------------
NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
xfrm4_output_finish,
!(IPCB(skb)->flags & IPSKB_REROUTED));
如果设置了IPSKB_REROUTED标记,直接执行xfrm4_output_finish不去走hook链表,要是没有设置IPSKB_REROUTED.肯定是遍历完了整个hook链表.
评论暂时关闭