diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/tun.c | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index f359d6082c38..1e655ea63102 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/if_ether.h> | 62 | #include <linux/if_ether.h> |
63 | #include <linux/if_tun.h> | 63 | #include <linux/if_tun.h> |
64 | #include <linux/crc32.h> | 64 | #include <linux/crc32.h> |
65 | #include <linux/nsproxy.h> | ||
65 | #include <net/net_namespace.h> | 66 | #include <net/net_namespace.h> |
66 | #include <net/netns/generic.h> | 67 | #include <net/netns/generic.h> |
67 | 68 | ||
@@ -112,7 +113,6 @@ struct tun_net { | |||
112 | struct list_head dev_list; | 113 | struct list_head dev_list; |
113 | }; | 114 | }; |
114 | 115 | ||
115 | static LIST_HEAD(tun_dev_list); | ||
116 | static const struct ethtool_ops tun_ethtool_ops; | 116 | static const struct ethtool_ops tun_ethtool_ops; |
117 | 117 | ||
118 | /* Net device open. */ | 118 | /* Net device open. */ |
@@ -479,12 +479,12 @@ static void tun_setup(struct net_device *dev) | |||
479 | dev->destructor = free_netdev; | 479 | dev->destructor = free_netdev; |
480 | } | 480 | } |
481 | 481 | ||
482 | static struct tun_struct *tun_get_by_name(const char *name) | 482 | static struct tun_struct *tun_get_by_name(struct tun_net *tn, const char *name) |
483 | { | 483 | { |
484 | struct tun_struct *tun; | 484 | struct tun_struct *tun; |
485 | 485 | ||
486 | ASSERT_RTNL(); | 486 | ASSERT_RTNL(); |
487 | list_for_each_entry(tun, &tun_dev_list, list) { | 487 | list_for_each_entry(tun, &tn->dev_list, list) { |
488 | if (!strncmp(tun->dev->name, name, IFNAMSIZ)) | 488 | if (!strncmp(tun->dev->name, name, IFNAMSIZ)) |
489 | return tun; | 489 | return tun; |
490 | } | 490 | } |
@@ -492,13 +492,15 @@ static struct tun_struct *tun_get_by_name(const char *name) | |||
492 | return NULL; | 492 | return NULL; |
493 | } | 493 | } |
494 | 494 | ||
495 | static int tun_set_iff(struct file *file, struct ifreq *ifr) | 495 | static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) |
496 | { | 496 | { |
497 | struct tun_net *tn; | ||
497 | struct tun_struct *tun; | 498 | struct tun_struct *tun; |
498 | struct net_device *dev; | 499 | struct net_device *dev; |
499 | int err; | 500 | int err; |
500 | 501 | ||
501 | tun = tun_get_by_name(ifr->ifr_name); | 502 | tn = net_generic(net, tun_net_id); |
503 | tun = tun_get_by_name(tn, ifr->ifr_name); | ||
502 | if (tun) { | 504 | if (tun) { |
503 | if (tun->attached) | 505 | if (tun->attached) |
504 | return -EBUSY; | 506 | return -EBUSY; |
@@ -511,7 +513,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr) | |||
511 | !capable(CAP_NET_ADMIN)) | 513 | !capable(CAP_NET_ADMIN)) |
512 | return -EPERM; | 514 | return -EPERM; |
513 | } | 515 | } |
514 | else if (__dev_get_by_name(&init_net, ifr->ifr_name)) | 516 | else if (__dev_get_by_name(net, ifr->ifr_name)) |
515 | return -EINVAL; | 517 | return -EINVAL; |
516 | else { | 518 | else { |
517 | char *name; | 519 | char *name; |
@@ -564,7 +566,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr) | |||
564 | if (err < 0) | 566 | if (err < 0) |
565 | goto err_free_dev; | 567 | goto err_free_dev; |
566 | 568 | ||
567 | list_add(&tun->list, &tun_dev_list); | 569 | list_add(&tun->list, &tn->dev_list); |
568 | } | 570 | } |
569 | 571 | ||
570 | DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); | 572 | DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); |
@@ -609,7 +611,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, | |||
609 | ifr.ifr_name[IFNAMSIZ-1] = '\0'; | 611 | ifr.ifr_name[IFNAMSIZ-1] = '\0'; |
610 | 612 | ||
611 | rtnl_lock(); | 613 | rtnl_lock(); |
612 | err = tun_set_iff(file, &ifr); | 614 | err = tun_set_iff(current->nsproxy->net_ns, file, &ifr); |
613 | rtnl_unlock(); | 615 | rtnl_unlock(); |
614 | 616 | ||
615 | if (err) | 617 | if (err) |
@@ -936,8 +938,17 @@ static int tun_init_net(struct net *net) | |||
936 | static void tun_exit_net(struct net *net) | 938 | static void tun_exit_net(struct net *net) |
937 | { | 939 | { |
938 | struct tun_net *tn; | 940 | struct tun_net *tn; |
941 | struct tun_struct *tun, *nxt; | ||
939 | 942 | ||
940 | tn = net_generic(net, tun_net_id); | 943 | tn = net_generic(net, tun_net_id); |
944 | |||
945 | rtnl_lock(); | ||
946 | list_for_each_entry_safe(tun, nxt, &tn->dev_list, list) { | ||
947 | DBG(KERN_INFO "%s cleaned up\n", tun->dev->name); | ||
948 | unregister_netdevice(tun->dev); | ||
949 | } | ||
950 | rtnl_unlock(); | ||
951 | |||
941 | kfree(tn); | 952 | kfree(tn); |
942 | } | 953 | } |
943 | 954 | ||
@@ -974,17 +985,7 @@ err_pernet: | |||
974 | 985 | ||
975 | static void tun_cleanup(void) | 986 | static void tun_cleanup(void) |
976 | { | 987 | { |
977 | struct tun_struct *tun, *nxt; | ||
978 | |||
979 | misc_deregister(&tun_miscdev); | 988 | misc_deregister(&tun_miscdev); |
980 | |||
981 | rtnl_lock(); | ||
982 | list_for_each_entry_safe(tun, nxt, &tun_dev_list, list) { | ||
983 | DBG(KERN_INFO "%s cleaned up\n", tun->dev->name); | ||
984 | unregister_netdevice(tun->dev); | ||
985 | } | ||
986 | rtnl_unlock(); | ||
987 | |||
988 | unregister_pernet_gen_device(tun_net_id, &tun_net_ops); | 989 | unregister_pernet_gen_device(tun_net_id, &tun_net_ops); |
989 | } | 990 | } |
990 | 991 | ||