2007-05-05 22:45:53 +04:00
/*
* mac80211 configuration hooks for cfg80211
*
* Copyright 2006 Johannes Berg < johannes @ sipsolutions . net >
*
* This file is GPLv2 as found in COPYING .
*/
# include <linux/nl80211.h>
# include <linux/rtnetlink.h>
2007-09-17 22:56:21 +04:00
# include <net/net_namespace.h>
2007-05-05 22:45:53 +04:00
# include <net/cfg80211.h>
# include "ieee80211_i.h"
2007-09-19 01:29:21 +04:00
# include "cfg.h"
2007-05-05 22:45:53 +04:00
2007-09-28 23:52:27 +04:00
static enum ieee80211_if_types
nl80211_type_to_mac80211_type ( enum nl80211_iftype type )
{
switch ( type ) {
case NL80211_IFTYPE_UNSPECIFIED :
return IEEE80211_IF_TYPE_STA ;
case NL80211_IFTYPE_ADHOC :
return IEEE80211_IF_TYPE_IBSS ;
case NL80211_IFTYPE_STATION :
return IEEE80211_IF_TYPE_STA ;
case NL80211_IFTYPE_MONITOR :
return IEEE80211_IF_TYPE_MNTR ;
default :
return IEEE80211_IF_TYPE_INVALID ;
}
}
2007-05-05 22:45:53 +04:00
static int ieee80211_add_iface ( struct wiphy * wiphy , char * name ,
2007-09-20 21:09:35 +04:00
enum nl80211_iftype type )
2007-05-05 22:45:53 +04:00
{
struct ieee80211_local * local = wiphy_priv ( wiphy ) ;
2007-09-28 23:52:27 +04:00
enum ieee80211_if_types itype ;
2007-05-05 22:45:53 +04:00
if ( unlikely ( local - > reg_state ! = IEEE80211_DEV_REGISTERED ) )
return - ENODEV ;
2007-09-28 23:52:27 +04:00
itype = nl80211_type_to_mac80211_type ( type ) ;
if ( itype = = IEEE80211_IF_TYPE_INVALID )
2007-05-05 22:45:53 +04:00
return - EINVAL ;
return ieee80211_if_add ( local - > mdev , name , NULL , itype ) ;
}
static int ieee80211_del_iface ( struct wiphy * wiphy , int ifindex )
{
struct ieee80211_local * local = wiphy_priv ( wiphy ) ;
struct net_device * dev ;
char * name ;
if ( unlikely ( local - > reg_state ! = IEEE80211_DEV_REGISTERED ) )
return - ENODEV ;
2007-09-28 23:52:27 +04:00
/* we're under RTNL */
dev = __dev_get_by_index ( & init_net , ifindex ) ;
2007-05-05 22:45:53 +04:00
if ( ! dev )
return 0 ;
name = dev - > name ;
return ieee80211_if_remove ( local - > mdev , name , - 1 ) ;
}
2007-09-28 23:52:27 +04:00
static int ieee80211_change_iface ( struct wiphy * wiphy , int ifindex ,
enum nl80211_iftype type )
{
struct ieee80211_local * local = wiphy_priv ( wiphy ) ;
struct net_device * dev ;
enum ieee80211_if_types itype ;
struct ieee80211_sub_if_data * sdata ;
if ( unlikely ( local - > reg_state ! = IEEE80211_DEV_REGISTERED ) )
return - ENODEV ;
/* we're under RTNL */
dev = __dev_get_by_index ( & init_net , ifindex ) ;
if ( ! dev )
return - ENODEV ;
if ( netif_running ( dev ) )
return - EBUSY ;
itype = nl80211_type_to_mac80211_type ( type ) ;
if ( itype = = IEEE80211_IF_TYPE_INVALID )
return - EINVAL ;
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
if ( sdata - > type = = IEEE80211_IF_TYPE_VLAN )
return - EOPNOTSUPP ;
ieee80211_if_reinit ( dev ) ;
ieee80211_if_set_type ( dev , itype ) ;
return 0 ;
}
2007-05-05 22:45:53 +04:00
struct cfg80211_ops mac80211_config_ops = {
. add_virtual_intf = ieee80211_add_iface ,
. del_virtual_intf = ieee80211_del_iface ,
2007-09-28 23:52:27 +04:00
. change_virtual_intf = ieee80211_change_iface ,
2007-05-05 22:45:53 +04:00
} ;