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 | } |
