diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 65 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 4 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 1 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 5 | ||||
-rw-r--r-- | net/ipv6/route.c | 2 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_beet.c | 6 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_tunnel.c | 6 |
8 files changed, 55 insertions, 36 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a225d5ee3c2f..6b8ebc5da0e1 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -434,6 +434,10 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
434 | /* Join all-node multicast group */ | 434 | /* Join all-node multicast group */ |
435 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); | 435 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); |
436 | 436 | ||
437 | /* Join all-router multicast group if forwarding is set */ | ||
438 | if (ndev->cnf.forwarding && dev && (dev->flags & IFF_MULTICAST)) | ||
439 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); | ||
440 | |||
437 | return ndev; | 441 | return ndev; |
438 | } | 442 | } |
439 | 443 | ||
@@ -502,29 +506,31 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
502 | rcu_read_unlock(); | 506 | rcu_read_unlock(); |
503 | } | 507 | } |
504 | 508 | ||
505 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | 509 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) |
506 | { | 510 | { |
507 | struct net *net; | 511 | struct net *net; |
512 | int old; | ||
513 | |||
514 | if (!rtnl_trylock()) | ||
515 | return restart_syscall(); | ||
508 | 516 | ||
509 | net = (struct net *)table->extra2; | 517 | net = (struct net *)table->extra2; |
510 | if (p == &net->ipv6.devconf_dflt->forwarding) | 518 | old = *p; |
511 | return 0; | 519 | *p = newf; |
512 | 520 | ||
513 | if (!rtnl_trylock()) { | 521 | if (p == &net->ipv6.devconf_dflt->forwarding) { |
514 | /* Restore the original values before restarting */ | 522 | rtnl_unlock(); |
515 | *p = old; | 523 | return 0; |
516 | return restart_syscall(); | ||
517 | } | 524 | } |
518 | 525 | ||
519 | if (p == &net->ipv6.devconf_all->forwarding) { | 526 | if (p == &net->ipv6.devconf_all->forwarding) { |
520 | __s32 newf = net->ipv6.devconf_all->forwarding; | ||
521 | net->ipv6.devconf_dflt->forwarding = newf; | 527 | net->ipv6.devconf_dflt->forwarding = newf; |
522 | addrconf_forward_change(net, newf); | 528 | addrconf_forward_change(net, newf); |
523 | } else if ((!*p) ^ (!old)) | 529 | } else if ((!newf) ^ (!old)) |
524 | dev_forward_change((struct inet6_dev *)table->extra1); | 530 | dev_forward_change((struct inet6_dev *)table->extra1); |
525 | rtnl_unlock(); | 531 | rtnl_unlock(); |
526 | 532 | ||
527 | if (*p) | 533 | if (newf) |
528 | rt6_purge_dflt_routers(net); | 534 | rt6_purge_dflt_routers(net); |
529 | return 1; | 535 | return 1; |
530 | } | 536 | } |
@@ -4260,9 +4266,17 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, | |||
4260 | int *valp = ctl->data; | 4266 | int *valp = ctl->data; |
4261 | int val = *valp; | 4267 | int val = *valp; |
4262 | loff_t pos = *ppos; | 4268 | loff_t pos = *ppos; |
4269 | ctl_table lctl; | ||
4263 | int ret; | 4270 | int ret; |
4264 | 4271 | ||
4265 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); | 4272 | /* |
4273 | * ctl->data points to idev->cnf.forwarding, we should | ||
4274 | * not modify it until we get the rtnl lock. | ||
4275 | */ | ||
4276 | lctl = *ctl; | ||
4277 | lctl.data = &val; | ||
4278 | |||
4279 | ret = proc_dointvec(&lctl, write, buffer, lenp, ppos); | ||
4266 | 4280 | ||
4267 | if (write) | 4281 | if (write) |
4268 | ret = addrconf_fixup_forwarding(ctl, valp, val); | 4282 | ret = addrconf_fixup_forwarding(ctl, valp, val); |
@@ -4300,26 +4314,27 @@ static void addrconf_disable_change(struct net *net, __s32 newf) | |||
4300 | rcu_read_unlock(); | 4314 | rcu_read_unlock(); |
4301 | } | 4315 | } |
4302 | 4316 | ||
4303 | static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) | 4317 | static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf) |
4304 | { | 4318 | { |
4305 | struct net *net; | 4319 | struct net *net; |
4320 | int old; | ||
4321 | |||
4322 | if (!rtnl_trylock()) | ||
4323 | return restart_syscall(); | ||
4306 | 4324 | ||
4307 | net = (struct net *)table->extra2; | 4325 | net = (struct net *)table->extra2; |
4326 | old = *p; | ||
4327 | *p = newf; | ||
4308 | 4328 | ||
4309 | if (p == &net->ipv6.devconf_dflt->disable_ipv6) | 4329 | if (p == &net->ipv6.devconf_dflt->disable_ipv6) { |
4330 | rtnl_unlock(); | ||
4310 | return 0; | 4331 | return 0; |
4311 | |||
4312 | if (!rtnl_trylock()) { | ||
4313 | /* Restore the original values before restarting */ | ||
4314 | *p = old; | ||
4315 | return restart_syscall(); | ||
4316 | } | 4332 | } |
4317 | 4333 | ||
4318 | if (p == &net->ipv6.devconf_all->disable_ipv6) { | 4334 | if (p == &net->ipv6.devconf_all->disable_ipv6) { |
4319 | __s32 newf = net->ipv6.devconf_all->disable_ipv6; | ||
4320 | net->ipv6.devconf_dflt->disable_ipv6 = newf; | 4335 | net->ipv6.devconf_dflt->disable_ipv6 = newf; |
4321 | addrconf_disable_change(net, newf); | 4336 | addrconf_disable_change(net, newf); |
4322 | } else if ((!*p) ^ (!old)) | 4337 | } else if ((!newf) ^ (!old)) |
4323 | dev_disable_change((struct inet6_dev *)table->extra1); | 4338 | dev_disable_change((struct inet6_dev *)table->extra1); |
4324 | 4339 | ||
4325 | rtnl_unlock(); | 4340 | rtnl_unlock(); |
@@ -4333,9 +4348,17 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write, | |||
4333 | int *valp = ctl->data; | 4348 | int *valp = ctl->data; |
4334 | int val = *valp; | 4349 | int val = *valp; |
4335 | loff_t pos = *ppos; | 4350 | loff_t pos = *ppos; |
4351 | ctl_table lctl; | ||
4336 | int ret; | 4352 | int ret; |
4337 | 4353 | ||
4338 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); | 4354 | /* |
4355 | * ctl->data points to idev->cnf.disable_ipv6, we should | ||
4356 | * not modify it until we get the rtnl lock. | ||
4357 | */ | ||
4358 | lctl = *ctl; | ||
4359 | lctl.data = &val; | ||
4360 | |||
4361 | ret = proc_dointvec(&lctl, write, buffer, lenp, ppos); | ||
4339 | 4362 | ||
4340 | if (write) | 4363 | if (write) |
4341 | ret = addrconf_disable_ipv6(ctl, valp, val); | 4364 | ret = addrconf_disable_ipv6(ctl, valp, val); |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index c7e95c8c579f..5aa3981a3922 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1926,8 +1926,10 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt, | |||
1926 | }; | 1926 | }; |
1927 | 1927 | ||
1928 | dst = ip6_route_output(net, NULL, &fl6); | 1928 | dst = ip6_route_output(net, NULL, &fl6); |
1929 | if (!dst) | 1929 | if (dst->error) { |
1930 | dst_release(dst); | ||
1930 | goto out_free; | 1931 | goto out_free; |
1932 | } | ||
1931 | 1933 | ||
1932 | skb_dst_drop(skb); | 1934 | skb_dst_drop(skb); |
1933 | skb_dst_set(skb, dst); | 1935 | skb_dst_set(skb, dst); |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index b853f06cc148..16c33e308121 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -257,7 +257,6 @@ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, | |||
257 | 257 | ||
258 | if (rt) { | 258 | if (rt) { |
259 | dev = rt->dst.dev; | 259 | dev = rt->dst.dev; |
260 | dev_hold(dev); | ||
261 | dst_release(&rt->dst); | 260 | dst_release(&rt->dst); |
262 | } | 261 | } |
263 | } else | 262 | } else |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index d8f02ef88e59..c964958ac470 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1545,9 +1545,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1545 | &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); | 1545 | &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); |
1546 | 1546 | ||
1547 | dst = ip6_route_output(net, NULL, &fl6); | 1547 | dst = ip6_route_output(net, NULL, &fl6); |
1548 | if (dst == NULL) | 1548 | if (dst->error) { |
1549 | dst_release(dst); | ||
1549 | return; | 1550 | return; |
1550 | 1551 | } | |
1551 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | 1552 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); |
1552 | if (IS_ERR(dst)) | 1553 | if (IS_ERR(dst)) |
1553 | return; | 1554 | return; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8c2e3ab58f2a..22b766407de1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1077,7 +1077,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1077 | struct net *net = dev_net(dev); | 1077 | struct net *net = dev_net(dev); |
1078 | 1078 | ||
1079 | if (unlikely(!idev)) | 1079 | if (unlikely(!idev)) |
1080 | return NULL; | 1080 | return ERR_PTR(-ENODEV); |
1081 | 1081 | ||
1082 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); | 1082 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); |
1083 | if (unlikely(!rt)) { | 1083 | if (unlikely(!rt)) { |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 906c7ca43542..3edd05ae4388 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1083,7 +1083,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1083 | 1083 | ||
1084 | #ifdef CONFIG_TCP_MD5SIG | 1084 | #ifdef CONFIG_TCP_MD5SIG |
1085 | if (sk) | 1085 | if (sk) |
1086 | key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); | 1086 | key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr); |
1087 | #endif | 1087 | #endif |
1088 | 1088 | ||
1089 | if (th->ack) | 1089 | if (th->ack) |
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index a81ce9450750..9949a356d62c 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c | |||
@@ -80,7 +80,6 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
80 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | 80 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) |
81 | { | 81 | { |
82 | struct ipv6hdr *ip6h; | 82 | struct ipv6hdr *ip6h; |
83 | const unsigned char *old_mac; | ||
84 | int size = sizeof(struct ipv6hdr); | 83 | int size = sizeof(struct ipv6hdr); |
85 | int err; | 84 | int err; |
86 | 85 | ||
@@ -90,10 +89,7 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | |||
90 | 89 | ||
91 | __skb_push(skb, size); | 90 | __skb_push(skb, size); |
92 | skb_reset_network_header(skb); | 91 | skb_reset_network_header(skb); |
93 | 92 | skb_mac_header_rebuild(skb); | |
94 | old_mac = skb_mac_header(skb); | ||
95 | skb_set_mac_header(skb, -skb->mac_len); | ||
96 | memmove(skb_mac_header(skb), old_mac, skb->mac_len); | ||
97 | 93 | ||
98 | xfrm6_beet_make_header(skb); | 94 | xfrm6_beet_make_header(skb); |
99 | 95 | ||
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 261e6e6f487e..9f2095b19ad0 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -63,7 +63,6 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
63 | static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | 63 | static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
64 | { | 64 | { |
65 | int err = -EINVAL; | 65 | int err = -EINVAL; |
66 | const unsigned char *old_mac; | ||
67 | 66 | ||
68 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) | 67 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) |
69 | goto out; | 68 | goto out; |
@@ -80,10 +79,9 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | |||
80 | if (!(x->props.flags & XFRM_STATE_NOECN)) | 79 | if (!(x->props.flags & XFRM_STATE_NOECN)) |
81 | ipip6_ecn_decapsulate(skb); | 80 | ipip6_ecn_decapsulate(skb); |
82 | 81 | ||
83 | old_mac = skb_mac_header(skb); | ||
84 | skb_set_mac_header(skb, -skb->mac_len); | ||
85 | memmove(skb_mac_header(skb), old_mac, skb->mac_len); | ||
86 | skb_reset_network_header(skb); | 82 | skb_reset_network_header(skb); |
83 | skb_mac_header_rebuild(skb); | ||
84 | |||
87 | err = 0; | 85 | err = 0; |
88 | 86 | ||
89 | out: | 87 | out: |