aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/tun.c56
1 files changed, 25 insertions, 31 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 97b050015f5e..e9bcbdfe015a 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -63,6 +63,7 @@
63#include <linux/virtio_net.h> 63#include <linux/virtio_net.h>
64#include <net/net_namespace.h> 64#include <net/net_namespace.h>
65#include <net/netns/generic.h> 65#include <net/netns/generic.h>
66#include <net/rtnetlink.h>
66 67
67#include <asm/system.h> 68#include <asm/system.h>
68#include <asm/uaccess.h> 69#include <asm/uaccess.h>
@@ -812,6 +813,22 @@ static void tun_setup(struct net_device *dev)
812 dev->destructor = free_netdev; 813 dev->destructor = free_netdev;
813} 814}
814 815
816/* Trivial set of netlink ops to allow deleting tun or tap
817 * device with netlink.
818 */
819static int tun_validate(struct nlattr *tb[], struct nlattr *data[])
820{
821 return -EINVAL;
822}
823
824static struct rtnl_link_ops tun_link_ops __read_mostly = {
825 .kind = DRV_NAME,
826 .priv_size = sizeof(struct tun_struct),
827 .setup = tun_setup,
828 .validate = tun_validate,
829};
830
831
815static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) 832static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
816{ 833{
817 struct tun_struct *tun; 834 struct tun_struct *tun;
@@ -861,6 +878,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
861 return -ENOMEM; 878 return -ENOMEM;
862 879
863 dev_net_set(dev, net); 880 dev_net_set(dev, net);
881 dev->rtnl_link_ops = &tun_link_ops;
864 882
865 tun = netdev_priv(dev); 883 tun = netdev_priv(dev);
866 tun->dev = dev; 884 tun->dev = dev;
@@ -1317,29 +1335,6 @@ static const struct ethtool_ops tun_ethtool_ops = {
1317 .set_rx_csum = tun_set_rx_csum 1335 .set_rx_csum = tun_set_rx_csum
1318}; 1336};
1319 1337
1320static int tun_init_net(struct net *net)
1321{
1322 return 0;
1323}
1324
1325static void tun_exit_net(struct net *net)
1326{
1327 struct net_device *dev, *next;
1328
1329 rtnl_lock();
1330 for_each_netdev_safe(net, dev, next) {
1331 if (dev->ethtool_ops != &tun_ethtool_ops)
1332 continue;
1333 DBG(KERN_INFO "%s cleaned up\n", dev->name);
1334 unregister_netdevice(dev);
1335 }
1336 rtnl_unlock();
1337}
1338
1339static struct pernet_operations tun_net_ops = {
1340 .init = tun_init_net,
1341 .exit = tun_exit_net,
1342};
1343 1338
1344static int __init tun_init(void) 1339static int __init tun_init(void)
1345{ 1340{
@@ -1348,10 +1343,10 @@ static int __init tun_init(void)
1348 printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); 1343 printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
1349 printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT); 1344 printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
1350 1345
1351 ret = register_pernet_device(&tun_net_ops); 1346 ret = rtnl_link_register(&tun_link_ops);
1352 if (ret) { 1347 if (ret) {
1353 printk(KERN_ERR "tun: Can't register pernet ops\n"); 1348 printk(KERN_ERR "tun: Can't register link_ops\n");
1354 goto err_pernet; 1349 goto err_linkops;
1355 } 1350 }
1356 1351
1357 ret = misc_register(&tun_miscdev); 1352 ret = misc_register(&tun_miscdev);
@@ -1359,18 +1354,17 @@ static int __init tun_init(void)
1359 printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR); 1354 printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
1360 goto err_misc; 1355 goto err_misc;
1361 } 1356 }
1362 return 0; 1357 return 0;
1363
1364err_misc: 1358err_misc:
1365 unregister_pernet_device(&tun_net_ops); 1359 rtnl_link_unregister(&tun_link_ops);
1366err_pernet: 1360err_linkops:
1367 return ret; 1361 return ret;
1368} 1362}
1369 1363
1370static void tun_cleanup(void) 1364static void tun_cleanup(void)
1371{ 1365{
1372 misc_deregister(&tun_miscdev); 1366 misc_deregister(&tun_miscdev);
1373 unregister_pernet_device(&tun_net_ops); 1367 rtnl_link_unregister(&tun_link_ops);
1374} 1368}
1375 1369
1376module_init(tun_init); 1370module_init(tun_init);