@ -63,6 +63,7 @@
# include <linux/virtio_net.h>
# include <net/net_namespace.h>
# include <net/netns/generic.h>
# include <net/rtnetlink.h>
# include <asm/system.h>
# include <asm/uaccess.h>
@ -812,6 +813,22 @@ static void tun_setup(struct net_device *dev)
dev - > destructor = free_netdev ;
}
/* Trivial set of netlink ops to allow deleting tun or tap
* device with netlink .
*/
static int tun_validate ( struct nlattr * tb [ ] , struct nlattr * data [ ] )
{
return - EINVAL ;
}
static struct rtnl_link_ops tun_link_ops __read_mostly = {
. kind = DRV_NAME ,
. priv_size = sizeof ( struct tun_struct ) ,
. setup = tun_setup ,
. validate = tun_validate ,
} ;
static int tun_set_iff ( struct net * net , struct file * file , struct ifreq * ifr )
{
struct tun_struct * tun ;
@ -861,6 +878,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
return - ENOMEM ;
dev_net_set ( dev , net ) ;
dev - > rtnl_link_ops = & tun_link_ops ;
tun = netdev_priv ( dev ) ;
tun - > dev = dev ;
@ -1317,29 +1335,6 @@ static const struct ethtool_ops tun_ethtool_ops = {
. set_rx_csum = tun_set_rx_csum
} ;
static int tun_init_net ( struct net * net )
{
return 0 ;
}
static void tun_exit_net ( struct net * net )
{
struct net_device * dev , * next ;
rtnl_lock ( ) ;
for_each_netdev_safe ( net , dev , next ) {
if ( dev - > ethtool_ops ! = & tun_ethtool_ops )
continue ;
DBG ( KERN_INFO " %s cleaned up \n " , dev - > name ) ;
unregister_netdevice ( dev ) ;
}
rtnl_unlock ( ) ;
}
static struct pernet_operations tun_net_ops = {
. init = tun_init_net ,
. exit = tun_exit_net ,
} ;
static int __init tun_init ( void )
{
@ -1348,10 +1343,10 @@ static int __init tun_init(void)
printk ( KERN_INFO " tun: %s, %s \n " , DRV_DESCRIPTION , DRV_VERSION ) ;
printk ( KERN_INFO " tun: %s \n " , DRV_COPYRIGHT ) ;
ret = register_pernet_device ( & tun_net _ops ) ;
ret = rtnl_link_register ( & tun_link _ops ) ;
if ( ret ) {
printk ( KERN_ERR " tun: Can't register pernet ops \n " ) ;
goto err_pernet ;
printk ( KERN_ERR " tun: Can't register link_ ops \n " ) ;
goto err_linkops ;
}
ret = misc_register ( & tun_miscdev ) ;
@ -1359,18 +1354,17 @@ static int __init tun_init(void)
printk ( KERN_ERR " tun: Can't register misc device %d \n " , TUN_MINOR ) ;
goto err_misc ;
}
return 0 ;
return 0 ;
err_misc :
unregister_pernet_device ( & tun_net _ops ) ;
err_pernet :
rtnl_link_ unregister( & tun_link _ops ) ;
err_linkops :
return ret ;
}
static void tun_cleanup ( void )
{
misc_deregister ( & tun_miscdev ) ;
unregister_pernet_device ( & tun_net _ops ) ;
rtnl_link_ unregister( & tun_link _ops ) ;
}
module_init ( tun_init ) ;