aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid Miller <davem@davemloft.net>2015-04-05 22:19:04 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-07 15:25:55 -0400
commit7026b1ddb6b8d4e6ee33dc2bd06c0ca8746fa7ab (patch)
tree3e11ed0f186ea6066a3f7efecb88d85bc732ee51 /net/ipv6
parent1c984f8a5df085bcf35364a8a870bd4db4da4ed3 (diff)
netfilter: Pass socket pointer down through okfn().
On the output paths in particular, we have to sometimes deal with two socket contexts. First, and usually skb->sk, is the local socket that generated the frame. And second, is potentially the socket used to control a tunneling socket, such as one the encapsulates using UDP. We do not want to disassociate skb->sk when encapsulating in order to fix this, because that would break socket memory accounting. The most extreme case where this can cause huge problems is an AF_PACKET socket transmitting over a vxlan device. We hit code paths doing checks that assume they are dealing with an ipv4 socket, but are actually operating upon the AF_PACKET one. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6_input.c11
-rw-r--r--net/ipv6/ip6_output.c33
-rw-r--r--net/ipv6/ip6mr.c7
-rw-r--r--net/ipv6/mcast.c9
-rw-r--r--net/ipv6/ndisc.c5
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c2
-rw-r--r--net/ipv6/output_core.c4
-rw-r--r--net/ipv6/raw.c4
-rw-r--r--net/ipv6/xfrm6_input.c3
-rw-r--r--net/ipv6/xfrm6_output.c15
10 files changed, 51 insertions, 42 deletions
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index fb97f7f8d4ed..f2e464eba5ef 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -46,8 +46,7 @@
46#include <net/xfrm.h> 46#include <net/xfrm.h>
47#include <net/inet_ecn.h> 47#include <net/inet_ecn.h>
48 48
49 49int ip6_rcv_finish(struct sock *sk, struct sk_buff *skb)
50int ip6_rcv_finish(struct sk_buff *skb)
51{ 50{
52 if (sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) { 51 if (sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
53 const struct inet6_protocol *ipprot; 52 const struct inet6_protocol *ipprot;
@@ -183,7 +182,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
183 /* Must drop socket now because of tproxy. */ 182 /* Must drop socket now because of tproxy. */
184 skb_orphan(skb); 183 skb_orphan(skb);
185 184
186 return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, dev, NULL, 185 return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, NULL, skb,
186 dev, NULL,
187 ip6_rcv_finish); 187 ip6_rcv_finish);
188err: 188err:
189 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); 189 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
@@ -198,7 +198,7 @@ drop:
198 */ 198 */
199 199
200 200
201static int ip6_input_finish(struct sk_buff *skb) 201static int ip6_input_finish(struct sock *sk, struct sk_buff *skb)
202{ 202{
203 struct net *net = dev_net(skb_dst(skb)->dev); 203 struct net *net = dev_net(skb_dst(skb)->dev);
204 const struct inet6_protocol *ipprot; 204 const struct inet6_protocol *ipprot;
@@ -277,7 +277,8 @@ discard:
277 277
278int ip6_input(struct sk_buff *skb) 278int ip6_input(struct sk_buff *skb)
279{ 279{
280 return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, skb, skb->dev, NULL, 280 return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, NULL, skb,
281 skb->dev, NULL,
281 ip6_input_finish); 282 ip6_input_finish);
282} 283}
283 284
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 654f245aa930..7fde1f265c90 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -56,7 +56,7 @@
56#include <net/checksum.h> 56#include <net/checksum.h>
57#include <linux/mroute6.h> 57#include <linux/mroute6.h>
58 58
59static int ip6_finish_output2(struct sk_buff *skb) 59static int ip6_finish_output2(struct sock *sk, struct sk_buff *skb)
60{ 60{
61 struct dst_entry *dst = skb_dst(skb); 61 struct dst_entry *dst = skb_dst(skb);
62 struct net_device *dev = dst->dev; 62 struct net_device *dev = dst->dev;
@@ -70,7 +70,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
70 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { 70 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
71 struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); 71 struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
72 72
73 if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) && 73 if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(sk) &&
74 ((mroute6_socket(dev_net(dev), skb) && 74 ((mroute6_socket(dev_net(dev), skb) &&
75 !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || 75 !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
76 ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, 76 ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
@@ -82,7 +82,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
82 */ 82 */
83 if (newskb) 83 if (newskb)
84 NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, 84 NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING,
85 newskb, NULL, newskb->dev, 85 sk, newskb, NULL, newskb->dev,
86 dev_loopback_xmit); 86 dev_loopback_xmit);
87 87
88 if (ipv6_hdr(skb)->hop_limit == 0) { 88 if (ipv6_hdr(skb)->hop_limit == 0) {
@@ -122,14 +122,14 @@ static int ip6_finish_output2(struct sk_buff *skb)
122 return -EINVAL; 122 return -EINVAL;
123} 123}
124 124
125static int ip6_finish_output(struct sk_buff *skb) 125static int ip6_finish_output(struct sock *sk, struct sk_buff *skb)
126{ 126{
127 if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || 127 if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
128 dst_allfrag(skb_dst(skb)) || 128 dst_allfrag(skb_dst(skb)) ||
129 (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) 129 (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size))
130 return ip6_fragment(skb, ip6_finish_output2); 130 return ip6_fragment(sk, skb, ip6_finish_output2);
131 else 131 else
132 return ip6_finish_output2(skb); 132 return ip6_finish_output2(sk, skb);
133} 133}
134 134
135int ip6_output(struct sock *sk, struct sk_buff *skb) 135int ip6_output(struct sock *sk, struct sk_buff *skb)
@@ -143,7 +143,8 @@ int ip6_output(struct sock *sk, struct sk_buff *skb)
143 return 0; 143 return 0;
144 } 144 }
145 145
146 return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, dev, 146 return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, sk, skb,
147 NULL, dev,
147 ip6_finish_output, 148 ip6_finish_output,
148 !(IP6CB(skb)->flags & IP6SKB_REROUTED)); 149 !(IP6CB(skb)->flags & IP6SKB_REROUTED));
149} 150}
@@ -223,8 +224,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
223 if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) { 224 if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) {
224 IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), 225 IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)),
225 IPSTATS_MIB_OUT, skb->len); 226 IPSTATS_MIB_OUT, skb->len);
226 return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, 227 return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
227 dst->dev, dst_output); 228 NULL, dst->dev, dst_output_sk);
228 } 229 }
229 230
230 skb->dev = dst->dev; 231 skb->dev = dst->dev;
@@ -316,10 +317,10 @@ static int ip6_forward_proxy_check(struct sk_buff *skb)
316 return 0; 317 return 0;
317} 318}
318 319
319static inline int ip6_forward_finish(struct sk_buff *skb) 320static inline int ip6_forward_finish(struct sock *sk, struct sk_buff *skb)
320{ 321{
321 skb_sender_cpu_clear(skb); 322 skb_sender_cpu_clear(skb);
322 return dst_output(skb); 323 return dst_output_sk(sk, skb);
323} 324}
324 325
325static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) 326static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
@@ -511,7 +512,8 @@ int ip6_forward(struct sk_buff *skb)
511 512
512 IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); 513 IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
513 IP6_ADD_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len); 514 IP6_ADD_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len);
514 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dst->dev, 515 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, NULL, skb,
516 skb->dev, dst->dev,
515 ip6_forward_finish); 517 ip6_forward_finish);
516 518
517error: 519error:
@@ -538,7 +540,8 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
538 skb_copy_secmark(to, from); 540 skb_copy_secmark(to, from);
539} 541}
540 542
541int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) 543int ip6_fragment(struct sock *sk, struct sk_buff *skb,
544 int (*output)(struct sock *, struct sk_buff *))
542{ 545{
543 struct sk_buff *frag; 546 struct sk_buff *frag;
544 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); 547 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
@@ -667,7 +670,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
667 ip6_copy_metadata(frag, skb); 670 ip6_copy_metadata(frag, skb);
668 } 671 }
669 672
670 err = output(skb); 673 err = output(sk, skb);
671 if (!err) 674 if (!err)
672 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 675 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
673 IPSTATS_MIB_FRAGCREATES); 676 IPSTATS_MIB_FRAGCREATES);
@@ -800,7 +803,7 @@ slow_path:
800 /* 803 /*
801 * Put this fragment into the sending queue. 804 * Put this fragment into the sending queue.
802 */ 805 */
803 err = output(frag); 806 err = output(sk, frag);
804 if (err) 807 if (err)
805 goto fail; 808 goto fail;
806 809
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 8493a22e74eb..74ceb73c1c9a 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1986,13 +1986,13 @@ int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1986} 1986}
1987#endif 1987#endif
1988 1988
1989static inline int ip6mr_forward2_finish(struct sk_buff *skb) 1989static inline int ip6mr_forward2_finish(struct sock *sk, struct sk_buff *skb)
1990{ 1990{
1991 IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), 1991 IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)),
1992 IPSTATS_MIB_OUTFORWDATAGRAMS); 1992 IPSTATS_MIB_OUTFORWDATAGRAMS);
1993 IP6_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), 1993 IP6_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)),
1994 IPSTATS_MIB_OUTOCTETS, skb->len); 1994 IPSTATS_MIB_OUTOCTETS, skb->len);
1995 return dst_output(skb); 1995 return dst_output_sk(sk, skb);
1996} 1996}
1997 1997
1998/* 1998/*
@@ -2064,7 +2064,8 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt,
2064 2064
2065 IP6CB(skb)->flags |= IP6SKB_FORWARDED; 2065 IP6CB(skb)->flags |= IP6SKB_FORWARDED;
2066 2066
2067 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dev, 2067 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, NULL, skb,
2068 skb->dev, dev,
2068 ip6mr_forward2_finish); 2069 ip6mr_forward2_finish);
2069 2070
2070out_free: 2071out_free:
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index fac1f27e428e..083b2927fc67 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1644,8 +1644,9 @@ static void mld_sendpack(struct sk_buff *skb)
1644 1644
1645 payload_len = skb->len; 1645 payload_len = skb->len;
1646 1646
1647 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, 1647 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
1648 dst_output); 1648 net->ipv6.igmp_sk, skb, NULL, skb->dev,
1649 dst_output_sk);
1649out: 1650out:
1650 if (!err) { 1651 if (!err) {
1651 ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT); 1652 ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT);
@@ -2007,8 +2008,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
2007 } 2008 }
2008 2009
2009 skb_dst_set(skb, dst); 2010 skb_dst_set(skb, dst);
2010 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, 2011 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
2011 dst_output); 2012 NULL, skb->dev, dst_output_sk);
2012out: 2013out:
2013 if (!err) { 2014 if (!err) {
2014 ICMP6MSGOUT_INC_STATS(net, idev, type); 2015 ICMP6MSGOUT_INC_STATS(net, idev, type);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 71fde6cafb35..96f153c0846b 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -463,8 +463,9 @@ static void ndisc_send_skb(struct sk_buff *skb,
463 idev = __in6_dev_get(dst->dev); 463 idev = __in6_dev_get(dst->dev);
464 IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); 464 IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
465 465
466 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, 466 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
467 dst_output); 467 NULL, dst->dev,
468 dst_output_sk);
468 if (!err) { 469 if (!err) {
469 ICMP6MSGOUT_INC_STATS(net, idev, type); 470 ICMP6MSGOUT_INC_STATS(net, idev, type);
470 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); 471 ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index e2b882056751..a45db0b4785c 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -75,7 +75,7 @@ static unsigned int ipv6_defrag(const struct nf_hook_ops *ops,
75 75
76 nf_ct_frag6_consume_orig(reasm); 76 nf_ct_frag6_consume_orig(reasm);
77 77
78 NF_HOOK_THRESH(NFPROTO_IPV6, ops->hooknum, reasm, 78 NF_HOOK_THRESH(NFPROTO_IPV6, ops->hooknum, state->sk, reasm,
79 state->in, state->out, 79 state->in, state->out,
80 state->okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1); 80 state->okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
81 81
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index 4016a6ef9d61..7d1131dc29fe 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -146,8 +146,8 @@ int __ip6_local_out(struct sk_buff *skb)
146 ipv6_hdr(skb)->payload_len = htons(len); 146 ipv6_hdr(skb)->payload_len = htons(len);
147 IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); 147 IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
148 148
149 return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, 149 return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb->sk, skb,
150 skb_dst(skb)->dev, dst_output); 150 NULL, skb_dst(skb)->dev, dst_output_sk);
151} 151}
152EXPORT_SYMBOL_GPL(__ip6_local_out); 152EXPORT_SYMBOL_GPL(__ip6_local_out);
153 153
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 79ccdb4c1b33..8072bd4139b7 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -652,8 +652,8 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
652 goto error_fault; 652 goto error_fault;
653 653
654 IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); 654 IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
655 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, 655 err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
656 rt->dst.dev, dst_output); 656 NULL, rt->dst.dev, dst_output_sk);
657 if (err > 0) 657 if (err > 0)
658 err = net_xmit_errno(err); 658 err = net_xmit_errno(err);
659 if (err) 659 if (err)
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index f48fbe4d16f5..74bd17882a2f 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -42,7 +42,8 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
42 ipv6_hdr(skb)->payload_len = htons(skb->len); 42 ipv6_hdr(skb)->payload_len = htons(skb->len);
43 __skb_push(skb, skb->data - skb_network_header(skb)); 43 __skb_push(skb, skb->data - skb_network_header(skb));
44 44
45 NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, 45 NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, NULL, skb,
46 skb->dev, NULL,
46 ip6_rcv_finish); 47 ip6_rcv_finish);
47 return -1; 48 return -1;
48} 49}
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 010f8bd2d577..09c76a7b474d 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -120,7 +120,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
120} 120}
121EXPORT_SYMBOL(xfrm6_prepare_output); 121EXPORT_SYMBOL(xfrm6_prepare_output);
122 122
123int xfrm6_output_finish(struct sk_buff *skb) 123int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
124{ 124{
125 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); 125 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
126 126
@@ -128,10 +128,10 @@ int xfrm6_output_finish(struct sk_buff *skb)
128 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; 128 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
129#endif 129#endif
130 130
131 return xfrm_output(skb); 131 return xfrm_output(sk, skb);
132} 132}
133 133
134static int __xfrm6_output(struct sk_buff *skb) 134static int __xfrm6_output(struct sock *sk, struct sk_buff *skb)
135{ 135{
136 struct dst_entry *dst = skb_dst(skb); 136 struct dst_entry *dst = skb_dst(skb);
137 struct xfrm_state *x = dst->xfrm; 137 struct xfrm_state *x = dst->xfrm;
@@ -140,7 +140,7 @@ static int __xfrm6_output(struct sk_buff *skb)
140#ifdef CONFIG_NETFILTER 140#ifdef CONFIG_NETFILTER
141 if (!x) { 141 if (!x) {
142 IP6CB(skb)->flags |= IP6SKB_REROUTED; 142 IP6CB(skb)->flags |= IP6SKB_REROUTED;
143 return dst_output(skb); 143 return dst_output_sk(sk, skb);
144 } 144 }
145#endif 145#endif
146 146
@@ -160,14 +160,15 @@ static int __xfrm6_output(struct sk_buff *skb)
160 if (x->props.mode == XFRM_MODE_TUNNEL && 160 if (x->props.mode == XFRM_MODE_TUNNEL &&
161 ((skb->len > mtu && !skb_is_gso(skb)) || 161 ((skb->len > mtu && !skb_is_gso(skb)) ||
162 dst_allfrag(skb_dst(skb)))) { 162 dst_allfrag(skb_dst(skb)))) {
163 return ip6_fragment(skb, x->outer_mode->afinfo->output_finish); 163 return ip6_fragment(sk, skb,
164 x->outer_mode->afinfo->output_finish);
164 } 165 }
165 return x->outer_mode->afinfo->output_finish(skb); 166 return x->outer_mode->afinfo->output_finish(sk, skb);
166} 167}
167 168
168int xfrm6_output(struct sock *sk, struct sk_buff *skb) 169int xfrm6_output(struct sock *sk, struct sk_buff *skb)
169{ 170{
170 return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, 171 return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, sk, skb,
171 NULL, skb_dst(skb)->dev, __xfrm6_output, 172 NULL, skb_dst(skb)->dev, __xfrm6_output,
172 !(IP6CB(skb)->flags & IP6SKB_REROUTED)); 173 !(IP6CB(skb)->flags & IP6SKB_REROUTED));
173} 174}