aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/xfrm6_output.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 16e84254a252..48fccb1eca08 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -94,7 +94,7 @@ error_nolock:
94 goto out_exit; 94 goto out_exit;
95} 95}
96 96
97static int xfrm6_output_finish(struct sk_buff *skb) 97static int xfrm6_output_finish2(struct sk_buff *skb)
98{ 98{
99 int err; 99 int err;
100 100
@@ -110,7 +110,7 @@ static int xfrm6_output_finish(struct sk_buff *skb)
110 return dst_output(skb); 110 return dst_output(skb);
111 111
112 err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL, 112 err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL,
113 skb->dst->dev, xfrm6_output_finish); 113 skb->dst->dev, xfrm6_output_finish2);
114 if (unlikely(err != 1)) 114 if (unlikely(err != 1))
115 break; 115 break;
116 } 116 }
@@ -118,6 +118,41 @@ static int xfrm6_output_finish(struct sk_buff *skb)
118 return err; 118 return err;
119} 119}
120 120
121static int xfrm6_output_finish(struct sk_buff *skb)
122{
123 struct sk_buff *segs;
124
125 if (!skb_shinfo(skb)->gso_size)
126 return xfrm6_output_finish2(skb);
127
128 skb->protocol = htons(ETH_P_IP);
129 segs = skb_gso_segment(skb, 0);
130 kfree_skb(skb);
131 if (unlikely(IS_ERR(segs)))
132 return PTR_ERR(segs);
133
134 do {
135 struct sk_buff *nskb = segs->next;
136 int err;
137
138 segs->next = NULL;
139 err = xfrm6_output_finish2(segs);
140
141 if (unlikely(err)) {
142 while ((segs = nskb)) {
143 nskb = segs->next;
144 segs->next = NULL;
145 kfree_skb(segs);
146 }
147 return err;
148 }
149
150 segs = nskb;
151 } while (segs);
152
153 return 0;
154}
155
121int xfrm6_output(struct sk_buff *skb) 156int xfrm6_output(struct sk_buff *skb)
122{ 157{
123 return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev, 158 return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev,