|
@@ -59,7 +59,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
|
|
return err;
|
|
|
|
|
|
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
|
|
- IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
|
|
|
+ IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED;
|
|
|
|
|
|
skb->protocol = htons(ETH_P_IP);
|
|
|
|
|
@@ -67,87 +67,19 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
|
|
|
}
|
|
|
EXPORT_SYMBOL(xfrm4_prepare_output);
|
|
|
|
|
|
-static inline int xfrm4_output_one(struct sk_buff *skb)
|
|
|
-{
|
|
|
- int err;
|
|
|
-
|
|
|
- err = xfrm_output(skb);
|
|
|
- if (err)
|
|
|
- goto error_nolock;
|
|
|
-
|
|
|
- IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
|
|
|
- err = 0;
|
|
|
-
|
|
|
-out_exit:
|
|
|
- return err;
|
|
|
-error_nolock:
|
|
|
- kfree_skb(skb);
|
|
|
- goto out_exit;
|
|
|
-}
|
|
|
-
|
|
|
-static int xfrm4_output_finish2(struct sk_buff *skb)
|
|
|
-{
|
|
|
- int err;
|
|
|
-
|
|
|
- while (likely((err = xfrm4_output_one(skb)) == 0)) {
|
|
|
- nf_reset(skb);
|
|
|
-
|
|
|
- err = __ip_local_out(skb);
|
|
|
- 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_finish2);
|
|
|
- if (unlikely(err != 1))
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return err;
|
|
|
-}
|
|
|
-
|
|
|
static int xfrm4_output_finish(struct sk_buff *skb)
|
|
|
{
|
|
|
- struct sk_buff *segs;
|
|
|
-
|
|
|
#ifdef CONFIG_NETFILTER
|
|
|
if (!skb->dst->xfrm) {
|
|
|
IPCB(skb)->flags |= IPSKB_REROUTED;
|
|
|
return dst_output(skb);
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
- if (!skb_is_gso(skb))
|
|
|
- return xfrm4_output_finish2(skb);
|
|
|
+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
|
|
|
+#endif
|
|
|
|
|
|
skb->protocol = htons(ETH_P_IP);
|
|
|
- segs = skb_gso_segment(skb, 0);
|
|
|
- kfree_skb(skb);
|
|
|
- if (unlikely(IS_ERR(segs)))
|
|
|
- return PTR_ERR(segs);
|
|
|
-
|
|
|
- do {
|
|
|
- struct sk_buff *nskb = segs->next;
|
|
|
- int err;
|
|
|
-
|
|
|
- segs->next = NULL;
|
|
|
- err = xfrm4_output_finish2(segs);
|
|
|
-
|
|
|
- if (unlikely(err)) {
|
|
|
- while ((segs = nskb)) {
|
|
|
- nskb = segs->next;
|
|
|
- segs->next = NULL;
|
|
|
- kfree_skb(segs);
|
|
|
- }
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
- segs = nskb;
|
|
|
- } while (segs);
|
|
|
-
|
|
|
- return 0;
|
|
|
+ return xfrm_output(skb);
|
|
|
}
|
|
|
|
|
|
int xfrm4_output(struct sk_buff *skb)
|