diff options
Diffstat (limited to 'net/ipv6/ip6_tunnel.c')
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 48 |
1 files changed, 24 insertions, 24 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 72485a3ac9fd..511a6c416887 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -82,12 +82,10 @@ static void ip6_tnl_dev_setup(struct net_device *dev); | |||
82 | 82 | ||
83 | static int ip6_tnl_net_id; | 83 | static int ip6_tnl_net_id; |
84 | struct ip6_tnl_net { | 84 | struct ip6_tnl_net { |
85 | /* the IPv6 tunnel fallback device */ | ||
86 | struct net_device *fb_tnl_dev; | ||
85 | }; | 87 | }; |
86 | 88 | ||
87 | /* the IPv6 tunnel fallback device */ | ||
88 | static struct net_device *ip6_fb_tnl_dev; | ||
89 | |||
90 | |||
91 | /* lists for storing tunnels in use */ | 89 | /* lists for storing tunnels in use */ |
92 | static struct ip6_tnl *tnls_r_l[HASH_SIZE]; | 90 | static struct ip6_tnl *tnls_r_l[HASH_SIZE]; |
93 | static struct ip6_tnl *tnls_wc[1]; | 91 | static struct ip6_tnl *tnls_wc[1]; |
@@ -314,7 +312,7 @@ ip6_tnl_dev_uninit(struct net_device *dev) | |||
314 | struct net *net = dev_net(dev); | 312 | struct net *net = dev_net(dev); |
315 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 313 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
316 | 314 | ||
317 | if (dev == ip6_fb_tnl_dev) { | 315 | if (dev == ip6n->fb_tnl_dev) { |
318 | write_lock_bh(&ip6_tnl_lock); | 316 | write_lock_bh(&ip6_tnl_lock); |
319 | tnls_wc[0] = NULL; | 317 | tnls_wc[0] = NULL; |
320 | write_unlock_bh(&ip6_tnl_lock); | 318 | write_unlock_bh(&ip6_tnl_lock); |
@@ -1209,7 +1207,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1209 | 1207 | ||
1210 | switch (cmd) { | 1208 | switch (cmd) { |
1211 | case SIOCGETTUNNEL: | 1209 | case SIOCGETTUNNEL: |
1212 | if (dev == ip6_fb_tnl_dev) { | 1210 | if (dev == ip6n->fb_tnl_dev) { |
1213 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) { | 1211 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) { |
1214 | err = -EFAULT; | 1212 | err = -EFAULT; |
1215 | break; | 1213 | break; |
@@ -1236,7 +1234,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1236 | p.proto != 0) | 1234 | p.proto != 0) |
1237 | break; | 1235 | break; |
1238 | t = ip6_tnl_locate(net, &p, cmd == SIOCADDTUNNEL); | 1236 | t = ip6_tnl_locate(net, &p, cmd == SIOCADDTUNNEL); |
1239 | if (dev != ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) { | 1237 | if (dev != ip6n->fb_tnl_dev && cmd == SIOCCHGTUNNEL) { |
1240 | if (t != NULL) { | 1238 | if (t != NULL) { |
1241 | if (t->dev != dev) { | 1239 | if (t->dev != dev) { |
1242 | err = -EEXIST; | 1240 | err = -EEXIST; |
@@ -1263,7 +1261,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1263 | if (!capable(CAP_NET_ADMIN)) | 1261 | if (!capable(CAP_NET_ADMIN)) |
1264 | break; | 1262 | break; |
1265 | 1263 | ||
1266 | if (dev == ip6_fb_tnl_dev) { | 1264 | if (dev == ip6n->fb_tnl_dev) { |
1267 | err = -EFAULT; | 1265 | err = -EFAULT; |
1268 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) | 1266 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) |
1269 | break; | 1267 | break; |
@@ -1271,7 +1269,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1271 | if ((t = ip6_tnl_locate(net, &p, 0)) == NULL) | 1269 | if ((t = ip6_tnl_locate(net, &p, 0)) == NULL) |
1272 | break; | 1270 | break; |
1273 | err = -EPERM; | 1271 | err = -EPERM; |
1274 | if (t->dev == ip6_fb_tnl_dev) | 1272 | if (t->dev == ip6n->fb_tnl_dev) |
1275 | break; | 1273 | break; |
1276 | dev = t->dev; | 1274 | dev = t->dev; |
1277 | } | 1275 | } |
@@ -1413,8 +1411,25 @@ static int ip6_tnl_init_net(struct net *net) | |||
1413 | if (err < 0) | 1411 | if (err < 0) |
1414 | goto err_assign; | 1412 | goto err_assign; |
1415 | 1413 | ||
1414 | err = -ENOMEM; | ||
1415 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", | ||
1416 | ip6_tnl_dev_setup); | ||
1417 | |||
1418 | if (!ip6n->fb_tnl_dev) | ||
1419 | goto err_alloc_dev; | ||
1420 | |||
1421 | ip6n->fb_tnl_dev->init = ip6_fb_tnl_dev_init; | ||
1422 | dev_net_set(ip6n->fb_tnl_dev, net); | ||
1423 | |||
1424 | err = register_netdev(ip6n->fb_tnl_dev); | ||
1425 | if (err < 0) | ||
1426 | goto err_register; | ||
1416 | return 0; | 1427 | return 0; |
1417 | 1428 | ||
1429 | err_register: | ||
1430 | free_netdev(ip6n->fb_tnl_dev); | ||
1431 | err_alloc_dev: | ||
1432 | /* nothing */ | ||
1418 | err_assign: | 1433 | err_assign: |
1419 | kfree(ip6n); | 1434 | kfree(ip6n); |
1420 | err_alloc: | 1435 | err_alloc: |
@@ -1455,27 +1470,12 @@ static int __init ip6_tunnel_init(void) | |||
1455 | err = -EAGAIN; | 1470 | err = -EAGAIN; |
1456 | goto unreg_ip4ip6; | 1471 | goto unreg_ip4ip6; |
1457 | } | 1472 | } |
1458 | ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", | ||
1459 | ip6_tnl_dev_setup); | ||
1460 | |||
1461 | if (!ip6_fb_tnl_dev) { | ||
1462 | err = -ENOMEM; | ||
1463 | goto fail; | ||
1464 | } | ||
1465 | ip6_fb_tnl_dev->init = ip6_fb_tnl_dev_init; | ||
1466 | |||
1467 | if ((err = register_netdev(ip6_fb_tnl_dev))) { | ||
1468 | free_netdev(ip6_fb_tnl_dev); | ||
1469 | goto fail; | ||
1470 | } | ||
1471 | 1473 | ||
1472 | err = register_pernet_gen_device(&ip6_tnl_net_id, &ip6_tnl_net_ops); | 1474 | err = register_pernet_gen_device(&ip6_tnl_net_id, &ip6_tnl_net_ops); |
1473 | if (err < 0) | 1475 | if (err < 0) |
1474 | goto err_pernet; | 1476 | goto err_pernet; |
1475 | return 0; | 1477 | return 0; |
1476 | err_pernet: | 1478 | err_pernet: |
1477 | unregister_netdevice(ip6_fb_tnl_dev); | ||
1478 | fail: | ||
1479 | xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); | 1479 | xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); |
1480 | unreg_ip4ip6: | 1480 | unreg_ip4ip6: |
1481 | xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); | 1481 | xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); |