diff options
author | David Miller <davem@davemloft.net> | 2015-04-05 22:19:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-04-07 15:25:55 -0400 |
commit | 7026b1ddb6b8d4e6ee33dc2bd06c0ca8746fa7ab (patch) | |
tree | 3e11ed0f186ea6066a3f7efecb88d85bc732ee51 /net/ipv6 | |
parent | 1c984f8a5df085bcf35364a8a870bd4db4da4ed3 (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.c | 11 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 33 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 7 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 9 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 2 | ||||
-rw-r--r-- | net/ipv6/output_core.c | 4 | ||||
-rw-r--r-- | net/ipv6/raw.c | 4 | ||||
-rw-r--r-- | net/ipv6/xfrm6_input.c | 3 | ||||
-rw-r--r-- | net/ipv6/xfrm6_output.c | 15 |
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 | 49 | int ip6_rcv_finish(struct sock *sk, struct sk_buff *skb) | |
50 | int 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); |
188 | err: | 188 | err: |
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 | ||
201 | static int ip6_input_finish(struct sk_buff *skb) | 201 | static 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 | ||
278 | int ip6_input(struct sk_buff *skb) | 278 | int 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 | ||
59 | static int ip6_finish_output2(struct sk_buff *skb) | 59 | static 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 | ||
125 | static int ip6_finish_output(struct sk_buff *skb) | 125 | static 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 | ||
135 | int ip6_output(struct sock *sk, struct sk_buff *skb) | 135 | int 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 | ||
319 | static inline int ip6_forward_finish(struct sk_buff *skb) | 320 | static 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 | ||
325 | static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) | 326 | static 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 | ||
517 | error: | 519 | error: |
@@ -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 | ||
541 | int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | 543 | int 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 | ||
1989 | static inline int ip6mr_forward2_finish(struct sk_buff *skb) | 1989 | static 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 | ||
2070 | out_free: | 2071 | out_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); | ||
1649 | out: | 1650 | out: |
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); |
2012 | out: | 2013 | out: |
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 | } |
152 | EXPORT_SYMBOL_GPL(__ip6_local_out); | 152 | EXPORT_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 | } |
121 | EXPORT_SYMBOL(xfrm6_prepare_output); | 121 | EXPORT_SYMBOL(xfrm6_prepare_output); |
122 | 122 | ||
123 | int xfrm6_output_finish(struct sk_buff *skb) | 123 | int 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 | ||
134 | static int __xfrm6_output(struct sk_buff *skb) | 134 | static 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 | ||
168 | int xfrm6_output(struct sock *sk, struct sk_buff *skb) | 169 | int 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 | } |