aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c65
-rw-r--r--net/ipv6/ip6mr.c4
-rw-r--r--net/ipv6/mcast.c1
-rw-r--r--net/ipv6/ndisc.c5
-rw-r--r--net/ipv6/route.c2
-rw-r--r--net/ipv6/tcp_ipv6.c2
-rw-r--r--net/ipv6/xfrm6_mode_beet.c6
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c6
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
505static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) 509static 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
4303static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) 4317static 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)
80static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) 80static 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)
63static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) 63static 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
89out: 87out: