patches/ask/kernel/0115-net__ipv6__output_core.c.patch
raw ยท 1318 bytes
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index 1c9b283..5682505 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -130,7 +130,19 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
len = skb->len - sizeof(struct ipv6hdr);
if (len > IPV6_MAXPLEN)
len = 0;
+
+#if defined(CONFIG_INET6_IPSEC_OFFLOAD)
+ /*
+ * Since tunnel header is not added in slow path and route cache entry
+ * lookup is changed to perform lookup on tunnel header, dst_output()
+ * may reach IPv6 output for IPv4-over-IPv6 IPsec tunnel packets. Only
+ * update the IPv6 payload length when the skb really carries IPv6 here.
+ */
+ if (ipv6_hdr(skb)->version == 6)
+ ipv6_hdr(skb)->payload_len = htons(len);
+#else
ipv6_hdr(skb)->payload_len = htons(len);
+#endif
IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
/* if egress device is enslaved to an L3 master device pass the
@@ -142,6 +154,13 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
skb->protocol = htons(ETH_P_IPV6);
+#if defined(CONFIG_INET6_IPSEC_OFFLOAD)
+ if (skb->ipsec_offload) {
+ dst_output(net, sk, skb);
+ return 0;
+ }
+#endif
+
return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
net, sk, skb, NULL, skb_dst_dev(skb),
dst_output);