@ -1971,7 +1971,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device * rdev = info - > user_ptr [ 0 ] ;
struct vif_params params ;
struct net_device * dev ;
struct wireless_dev * w dev;
int err ;
enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED ;
u32 flags ;
@ -2001,16 +2001,14 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
err = parse_monitor_flags ( type = = NL80211_IFTYPE_MONITOR ?
info - > attrs [ NL80211_ATTR_MNTR_FLAGS ] : NULL ,
& flags ) ;
dev = rdev - > ops - > add_virtual_intf ( & rdev - > wiphy ,
w dev = rdev - > ops - > add_virtual_intf ( & rdev - > wiphy ,
nla_data ( info - > attrs [ NL80211_ATTR_IFNAME ] ) ,
type , err ? NULL : & flags , & params ) ;
if ( IS_ERR ( dev ) )
return PTR_ERR ( dev ) ;
if ( IS_ERR ( w dev) )
return PTR_ERR ( w dev) ;
if ( type = = NL80211_IFTYPE_MESH_POINT & &
info - > attrs [ NL80211_ATTR_MESH_ID ] ) {
struct wireless_dev * wdev = dev - > ieee80211_ptr ;
wdev_lock ( wdev ) ;
BUILD_BUG_ON ( IEEE80211_MAX_SSID_LEN ! =
IEEE80211_MAX_MESH_ID_LEN ) ;
@ -2027,12 +2025,22 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
static int nl80211_del_interface ( struct sk_buff * skb , struct genl_info * info )
{
struct cfg80211_registered_device * rdev = info - > user_ptr [ 0 ] ;
struct net_device * dev = info - > user_ptr [ 1 ] ;
struct wireless_dev * w dev = info - > user_ptr [ 1 ] ;
if ( ! rdev - > ops - > del_virtual_intf )
return - EOPNOTSUPP ;
return rdev - > ops - > del_virtual_intf ( & rdev - > wiphy , dev ) ;
/*
* If we remove a wireless device without a netdev then clear
* user_ptr [ 1 ] so that nl80211_post_doit won ' t dereference it
* to check if it needs to do dev_put ( ) . Otherwise it crashes
* since the wdev has been freed , unlike with a netdev where
* we need the dev_put ( ) for the netdev to really be freed .
*/
if ( ! wdev - > netdev )
info - > user_ptr [ 1 ] = NULL ;
return rdev - > ops - > del_virtual_intf ( & rdev - > wiphy , wdev ) ;
}
static int nl80211_set_noack_map ( struct sk_buff * skb , struct genl_info * info )
@ -6874,7 +6882,7 @@ static struct genl_ops nl80211_ops[] = {
. doit = nl80211_del_interface ,
. policy = nl80211_policy ,
. flags = GENL_ADMIN_PERM ,
. internal_flags = NL80211_FLAG_NEED_NET DEV |
. internal_flags = NL80211_FLAG_NEED_W DEV |
NL80211_FLAG_NEED_RTNL ,
} ,
{