diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ip6_gre.c | 9 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 39 | ||||
-rw-r--r-- | net/ipv6/route.c | 5 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 3 |
4 files changed, 37 insertions, 19 deletions
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index b5e6cc1d4a73..a38d3ac0f18f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -1246,7 +1246,6 @@ static void ip6gre_tunnel_setup(struct net_device *dev) | |||
1246 | static int ip6gre_tunnel_init(struct net_device *dev) | 1246 | static int ip6gre_tunnel_init(struct net_device *dev) |
1247 | { | 1247 | { |
1248 | struct ip6_tnl *tunnel; | 1248 | struct ip6_tnl *tunnel; |
1249 | int i; | ||
1250 | 1249 | ||
1251 | tunnel = netdev_priv(dev); | 1250 | tunnel = netdev_priv(dev); |
1252 | 1251 | ||
@@ -1260,16 +1259,10 @@ static int ip6gre_tunnel_init(struct net_device *dev) | |||
1260 | if (ipv6_addr_any(&tunnel->parms.raddr)) | 1259 | if (ipv6_addr_any(&tunnel->parms.raddr)) |
1261 | dev->header_ops = &ip6gre_header_ops; | 1260 | dev->header_ops = &ip6gre_header_ops; |
1262 | 1261 | ||
1263 | dev->tstats = alloc_percpu(struct pcpu_sw_netstats); | 1262 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
1264 | if (!dev->tstats) | 1263 | if (!dev->tstats) |
1265 | return -ENOMEM; | 1264 | return -ENOMEM; |
1266 | 1265 | ||
1267 | for_each_possible_cpu(i) { | ||
1268 | struct pcpu_sw_netstats *ip6gre_tunnel_stats; | ||
1269 | ip6gre_tunnel_stats = per_cpu_ptr(dev->tstats, i); | ||
1270 | u64_stats_init(&ip6gre_tunnel_stats->syncp); | ||
1271 | } | ||
1272 | |||
1273 | return 0; | 1266 | return 0; |
1274 | } | 1267 | } |
1275 | 1268 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7fde1f265c90..c21777565c58 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -886,22 +886,45 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
886 | #endif | 886 | #endif |
887 | int err; | 887 | int err; |
888 | 888 | ||
889 | if (!*dst) | 889 | /* The correct way to handle this would be to do |
890 | *dst = ip6_route_output(net, sk, fl6); | 890 | * ip6_route_get_saddr, and then ip6_route_output; however, |
891 | 891 | * the route-specific preferred source forces the | |
892 | err = (*dst)->error; | 892 | * ip6_route_output call _before_ ip6_route_get_saddr. |
893 | if (err) | 893 | * |
894 | goto out_err_release; | 894 | * In source specific routing (no src=any default route), |
895 | * ip6_route_output will fail given src=any saddr, though, so | ||
896 | * that's why we try it again later. | ||
897 | */ | ||
898 | if (ipv6_addr_any(&fl6->saddr) && (!*dst || !(*dst)->error)) { | ||
899 | struct rt6_info *rt; | ||
900 | bool had_dst = *dst != NULL; | ||
895 | 901 | ||
896 | if (ipv6_addr_any(&fl6->saddr)) { | 902 | if (!had_dst) |
897 | struct rt6_info *rt = (struct rt6_info *) *dst; | 903 | *dst = ip6_route_output(net, sk, fl6); |
904 | rt = (*dst)->error ? NULL : (struct rt6_info *)*dst; | ||
898 | err = ip6_route_get_saddr(net, rt, &fl6->daddr, | 905 | err = ip6_route_get_saddr(net, rt, &fl6->daddr, |
899 | sk ? inet6_sk(sk)->srcprefs : 0, | 906 | sk ? inet6_sk(sk)->srcprefs : 0, |
900 | &fl6->saddr); | 907 | &fl6->saddr); |
901 | if (err) | 908 | if (err) |
902 | goto out_err_release; | 909 | goto out_err_release; |
910 | |||
911 | /* If we had an erroneous initial result, pretend it | ||
912 | * never existed and let the SA-enabled version take | ||
913 | * over. | ||
914 | */ | ||
915 | if (!had_dst && (*dst)->error) { | ||
916 | dst_release(*dst); | ||
917 | *dst = NULL; | ||
918 | } | ||
903 | } | 919 | } |
904 | 920 | ||
921 | if (!*dst) | ||
922 | *dst = ip6_route_output(net, sk, fl6); | ||
923 | |||
924 | err = (*dst)->error; | ||
925 | if (err) | ||
926 | goto out_err_release; | ||
927 | |||
905 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 928 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
906 | /* | 929 | /* |
907 | * Here if the dst entry we've looked up | 930 | * Here if the dst entry we've looked up |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5c48293ff062..d3588885f097 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2245,9 +2245,10 @@ int ip6_route_get_saddr(struct net *net, | |||
2245 | unsigned int prefs, | 2245 | unsigned int prefs, |
2246 | struct in6_addr *saddr) | 2246 | struct in6_addr *saddr) |
2247 | { | 2247 | { |
2248 | struct inet6_dev *idev = ip6_dst_idev((struct dst_entry *)rt); | 2248 | struct inet6_dev *idev = |
2249 | rt ? ip6_dst_idev((struct dst_entry *)rt) : NULL; | ||
2249 | int err = 0; | 2250 | int err = 0; |
2250 | if (rt->rt6i_prefsrc.plen) | 2251 | if (rt && rt->rt6i_prefsrc.plen) |
2251 | *saddr = rt->rt6i_prefsrc.addr; | 2252 | *saddr = rt->rt6i_prefsrc.addr; |
2252 | else | 2253 | else |
2253 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | 2254 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index ad51df85aa00..b6575d665568 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -946,7 +946,8 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
946 | &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb)); | 946 | &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb)); |
947 | if (req) { | 947 | if (req) { |
948 | nsk = tcp_check_req(sk, skb, req, false); | 948 | nsk = tcp_check_req(sk, skb, req, false); |
949 | reqsk_put(req); | 949 | if (!nsk) |
950 | reqsk_put(req); | ||
950 | return nsk; | 951 | return nsk; |
951 | } | 952 | } |
952 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, | 953 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, |