2007-05-05 11:45:53 -07:00
/*
* Copyright 2002 - 2005 , Instant802 Networks , Inc .
* Copyright 2005 - 2006 , Devicescape Software , Inc .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/netdevice.h>
# include <linux/types.h>
# include <linux/slab.h>
# include <linux/skbuff.h>
# include <linux/etherdevice.h>
# include <linux/if_arp.h>
# include <linux/wireless.h>
# include <net/iw_handler.h>
# include <asm/uaccess.h>
# include <net/mac80211.h>
# include "ieee80211_i.h"
2008-04-08 15:14:40 -04:00
# include "led.h"
# include "rate.h"
2007-05-05 11:45:53 -07:00
# include "wpa.h"
# include "aes_ccm.h"
2007-09-14 11:10:25 -04:00
2007-05-05 11:45:53 -07:00
static int ieee80211_set_encryption ( struct net_device * dev , u8 * sta_addr ,
2007-09-26 17:53:17 +02:00
int idx , int alg , int remove ,
int set_tx_key , const u8 * _key ,
size_t key_len )
2007-05-05 11:45:53 -07:00
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
2008-02-25 16:27:46 +01:00
struct sta_info * sta ;
2007-08-28 17:01:55 -04:00
struct ieee80211_key * key ;
2007-05-05 11:45:53 -07:00
struct ieee80211_sub_if_data * sdata ;
2008-04-08 17:56:52 +02:00
int err ;
2007-05-05 11:45:53 -07:00
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2007-09-14 11:10:25 -04:00
if ( idx < 0 | | idx > = NUM_DEFAULT_KEYS ) {
printk ( KERN_DEBUG " %s: set_encrypt - invalid idx=%d \n " ,
dev - > name , idx ) ;
return - EINVAL ;
}
2008-02-25 16:27:45 +01:00
if ( remove ) {
2008-04-08 17:56:52 +02:00
rcu_read_lock ( ) ;
err = 0 ;
2008-02-25 16:27:45 +01:00
if ( is_broadcast_ether_addr ( sta_addr ) ) {
key = sdata - > keys [ idx ] ;
} else {
sta = sta_info_get ( local , sta_addr ) ;
2008-04-08 17:56:52 +02:00
if ( ! sta ) {
err = - ENOENT ;
goto out_unlock ;
}
2008-02-25 16:27:45 +01:00
key = sta - > key ;
2007-05-05 11:45:53 -07:00
}
2008-02-25 16:27:46 +01:00
ieee80211_key_free ( key ) ;
2008-02-25 16:27:45 +01:00
} else {
key = ieee80211_key_alloc ( alg , idx , key_len , _key ) ;
if ( ! key )
return - ENOMEM ;
2008-02-25 16:27:46 +01:00
sta = NULL ;
2008-04-08 17:56:52 +02:00
err = 0 ;
rcu_read_lock ( ) ;
2008-02-25 16:27:46 +01:00
2008-02-25 16:27:45 +01:00
if ( ! is_broadcast_ether_addr ( sta_addr ) ) {
set_tx_key = 0 ;
/*
* According to the standard , the key index of a
* pairwise key must be zero . However , some AP are
* broken when it comes to WEP key indices , so we
* work around this .
*/
if ( idx ! = 0 & & alg ! = ALG_WEP ) {
2008-02-25 16:27:46 +01:00
ieee80211_key_free ( key ) ;
2008-04-08 17:56:52 +02:00
err = - EINVAL ;
goto out_unlock ;
2008-02-25 16:27:45 +01:00
}
2007-05-05 11:45:53 -07:00
2008-02-25 16:27:45 +01:00
sta = sta_info_get ( local , sta_addr ) ;
if ( ! sta ) {
2008-02-25 16:27:46 +01:00
ieee80211_key_free ( key ) ;
2008-04-08 17:56:52 +02:00
err = - ENOENT ;
goto out_unlock ;
2008-02-25 16:27:45 +01:00
}
2007-05-05 11:45:53 -07:00
}
2008-02-25 16:27:45 +01:00
ieee80211_key_link ( key , sdata , sta ) ;
2007-05-05 11:45:53 -07:00
2008-02-25 16:27:45 +01:00
if ( set_tx_key | | ( ! sta & & ! sdata - > default_key & & key ) )
ieee80211_set_default_key ( sdata , idx ) ;
}
2007-05-05 11:45:53 -07:00
2008-04-08 17:56:52 +02:00
out_unlock :
rcu_read_unlock ( ) ;
return err ;
2007-05-05 11:45:53 -07:00
}
static int ieee80211_ioctl_siwgenie ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * data , char * extra )
{
struct ieee80211_sub_if_data * sdata ;
2007-09-26 17:53:20 +02:00
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
if ( sdata - > flags & IEEE80211_SDATA_USERSPACE_MLME )
2007-05-05 11:45:53 -07:00
return - EOPNOTSUPP ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA | |
sdata - > vif . type = = IEEE80211_IF_TYPE_IBSS ) {
2007-05-05 11:45:53 -07:00
int ret = ieee80211_sta_set_extra_ie ( dev , extra , data - > length ) ;
if ( ret )
return ret ;
2007-08-28 17:01:54 -04:00
sdata - > u . sta . flags & = ~ IEEE80211_STA_AUTO_BSSID_SEL ;
2007-05-05 11:45:53 -07:00
ieee80211_sta_req_auth ( dev , & sdata - > u . sta ) ;
return 0 ;
}
return - EOPNOTSUPP ;
}
static int ieee80211_ioctl_giwname ( struct net_device * dev ,
struct iw_request_info * info ,
char * name , char * extra )
{
2008-01-24 19:38:38 +01:00
strcpy ( name , " IEEE 802.11 " ) ;
2007-05-05 11:45:53 -07:00
return 0 ;
}
static int ieee80211_ioctl_giwrange ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * data , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
struct iw_range * range = ( struct iw_range * ) extra ;
2008-01-24 19:38:38 +01:00
enum ieee80211_band band ;
2007-07-10 19:32:08 +02:00
int c = 0 ;
2007-05-05 11:45:53 -07:00
data - > length = sizeof ( struct iw_range ) ;
memset ( range , 0 , sizeof ( struct iw_range ) ) ;
range - > we_version_compiled = WIRELESS_EXT ;
range - > we_version_source = 21 ;
range - > retry_capa = IW_RETRY_LIMIT ;
range - > retry_flags = IW_RETRY_LIMIT ;
range - > min_retry = 0 ;
range - > max_retry = 255 ;
range - > min_rts = 0 ;
range - > max_rts = 2347 ;
range - > min_frag = 256 ;
range - > max_frag = 2346 ;
range - > encoding_size [ 0 ] = 5 ;
range - > encoding_size [ 1 ] = 13 ;
range - > num_encoding_sizes = 2 ;
range - > max_encoding_tokens = NUM_DEFAULT_KEYS ;
range - > max_qual . qual = local - > hw . max_signal ;
range - > max_qual . level = local - > hw . max_rssi ;
range - > max_qual . noise = local - > hw . max_noise ;
range - > max_qual . updated = local - > wstats_flags ;
range - > avg_qual . qual = local - > hw . max_signal / 2 ;
range - > avg_qual . level = 0 ;
range - > avg_qual . noise = 0 ;
range - > avg_qual . updated = local - > wstats_flags ;
range - > enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP ;
2007-07-10 19:32:08 +02:00
2008-01-24 19:38:38 +01:00
for ( band = 0 ; band < IEEE80211_NUM_BANDS ; band + + ) {
int i ;
struct ieee80211_supported_band * sband ;
sband = local - > hw . wiphy - > bands [ band ] ;
if ( ! sband )
2007-07-10 19:32:08 +02:00
continue ;
2008-01-24 19:38:38 +01:00
for ( i = 0 ; i < sband - > n_channels & & c < IW_MAX_FREQUENCIES ; i + + ) {
struct ieee80211_channel * chan = & sband - > channels [ i ] ;
2007-07-10 19:32:08 +02:00
2008-01-24 19:38:38 +01:00
if ( ! ( chan - > flags & IEEE80211_CHAN_DISABLED ) ) {
range - > freq [ c ] . i =
ieee80211_frequency_to_channel (
chan - > center_freq ) ;
range - > freq [ c ] . m = chan - > center_freq ;
range - > freq [ c ] . e = 6 ;
2007-07-10 19:32:08 +02:00
c + + ;
}
}
}
range - > num_channels = c ;
range - > num_frequency = c ;
2007-05-05 11:45:53 -07:00
IW_EVENT_CAPA_SET_KERNEL ( range - > event_capa ) ;
IW_EVENT_CAPA_SET ( range - > event_capa , SIOCGIWAP ) ;
IW_EVENT_CAPA_SET ( range - > event_capa , SIOCGIWSCAN ) ;
2007-12-12 10:25:07 -05:00
range - > scan_capa | = IW_SCAN_CAPA_ESSID ;
2007-05-05 11:45:53 -07:00
return 0 ;
}
static int ieee80211_ioctl_siwmode ( struct net_device * dev ,
struct iw_request_info * info ,
__u32 * mode , char * extra )
{
struct ieee80211_sub_if_data * sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
int type ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_VLAN )
2007-05-05 11:45:53 -07:00
return - EOPNOTSUPP ;
switch ( * mode ) {
case IW_MODE_INFRA :
type = IEEE80211_IF_TYPE_STA ;
break ;
case IW_MODE_ADHOC :
type = IEEE80211_IF_TYPE_IBSS ;
break ;
2008-04-14 15:37:03 +02:00
case IW_MODE_REPEAT :
type = IEEE80211_IF_TYPE_WDS ;
break ;
2007-05-05 11:45:53 -07:00
case IW_MODE_MONITOR :
type = IEEE80211_IF_TYPE_MNTR ;
break ;
default :
return - EINVAL ;
}
2007-12-19 01:31:27 +01:00
if ( type = = sdata - > vif . type )
2007-05-05 11:45:53 -07:00
return 0 ;
if ( netif_running ( dev ) )
return - EBUSY ;
ieee80211_if_reinit ( dev ) ;
ieee80211_if_set_type ( dev , type ) ;
return 0 ;
}
static int ieee80211_ioctl_giwmode ( struct net_device * dev ,
struct iw_request_info * info ,
__u32 * mode , char * extra )
{
struct ieee80211_sub_if_data * sdata ;
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2007-12-19 01:31:27 +01:00
switch ( sdata - > vif . type ) {
2007-05-05 11:45:53 -07:00
case IEEE80211_IF_TYPE_AP :
* mode = IW_MODE_MASTER ;
break ;
case IEEE80211_IF_TYPE_STA :
* mode = IW_MODE_INFRA ;
break ;
case IEEE80211_IF_TYPE_IBSS :
* mode = IW_MODE_ADHOC ;
break ;
case IEEE80211_IF_TYPE_MNTR :
* mode = IW_MODE_MONITOR ;
break ;
case IEEE80211_IF_TYPE_WDS :
* mode = IW_MODE_REPEAT ;
break ;
case IEEE80211_IF_TYPE_VLAN :
* mode = IW_MODE_SECOND ; /* FIXME */
break ;
default :
* mode = IW_MODE_AUTO ;
break ;
}
return 0 ;
}
2008-06-05 19:55:21 +03:00
int ieee80211_set_freq ( struct net_device * dev , int freqMHz )
2007-05-05 11:45:53 -07:00
{
int ret = - EINVAL ;
2008-03-16 18:35:56 +01:00
struct ieee80211_channel * chan ;
2008-06-05 19:55:21 +03:00
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
struct ieee80211_sub_if_data * sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2008-01-24 19:38:38 +01:00
2008-03-16 18:35:56 +01:00
chan = ieee80211_get_channel ( local - > hw . wiphy , freqMHz ) ;
2008-01-24 19:38:38 +01:00
2008-03-16 18:35:56 +01:00
if ( chan & & ! ( chan - > flags & IEEE80211_CHAN_DISABLED ) ) {
2008-06-05 19:55:21 +03:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_IBSS & &
chan - > flags & IEEE80211_CHAN_NO_IBSS ) {
printk ( KERN_DEBUG " %s: IBSS not allowed on frequency "
" %d MHz \n " , dev - > name , chan - > center_freq ) ;
return ret ;
}
2008-03-16 18:35:56 +01:00
local - > oper_channel = chan ;
2007-05-05 11:45:53 -07:00
2008-03-20 08:14:29 -07:00
if ( local - > sta_sw_scanning | | local - > sta_hw_scanning )
2007-05-05 11:45:53 -07:00
ret = 0 ;
else
ret = ieee80211_hw_config ( local ) ;
rate_control_clear ( local ) ;
}
return ret ;
}
static int ieee80211_ioctl_siwfreq ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_freq * freq , char * extra )
{
struct ieee80211_sub_if_data * sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA )
2007-08-28 17:01:54 -04:00
sdata - > u . sta . flags & = ~ IEEE80211_STA_AUTO_CHANNEL_SEL ;
2007-05-05 11:45:53 -07:00
/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
if ( freq - > e = = 0 ) {
if ( freq - > m < 0 ) {
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA )
2007-08-28 17:01:54 -04:00
sdata - > u . sta . flags | =
IEEE80211_STA_AUTO_CHANNEL_SEL ;
2007-05-05 11:45:53 -07:00
return 0 ;
} else
2008-06-05 19:55:21 +03:00
return ieee80211_set_freq ( dev ,
2008-01-24 19:38:38 +01:00
ieee80211_channel_to_frequency ( freq - > m ) ) ;
2007-05-05 11:45:53 -07:00
} else {
int i , div = 1000000 ;
for ( i = 0 ; i < freq - > e ; i + + )
div / = 10 ;
if ( div > 0 )
2008-06-05 19:55:21 +03:00
return ieee80211_set_freq ( dev , freq - > m / div ) ;
2007-05-05 11:45:53 -07:00
else
return - EINVAL ;
}
}
static int ieee80211_ioctl_giwfreq ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_freq * freq , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
2008-01-24 19:38:38 +01:00
freq - > m = local - > hw . conf . channel - > center_freq ;
2007-05-05 11:45:53 -07:00
freq - > e = 6 ;
return 0 ;
}
static int ieee80211_ioctl_siwessid ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * data , char * ssid )
{
struct ieee80211_sub_if_data * sdata ;
size_t len = data - > length ;
/* iwconfig uses nul termination in SSID.. */
if ( len > 0 & & ssid [ len - 1 ] = = ' \0 ' )
len - - ;
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA | |
sdata - > vif . type = = IEEE80211_IF_TYPE_IBSS ) {
2007-05-05 11:45:53 -07:00
int ret ;
2007-09-26 17:53:20 +02:00
if ( sdata - > flags & IEEE80211_SDATA_USERSPACE_MLME ) {
2007-05-05 11:45:53 -07:00
if ( len > IEEE80211_MAX_SSID_LEN )
return - EINVAL ;
memcpy ( sdata - > u . sta . ssid , ssid , len ) ;
sdata - > u . sta . ssid_len = len ;
return 0 ;
}
2007-08-28 17:01:54 -04:00
if ( data - > flags )
sdata - > u . sta . flags & = ~ IEEE80211_STA_AUTO_SSID_SEL ;
else
sdata - > u . sta . flags | = IEEE80211_STA_AUTO_SSID_SEL ;
2007-05-05 11:45:53 -07:00
ret = ieee80211_sta_set_ssid ( dev , ssid , len ) ;
if ( ret )
return ret ;
ieee80211_sta_req_auth ( dev , & sdata - > u . sta ) ;
return 0 ;
}
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_AP ) {
2007-05-05 11:45:53 -07:00
memcpy ( sdata - > u . ap . ssid , ssid , len ) ;
memset ( sdata - > u . ap . ssid + len , 0 ,
IEEE80211_MAX_SSID_LEN - len ) ;
sdata - > u . ap . ssid_len = len ;
return ieee80211_if_config ( dev ) ;
}
return - EOPNOTSUPP ;
}
static int ieee80211_ioctl_giwessid ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * data , char * ssid )
{
size_t len ;
struct ieee80211_sub_if_data * sdata ;
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA | |
sdata - > vif . type = = IEEE80211_IF_TYPE_IBSS ) {
2007-05-05 11:45:53 -07:00
int res = ieee80211_sta_get_ssid ( dev , ssid , & len ) ;
if ( res = = 0 ) {
data - > length = len ;
data - > flags = 1 ;
} else
data - > flags = 0 ;
return res ;
}
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_AP ) {
2007-05-05 11:45:53 -07:00
len = sdata - > u . ap . ssid_len ;
if ( len > IW_ESSID_MAX_SIZE )
len = IW_ESSID_MAX_SIZE ;
memcpy ( ssid , sdata - > u . ap . ssid , len ) ;
data - > length = len ;
data - > flags = 1 ;
return 0 ;
}
return - EOPNOTSUPP ;
}
static int ieee80211_ioctl_siwap ( struct net_device * dev ,
struct iw_request_info * info ,
struct sockaddr * ap_addr , char * extra )
{
struct ieee80211_sub_if_data * sdata ;
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA | |
sdata - > vif . type = = IEEE80211_IF_TYPE_IBSS ) {
2007-05-05 11:45:53 -07:00
int ret ;
2007-09-26 17:53:20 +02:00
if ( sdata - > flags & IEEE80211_SDATA_USERSPACE_MLME ) {
2007-05-05 11:45:53 -07:00
memcpy ( sdata - > u . sta . bssid , ( u8 * ) & ap_addr - > sa_data ,
ETH_ALEN ) ;
return 0 ;
}
2007-08-28 17:01:54 -04:00
if ( is_zero_ether_addr ( ( u8 * ) & ap_addr - > sa_data ) )
sdata - > u . sta . flags | = IEEE80211_STA_AUTO_BSSID_SEL |
IEEE80211_STA_AUTO_CHANNEL_SEL ;
else if ( is_broadcast_ether_addr ( ( u8 * ) & ap_addr - > sa_data ) )
sdata - > u . sta . flags | = IEEE80211_STA_AUTO_BSSID_SEL ;
2007-05-05 11:45:53 -07:00
else
2007-08-28 17:01:54 -04:00
sdata - > u . sta . flags & = ~ IEEE80211_STA_AUTO_BSSID_SEL ;
2007-05-05 11:45:53 -07:00
ret = ieee80211_sta_set_bssid ( dev , ( u8 * ) & ap_addr - > sa_data ) ;
if ( ret )
return ret ;
ieee80211_sta_req_auth ( dev , & sdata - > u . sta ) ;
return 0 ;
2007-12-19 01:31:27 +01:00
} else if ( sdata - > vif . type = = IEEE80211_IF_TYPE_WDS ) {
2008-02-25 16:27:49 +01:00
/*
* If it is necessary to update the WDS peer address
* while the interface is running , then we need to do
* more work here , namely if it is running we need to
* add a new and remove the old STA entry , this is
* normally handled by _open ( ) and _stop ( ) .
*/
if ( netif_running ( dev ) )
return - EBUSY ;
memcpy ( & sdata - > u . wds . remote_addr , ( u8 * ) & ap_addr - > sa_data ,
ETH_ALEN ) ;
return 0 ;
2007-05-05 11:45:53 -07:00
}
return - EOPNOTSUPP ;
}
static int ieee80211_ioctl_giwap ( struct net_device * dev ,
struct iw_request_info * info ,
struct sockaddr * ap_addr , char * extra )
{
struct ieee80211_sub_if_data * sdata ;
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA | |
sdata - > vif . type = = IEEE80211_IF_TYPE_IBSS ) {
2008-06-12 09:47:16 +08:00
if ( sdata - > u . sta . state = = IEEE80211_ASSOCIATED | |
sdata - > u . sta . state = = IEEE80211_IBSS_JOINED ) {
2008-05-23 10:15:26 -07:00
ap_addr - > sa_family = ARPHRD_ETHER ;
memcpy ( & ap_addr - > sa_data , sdata - > u . sta . bssid , ETH_ALEN ) ;
return 0 ;
} else {
memset ( & ap_addr - > sa_data , 0 , ETH_ALEN ) ;
return 0 ;
}
2007-12-19 01:31:27 +01:00
} else if ( sdata - > vif . type = = IEEE80211_IF_TYPE_WDS ) {
2007-05-05 11:45:53 -07:00
ap_addr - > sa_family = ARPHRD_ETHER ;
memcpy ( & ap_addr - > sa_data , sdata - > u . wds . remote_addr , ETH_ALEN ) ;
return 0 ;
}
return - EOPNOTSUPP ;
}
static int ieee80211_ioctl_siwscan ( struct net_device * dev ,
struct iw_request_info * info ,
2007-10-10 16:23:55 -04:00
union iwreq_data * wrqu , char * extra )
2007-05-05 11:45:53 -07:00
{
struct ieee80211_sub_if_data * sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2007-10-10 16:23:55 -04:00
struct iw_scan_req * req = NULL ;
2007-05-05 11:45:53 -07:00
u8 * ssid = NULL ;
size_t ssid_len = 0 ;
if ( ! netif_running ( dev ) )
return - ENETDOWN ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type ! = IEEE80211_IF_TYPE_STA & &
sdata - > vif . type ! = IEEE80211_IF_TYPE_IBSS & &
2008-02-23 15:17:11 +01:00
sdata - > vif . type ! = IEEE80211_IF_TYPE_MESH_POINT & &
2007-12-19 01:31:27 +01:00
sdata - > vif . type ! = IEEE80211_IF_TYPE_AP )
2007-10-17 21:16:16 -07:00
return - EOPNOTSUPP ;
/* if SSID was specified explicitly then use that */
2007-10-10 16:23:55 -04:00
if ( wrqu - > data . length = = sizeof ( struct iw_scan_req ) & &
wrqu - > data . flags & IW_SCAN_THIS_ESSID ) {
req = ( struct iw_scan_req * ) extra ;
ssid = req - > essid ;
ssid_len = req - > essid_len ;
2007-05-05 11:45:53 -07:00
}
2007-07-27 15:43:24 +02:00
2007-05-05 11:45:53 -07:00
return ieee80211_sta_req_scan ( dev , ssid , ssid_len ) ;
}
static int ieee80211_ioctl_giwscan ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * data , char * extra )
{
int res ;
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
2007-11-22 10:53:21 +08:00
if ( local - > sta_sw_scanning | | local - > sta_hw_scanning )
2007-05-05 11:45:53 -07:00
return - EAGAIN ;
2007-11-22 10:53:21 +08:00
2007-05-05 11:45:53 -07:00
res = ieee80211_sta_scan_results ( dev , extra , data - > length ) ;
if ( res > = 0 ) {
data - > length = res ;
return 0 ;
}
data - > length = 0 ;
return res ;
}
2007-07-10 19:32:10 +02:00
static int ieee80211_ioctl_siwrate ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * rate , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
2008-01-24 19:38:38 +01:00
int i , err = - EINVAL ;
2007-07-10 19:32:10 +02:00
u32 target_rate = rate - > value / 100000 ;
struct ieee80211_sub_if_data * sdata ;
2008-01-24 19:38:38 +01:00
struct ieee80211_supported_band * sband ;
2007-07-10 19:32:10 +02:00
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
if ( ! sdata - > bss )
return - ENODEV ;
2008-01-24 19:38:38 +01:00
sband = local - > hw . wiphy - > bands [ local - > hw . conf . channel - > band ] ;
2007-07-10 19:32:10 +02:00
/* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
* target_rate = X , rate - > fixed = 1 means only rate X
* target_rate = X , rate - > fixed = 0 means all rates < = X */
sdata - > bss - > max_ratectrl_rateidx = - 1 ;
sdata - > bss - > force_unicast_rateidx = - 1 ;
if ( rate - > value < 0 )
return 0 ;
2008-01-24 19:38:38 +01:00
for ( i = 0 ; i < sband - > n_bitrates ; i + + ) {
struct ieee80211_rate * brate = & sband - > bitrates [ i ] ;
int this_rate = brate - > bitrate ;
2007-07-10 19:32:10 +02:00
if ( target_rate = = this_rate ) {
sdata - > bss - > max_ratectrl_rateidx = i ;
if ( rate - > fixed )
sdata - > bss - > force_unicast_rateidx = i ;
2008-01-24 19:38:38 +01:00
err = 0 ;
break ;
2007-07-10 19:32:10 +02:00
}
}
2008-01-24 19:38:38 +01:00
return err ;
2007-07-10 19:32:10 +02:00
}
2007-06-10 17:57:33 -07:00
static int ieee80211_ioctl_giwrate ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * rate , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
struct sta_info * sta ;
struct ieee80211_sub_if_data * sdata ;
2008-01-24 19:38:38 +01:00
struct ieee80211_supported_band * sband ;
2007-06-10 17:57:33 -07:00
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2008-01-24 19:38:38 +01:00
2008-04-04 23:40:35 +02:00
if ( sdata - > vif . type ! = IEEE80211_IF_TYPE_STA )
2007-06-10 17:57:33 -07:00
return - EOPNOTSUPP ;
2008-01-24 19:38:38 +01:00
sband = local - > hw . wiphy - > bands [ local - > hw . conf . channel - > band ] ;
2008-04-04 23:40:35 +02:00
rcu_read_lock ( ) ;
sta = sta_info_get ( local , sdata - > u . sta . bssid ) ;
if ( sta & & sta - > txrate_idx < sband - > n_bitrates )
2008-01-24 19:38:38 +01:00
rate - > value = sband - > bitrates [ sta - > txrate_idx ] . bitrate ;
2007-06-10 17:57:33 -07:00
else
rate - > value = 0 ;
2008-04-04 23:40:35 +02:00
rcu_read_unlock ( ) ;
if ( ! sta )
return - ENODEV ;
2008-01-24 19:38:38 +01:00
rate - > value * = 100000 ;
2008-02-25 16:27:46 +01:00
2007-06-10 17:57:33 -07:00
return 0 ;
}
2007-09-20 22:06:39 +02:00
static int ieee80211_ioctl_siwtxpower ( struct net_device * dev ,
struct iw_request_info * info ,
union iwreq_data * data , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
bool need_reconfig = 0 ;
2008-01-24 19:38:38 +01:00
int new_power_level ;
2007-09-20 22:06:39 +02:00
if ( ( data - > txpower . flags & IW_TXPOW_TYPE ) ! = IW_TXPOW_DBM )
return - EINVAL ;
if ( data - > txpower . flags & IW_TXPOW_RANGE )
return - EINVAL ;
2007-10-24 23:30:36 +02:00
if ( data - > txpower . fixed ) {
new_power_level = data - > txpower . value ;
} else {
2008-01-24 19:38:38 +01:00
/*
* Automatic power level . Use maximum power for the current
* channel . Should be part of rate control .
*/
struct ieee80211_channel * chan = local - > hw . conf . channel ;
2007-10-24 23:30:36 +02:00
if ( ! chan )
return - EINVAL ;
2008-01-24 19:38:38 +01:00
new_power_level = chan - > max_power ;
2007-10-24 23:30:36 +02:00
}
if ( local - > hw . conf . power_level ! = new_power_level ) {
local - > hw . conf . power_level = new_power_level ;
2007-09-20 22:06:39 +02:00
need_reconfig = 1 ;
}
2007-10-24 23:30:36 +02:00
2007-09-20 22:06:39 +02:00
if ( local - > hw . conf . radio_enabled ! = ! ( data - > txpower . disabled ) ) {
local - > hw . conf . radio_enabled = ! ( data - > txpower . disabled ) ;
need_reconfig = 1 ;
2008-01-07 19:45:24 +01:00
ieee80211_led_radio ( local , local - > hw . conf . radio_enabled ) ;
2007-09-20 22:06:39 +02:00
}
2007-10-24 23:30:36 +02:00
2007-09-20 22:06:39 +02:00
if ( need_reconfig ) {
ieee80211_hw_config ( local ) ;
/* The return value of hw_config is not of big interest here,
* as it doesn ' t say that it failed because of _this_ config
* change or something else . Ignore it . */
}
return 0 ;
}
2007-08-10 11:23:20 -05:00
static int ieee80211_ioctl_giwtxpower ( struct net_device * dev ,
struct iw_request_info * info ,
union iwreq_data * data , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
data - > txpower . fixed = 1 ;
data - > txpower . disabled = ! ( local - > hw . conf . radio_enabled ) ;
data - > txpower . value = local - > hw . conf . power_level ;
data - > txpower . flags = IW_TXPOW_DBM ;
return 0 ;
}
2007-05-05 11:45:53 -07:00
static int ieee80211_ioctl_siwrts ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * rts , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
if ( rts - > disabled )
local - > rts_threshold = IEEE80211_MAX_RTS_THRESHOLD ;
else if ( rts - > value < 0 | | rts - > value > IEEE80211_MAX_RTS_THRESHOLD )
return - EINVAL ;
else
local - > rts_threshold = rts - > value ;
/* If the wlan card performs RTS/CTS in hardware/firmware,
* configure it here */
if ( local - > ops - > set_rts_threshold )
local - > ops - > set_rts_threshold ( local_to_hw ( local ) ,
local - > rts_threshold ) ;
return 0 ;
}
static int ieee80211_ioctl_giwrts ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * rts , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
rts - > value = local - > rts_threshold ;
rts - > disabled = ( rts - > value > = IEEE80211_MAX_RTS_THRESHOLD ) ;
rts - > fixed = 1 ;
return 0 ;
}
static int ieee80211_ioctl_siwfrag ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * frag , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
if ( frag - > disabled )
local - > fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD ;
else if ( frag - > value < 256 | |
frag - > value > IEEE80211_MAX_FRAG_THRESHOLD )
return - EINVAL ;
else {
/* Fragment length must be even, so strip LSB. */
local - > fragmentation_threshold = frag - > value & ~ 0x1 ;
}
/* If the wlan card performs fragmentation in hardware/firmware,
* configure it here */
if ( local - > ops - > set_frag_threshold )
local - > ops - > set_frag_threshold (
local_to_hw ( local ) ,
local - > fragmentation_threshold ) ;
return 0 ;
}
static int ieee80211_ioctl_giwfrag ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * frag , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
frag - > value = local - > fragmentation_threshold ;
frag - > disabled = ( frag - > value > = IEEE80211_MAX_RTS_THRESHOLD ) ;
frag - > fixed = 1 ;
return 0 ;
}
static int ieee80211_ioctl_siwretry ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * retry , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
if ( retry - > disabled | |
( retry - > flags & IW_RETRY_TYPE ) ! = IW_RETRY_LIMIT )
return - EINVAL ;
if ( retry - > flags & IW_RETRY_MAX )
local - > long_retry_limit = retry - > value ;
else if ( retry - > flags & IW_RETRY_MIN )
local - > short_retry_limit = retry - > value ;
else {
local - > long_retry_limit = retry - > value ;
local - > short_retry_limit = retry - > value ;
}
if ( local - > ops - > set_retry_limit ) {
return local - > ops - > set_retry_limit (
local_to_hw ( local ) ,
local - > short_retry_limit ,
local - > long_retry_limit ) ;
}
return 0 ;
}
static int ieee80211_ioctl_giwretry ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * retry , char * extra )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
retry - > disabled = 0 ;
if ( retry - > flags = = 0 | | retry - > flags & IW_RETRY_MIN ) {
/* first return min value, iwconfig will ask max value
* later if needed */
retry - > flags | = IW_RETRY_LIMIT ;
retry - > value = local - > short_retry_limit ;
if ( local - > long_retry_limit ! = local - > short_retry_limit )
retry - > flags | = IW_RETRY_MIN ;
return 0 ;
}
if ( retry - > flags & IW_RETRY_MAX ) {
retry - > flags = IW_RETRY_LIMIT | IW_RETRY_MAX ;
retry - > value = local - > long_retry_limit ;
}
return 0 ;
}
static int ieee80211_ioctl_siwmlme ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * data , char * extra )
{
struct ieee80211_sub_if_data * sdata ;
struct iw_mlme * mlme = ( struct iw_mlme * ) extra ;
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type ! = IEEE80211_IF_TYPE_STA & &
sdata - > vif . type ! = IEEE80211_IF_TYPE_IBSS )
2007-05-05 11:45:53 -07:00
return - EINVAL ;
switch ( mlme - > cmd ) {
case IW_MLME_DEAUTH :
/* TODO: mlme->addr.sa_data */
return ieee80211_sta_deauthenticate ( dev , mlme - > reason_code ) ;
case IW_MLME_DISASSOC :
/* TODO: mlme->addr.sa_data */
return ieee80211_sta_disassociate ( dev , mlme - > reason_code ) ;
default :
return - EOPNOTSUPP ;
}
}
static int ieee80211_ioctl_siwencode ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * erq , char * keybuf )
{
struct ieee80211_sub_if_data * sdata ;
int idx , i , alg = ALG_WEP ;
u8 bcaddr [ ETH_ALEN ] = { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff } ;
2007-09-26 17:53:17 +02:00
int remove = 0 ;
2007-05-05 11:45:53 -07:00
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
idx = erq - > flags & IW_ENCODE_INDEX ;
if ( idx = = 0 ) {
if ( sdata - > default_key )
for ( i = 0 ; i < NUM_DEFAULT_KEYS ; i + + ) {
if ( sdata - > default_key = = sdata - > keys [ i ] ) {
idx = i ;
break ;
}
}
} else if ( idx < 1 | | idx > 4 )
return - EINVAL ;
else
idx - - ;
if ( erq - > flags & IW_ENCODE_DISABLED )
2007-09-26 17:53:17 +02:00
remove = 1 ;
2007-05-05 11:45:53 -07:00
else if ( erq - > length = = 0 ) {
/* No key data - just set the default TX key index */
2007-08-28 17:01:55 -04:00
ieee80211_set_default_key ( sdata , idx ) ;
2007-05-05 11:45:53 -07:00
return 0 ;
}
return ieee80211_set_encryption (
dev , bcaddr ,
2007-09-26 17:53:17 +02:00
idx , alg , remove ,
2007-05-05 11:45:53 -07:00
! sdata - > default_key ,
keybuf , erq - > length ) ;
}
static int ieee80211_ioctl_giwencode ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * erq , char * key )
{
struct ieee80211_sub_if_data * sdata ;
int idx , i ;
sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
idx = erq - > flags & IW_ENCODE_INDEX ;
if ( idx < 1 | | idx > 4 ) {
idx = - 1 ;
if ( ! sdata - > default_key )
idx = 0 ;
else for ( i = 0 ; i < NUM_DEFAULT_KEYS ; i + + ) {
if ( sdata - > default_key = = sdata - > keys [ i ] ) {
idx = i ;
break ;
}
}
if ( idx < 0 )
return - EINVAL ;
} else
idx - - ;
erq - > flags = idx + 1 ;
if ( ! sdata - > keys [ idx ] ) {
erq - > length = 0 ;
erq - > flags | = IW_ENCODE_DISABLED ;
return 0 ;
}
2007-08-28 17:01:54 -04:00
memcpy ( key , sdata - > keys [ idx ] - > conf . key ,
2007-08-28 17:01:55 -04:00
min_t ( int , erq - > length , sdata - > keys [ idx ] - > conf . keylen ) ) ;
2007-08-28 17:01:54 -04:00
erq - > length = sdata - > keys [ idx ] - > conf . keylen ;
2007-05-05 11:45:53 -07:00
erq - > flags | = IW_ENCODE_ENABLED ;
return 0 ;
}
static int ieee80211_ioctl_siwauth ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * data , char * extra )
{
struct ieee80211_sub_if_data * sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
int ret = 0 ;
switch ( data - > flags & IW_AUTH_INDEX ) {
case IW_AUTH_WPA_VERSION :
case IW_AUTH_CIPHER_PAIRWISE :
case IW_AUTH_CIPHER_GROUP :
case IW_AUTH_WPA_ENABLED :
case IW_AUTH_RX_UNENCRYPTED_EAPOL :
case IW_AUTH_KEY_MGMT :
2007-11-03 13:11:10 +00:00
break ;
2007-11-28 11:04:21 +01:00
case IW_AUTH_DROP_UNENCRYPTED :
sdata - > drop_unencrypted = ! ! data - > value ;
break ;
2007-11-03 13:11:10 +00:00
case IW_AUTH_PRIVACY_INVOKED :
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type ! = IEEE80211_IF_TYPE_STA )
2007-05-05 11:45:53 -07:00
ret = - EINVAL ;
else {
2007-11-03 13:11:10 +00:00
sdata - > u . sta . flags & = ~ IEEE80211_STA_PRIVACY_INVOKED ;
2007-05-05 11:45:53 -07:00
/*
2007-11-03 13:11:10 +00:00
* Privacy invoked by wpa_supplicant , store the
* value and allow associating to a protected
* network without having a key up front .
2007-05-05 11:45:53 -07:00
*/
2007-11-03 13:11:10 +00:00
if ( data - > value )
sdata - > u . sta . flags | =
IEEE80211_STA_PRIVACY_INVOKED ;
2007-05-05 11:45:53 -07:00
}
break ;
case IW_AUTH_80211_AUTH_ALG :
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA | |
sdata - > vif . type = = IEEE80211_IF_TYPE_IBSS )
2007-05-05 11:45:53 -07:00
sdata - > u . sta . auth_algs = data - > value ;
else
ret = - EOPNOTSUPP ;
break ;
default :
ret = - EOPNOTSUPP ;
break ;
}
return ret ;
}
/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
static struct iw_statistics * ieee80211_get_wireless_stats ( struct net_device * dev )
{
struct ieee80211_local * local = wdev_priv ( dev - > ieee80211_ptr ) ;
struct iw_statistics * wstats = & local - > wstats ;
struct ieee80211_sub_if_data * sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
struct sta_info * sta = NULL ;
2008-04-10 15:36:09 +02:00
rcu_read_lock ( ) ;
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA | |
sdata - > vif . type = = IEEE80211_IF_TYPE_IBSS )
2007-05-05 11:45:53 -07:00
sta = sta_info_get ( local , sdata - > u . sta . bssid ) ;
if ( ! sta ) {
wstats - > discard . fragment = 0 ;
wstats - > discard . misc = 0 ;
wstats - > qual . qual = 0 ;
wstats - > qual . level = 0 ;
wstats - > qual . noise = 0 ;
wstats - > qual . updated = IW_QUAL_ALL_INVALID ;
} else {
wstats - > qual . level = sta - > last_rssi ;
wstats - > qual . qual = sta - > last_signal ;
wstats - > qual . noise = sta - > last_noise ;
wstats - > qual . updated = local - > wstats_flags ;
}
2008-04-10 15:36:09 +02:00
rcu_read_unlock ( ) ;
2007-05-05 11:45:53 -07:00
return wstats ;
}
static int ieee80211_ioctl_giwauth ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_param * data , char * extra )
{
struct ieee80211_sub_if_data * sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
int ret = 0 ;
switch ( data - > flags & IW_AUTH_INDEX ) {
case IW_AUTH_80211_AUTH_ALG :
2007-12-19 01:31:27 +01:00
if ( sdata - > vif . type = = IEEE80211_IF_TYPE_STA | |
sdata - > vif . type = = IEEE80211_IF_TYPE_IBSS )
2007-05-05 11:45:53 -07:00
data - > value = sdata - > u . sta . auth_algs ;
else
ret = - EOPNOTSUPP ;
break ;
default :
ret = - EOPNOTSUPP ;
break ;
}
return ret ;
}
static int ieee80211_ioctl_siwencodeext ( struct net_device * dev ,
struct iw_request_info * info ,
struct iw_point * erq , char * extra )
{
struct ieee80211_sub_if_data * sdata = IEEE80211_DEV_TO_SUB_IF ( dev ) ;
struct iw_encode_ext * ext = ( struct iw_encode_ext * ) extra ;
2007-09-26 17:53:17 +02:00
int uninitialized_var ( alg ) , idx , i , remove = 0 ;
2007-05-05 11:45:53 -07:00
switch ( ext - > alg ) {
case IW_ENCODE_ALG_NONE :
2007-09-26 17:53:17 +02:00
remove = 1 ;
2007-05-05 11:45:53 -07:00
break ;
case IW_ENCODE_ALG_WEP :
alg = ALG_WEP ;
break ;
case IW_ENCODE_ALG_TKIP :
alg = ALG_TKIP ;
break ;
case IW_ENCODE_ALG_CCMP :
alg = ALG_CCMP ;
break ;
default :
return - EOPNOTSUPP ;
}
if ( erq - > flags & IW_ENCODE_DISABLED )
2007-09-26 17:53:17 +02:00
remove = 1 ;
2007-05-05 11:45:53 -07:00
idx = erq - > flags & IW_ENCODE_INDEX ;
if ( idx < 1 | | idx > 4 ) {
idx = - 1 ;
if ( ! sdata - > default_key )
idx = 0 ;
else for ( i = 0 ; i < NUM_DEFAULT_KEYS ; i + + ) {
if ( sdata - > default_key = = sdata - > keys [ i ] ) {
idx = i ;
break ;
}
}
if ( idx < 0 )
return - EINVAL ;
} else
idx - - ;
return ieee80211_set_encryption ( dev , ext - > addr . sa_data , idx , alg ,
2007-09-26 17:53:17 +02:00
remove ,
2007-05-05 11:45:53 -07:00
ext - > ext_flags &
IW_ENCODE_EXT_SET_TX_KEY ,
ext - > key , ext - > key_len ) ;
}
/* Structures to export the Wireless Handlers */
static const iw_handler ieee80211_handler [ ] =
{
( iw_handler ) NULL , /* SIOCSIWCOMMIT */
( iw_handler ) ieee80211_ioctl_giwname , /* SIOCGIWNAME */
( iw_handler ) NULL , /* SIOCSIWNWID */
( iw_handler ) NULL , /* SIOCGIWNWID */
( iw_handler ) ieee80211_ioctl_siwfreq , /* SIOCSIWFREQ */
( iw_handler ) ieee80211_ioctl_giwfreq , /* SIOCGIWFREQ */
( iw_handler ) ieee80211_ioctl_siwmode , /* SIOCSIWMODE */
( iw_handler ) ieee80211_ioctl_giwmode , /* SIOCGIWMODE */
( iw_handler ) NULL , /* SIOCSIWSENS */
( iw_handler ) NULL , /* SIOCGIWSENS */
( iw_handler ) NULL /* not used */ , /* SIOCSIWRANGE */
( iw_handler ) ieee80211_ioctl_giwrange , /* SIOCGIWRANGE */
( iw_handler ) NULL /* not used */ , /* SIOCSIWPRIV */
( iw_handler ) NULL /* kernel code */ , /* SIOCGIWPRIV */
( iw_handler ) NULL /* not used */ , /* SIOCSIWSTATS */
( iw_handler ) NULL /* kernel code */ , /* SIOCGIWSTATS */
2007-09-14 11:10:24 -04:00
( iw_handler ) NULL , /* SIOCSIWSPY */
( iw_handler ) NULL , /* SIOCGIWSPY */
( iw_handler ) NULL , /* SIOCSIWTHRSPY */
( iw_handler ) NULL , /* SIOCGIWTHRSPY */
2007-05-05 11:45:53 -07:00
( iw_handler ) ieee80211_ioctl_siwap , /* SIOCSIWAP */
( iw_handler ) ieee80211_ioctl_giwap , /* SIOCGIWAP */
( iw_handler ) ieee80211_ioctl_siwmlme , /* SIOCSIWMLME */
( iw_handler ) NULL , /* SIOCGIWAPLIST */
( iw_handler ) ieee80211_ioctl_siwscan , /* SIOCSIWSCAN */
( iw_handler ) ieee80211_ioctl_giwscan , /* SIOCGIWSCAN */
( iw_handler ) ieee80211_ioctl_siwessid , /* SIOCSIWESSID */
( iw_handler ) ieee80211_ioctl_giwessid , /* SIOCGIWESSID */
( iw_handler ) NULL , /* SIOCSIWNICKN */
( iw_handler ) NULL , /* SIOCGIWNICKN */
( iw_handler ) NULL , /* -- hole -- */
( iw_handler ) NULL , /* -- hole -- */
2007-07-10 19:32:10 +02:00
( iw_handler ) ieee80211_ioctl_siwrate , /* SIOCSIWRATE */
2007-06-10 17:57:33 -07:00
( iw_handler ) ieee80211_ioctl_giwrate , /* SIOCGIWRATE */
2007-05-05 11:45:53 -07:00
( iw_handler ) ieee80211_ioctl_siwrts , /* SIOCSIWRTS */
( iw_handler ) ieee80211_ioctl_giwrts , /* SIOCGIWRTS */
( iw_handler ) ieee80211_ioctl_siwfrag , /* SIOCSIWFRAG */
( iw_handler ) ieee80211_ioctl_giwfrag , /* SIOCGIWFRAG */
2007-09-20 22:06:39 +02:00
( iw_handler ) ieee80211_ioctl_siwtxpower , /* SIOCSIWTXPOW */
2007-08-10 11:23:20 -05:00
( iw_handler ) ieee80211_ioctl_giwtxpower , /* SIOCGIWTXPOW */
2007-05-05 11:45:53 -07:00
( iw_handler ) ieee80211_ioctl_siwretry , /* SIOCSIWRETRY */
( iw_handler ) ieee80211_ioctl_giwretry , /* SIOCGIWRETRY */
( iw_handler ) ieee80211_ioctl_siwencode , /* SIOCSIWENCODE */
( iw_handler ) ieee80211_ioctl_giwencode , /* SIOCGIWENCODE */
( iw_handler ) NULL , /* SIOCSIWPOWER */
( iw_handler ) NULL , /* SIOCGIWPOWER */
( iw_handler ) NULL , /* -- hole -- */
( iw_handler ) NULL , /* -- hole -- */
( iw_handler ) ieee80211_ioctl_siwgenie , /* SIOCSIWGENIE */
( iw_handler ) NULL , /* SIOCGIWGENIE */
( iw_handler ) ieee80211_ioctl_siwauth , /* SIOCSIWAUTH */
( iw_handler ) ieee80211_ioctl_giwauth , /* SIOCGIWAUTH */
( iw_handler ) ieee80211_ioctl_siwencodeext , /* SIOCSIWENCODEEXT */
( iw_handler ) NULL , /* SIOCGIWENCODEEXT */
( iw_handler ) NULL , /* SIOCSIWPMKSA */
( iw_handler ) NULL , /* -- hole -- */
} ;
const struct iw_handler_def ieee80211_iw_handler_def =
{
. num_standard = ARRAY_SIZE ( ieee80211_handler ) ,
. standard = ( iw_handler * ) ieee80211_handler ,
. get_wireless_stats = ieee80211_get_wireless_stats ,
} ;