wext: refactor
Refactor wext to * split out iwpriv handling * split out iwspy handling * split out procfs support * allow cfg80211 to have wireless extensions compat code w/o CONFIG_WIRELESS_EXT After this, drivers need to - select WIRELESS_EXT - for wext support - select WEXT_PRIV - for iwpriv support - select WEXT_SPY - for iwspy support except cfg80211 -- which gets new hooks in wext-core.c and can then get wext handlers without CONFIG_WIRELESS_EXT. Wireless extensions procfs support is auto-selected based on PROC_FS and anything that requires the wext core (i.e. WIRELESS_EXT or CFG80211_WEXT). Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
bc974f4a23
commit
3d23e349d8
|
@ -67,6 +67,8 @@ config WAVELAN
|
||||||
tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support"
|
tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support"
|
||||||
depends on ISA && WLAN_PRE80211
|
depends on ISA && WLAN_PRE80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
|
select WEXT_PRIV
|
||||||
---help---
|
---help---
|
||||||
The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is
|
The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is
|
||||||
a Radio LAN (wireless Ethernet-like Local Area Network) using the
|
a Radio LAN (wireless Ethernet-like Local Area Network) using the
|
||||||
|
@ -90,6 +92,8 @@ config PCMCIA_WAVELAN
|
||||||
tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support"
|
tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support"
|
||||||
depends on PCMCIA && WLAN_PRE80211
|
depends on PCMCIA && WLAN_PRE80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
|
select WEXT_PRIV
|
||||||
help
|
help
|
||||||
Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA
|
Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA
|
||||||
(PC-card) wireless Ethernet networking card to your computer. This
|
(PC-card) wireless Ethernet networking card to your computer. This
|
||||||
|
@ -102,6 +106,7 @@ config PCMCIA_NETWAVE
|
||||||
tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
|
tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
|
||||||
depends on PCMCIA && WLAN_PRE80211
|
depends on PCMCIA && WLAN_PRE80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_PRIV
|
||||||
help
|
help
|
||||||
Say Y here if you intend to attach this type of PCMCIA (PC-card)
|
Say Y here if you intend to attach this type of PCMCIA (PC-card)
|
||||||
wireless Ethernet networking card to your computer.
|
wireless Ethernet networking card to your computer.
|
||||||
|
@ -123,6 +128,8 @@ config PCMCIA_RAYCS
|
||||||
tristate "Aviator/Raytheon 2.4GHz wireless support"
|
tristate "Aviator/Raytheon 2.4GHz wireless support"
|
||||||
depends on PCMCIA && WLAN_80211
|
depends on PCMCIA && WLAN_80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
|
select WEXT_PRIV
|
||||||
---help---
|
---help---
|
||||||
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
|
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
|
||||||
(PC-card) wireless Ethernet networking card to your computer.
|
(PC-card) wireless Ethernet networking card to your computer.
|
||||||
|
@ -136,6 +143,7 @@ config LIBERTAS
|
||||||
tristate "Marvell 8xxx Libertas WLAN driver support"
|
tristate "Marvell 8xxx Libertas WLAN driver support"
|
||||||
depends on WLAN_80211
|
depends on WLAN_80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
select LIB80211
|
select LIB80211
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
---help---
|
---help---
|
||||||
|
@ -190,6 +198,8 @@ config AIRO
|
||||||
depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN)
|
depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN)
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
select CRYPTO
|
select CRYPTO
|
||||||
|
select WEXT_SPY
|
||||||
|
select WEXT_PRIV
|
||||||
---help---
|
---help---
|
||||||
This is the standard Linux driver to support Cisco/Aironet ISA and
|
This is the standard Linux driver to support Cisco/Aironet ISA and
|
||||||
PCI 802.11 wireless cards.
|
PCI 802.11 wireless cards.
|
||||||
|
@ -207,6 +217,7 @@ config ATMEL
|
||||||
tristate "Atmel at76c50x chipset 802.11b support"
|
tristate "Atmel at76c50x chipset 802.11b support"
|
||||||
depends on (PCI || PCMCIA) && WLAN_80211
|
depends on (PCI || PCMCIA) && WLAN_80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_PRIV
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
select CRC32
|
select CRC32
|
||||||
---help---
|
---help---
|
||||||
|
@ -266,18 +277,21 @@ config AIRO_CS
|
||||||
Cisco Linux utilities can be used to configure the card.
|
Cisco Linux utilities can be used to configure the card.
|
||||||
|
|
||||||
config PCMCIA_WL3501
|
config PCMCIA_WL3501
|
||||||
tristate "Planet WL3501 PCMCIA cards"
|
tristate "Planet WL3501 PCMCIA cards"
|
||||||
depends on EXPERIMENTAL && PCMCIA && WLAN_80211
|
depends on EXPERIMENTAL && PCMCIA && WLAN_80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
---help---
|
select WEXT_SPY
|
||||||
A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
|
help
|
||||||
It has basic support for Linux wireless extensions and initial
|
A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
|
||||||
micro support for ethtool.
|
It has basic support for Linux wireless extensions and initial
|
||||||
|
micro support for ethtool.
|
||||||
|
|
||||||
config PRISM54
|
config PRISM54
|
||||||
tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)'
|
tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)'
|
||||||
depends on PCI && EXPERIMENTAL && WLAN_80211
|
depends on PCI && EXPERIMENTAL && WLAN_80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
|
select WEXT_PRIV
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
---help---
|
---help---
|
||||||
This enables support for FullMAC PCI/Cardbus prism54 devices. This
|
This enables support for FullMAC PCI/Cardbus prism54 devices. This
|
||||||
|
@ -300,6 +314,7 @@ config USB_ZD1201
|
||||||
tristate "USB ZD1201 based Wireless device support"
|
tristate "USB ZD1201 based Wireless device support"
|
||||||
depends on USB && WLAN_80211
|
depends on USB && WLAN_80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_PRIV
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
---help---
|
---help---
|
||||||
Say Y if you want to use wireless LAN adapters based on the ZyDAS
|
Say Y if you want to use wireless LAN adapters based on the ZyDAS
|
||||||
|
|
|
@ -2,6 +2,8 @@ config HOSTAP
|
||||||
tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
|
tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
|
||||||
depends on WLAN_80211
|
depends on WLAN_80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
|
select WEXT_PRIV
|
||||||
select CRYPTO
|
select CRYPTO
|
||||||
select CRYPTO_ARC4
|
select CRYPTO_ARC4
|
||||||
select CRYPTO_ECB
|
select CRYPTO_ECB
|
||||||
|
|
|
@ -6,6 +6,8 @@ config IPW2100
|
||||||
tristate "Intel PRO/Wireless 2100 Network Connection"
|
tristate "Intel PRO/Wireless 2100 Network Connection"
|
||||||
depends on PCI && WLAN_80211 && CFG80211
|
depends on PCI && WLAN_80211 && CFG80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
|
select WEXT_PRIV
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
select LIB80211
|
select LIB80211
|
||||||
select LIBIPW
|
select LIBIPW
|
||||||
|
@ -65,6 +67,8 @@ config IPW2200
|
||||||
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
|
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
|
||||||
depends on PCI && WLAN_80211 && CFG80211
|
depends on PCI && WLAN_80211 && CFG80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
|
select WEXT_PRIV
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
select LIB80211
|
select LIB80211
|
||||||
select LIBIPW
|
select LIBIPW
|
||||||
|
@ -152,6 +156,7 @@ config LIBIPW
|
||||||
tristate
|
tristate
|
||||||
depends on PCI && WLAN_80211 && CFG80211
|
depends on PCI && WLAN_80211 && CFG80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
select CRYPTO
|
select CRYPTO
|
||||||
select CRYPTO_ARC4
|
select CRYPTO_ARC4
|
||||||
select CRYPTO_ECB
|
select CRYPTO_ECB
|
||||||
|
|
|
@ -3,6 +3,8 @@ config HERMES
|
||||||
depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
|
depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
|
||||||
depends on CFG80211
|
depends on CFG80211
|
||||||
select WIRELESS_EXT
|
select WIRELESS_EXT
|
||||||
|
select WEXT_SPY
|
||||||
|
select WEXT_PRIV
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
select CRYPTO
|
select CRYPTO
|
||||||
select CRYPTO_MICHAEL_MIC
|
select CRYPTO_MICHAEL_MIC
|
||||||
|
|
|
@ -1171,6 +1171,10 @@ struct wiphy {
|
||||||
struct net *_net;
|
struct net *_net;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
|
const struct iw_handler_def *wext;
|
||||||
|
#endif
|
||||||
|
|
||||||
char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
|
char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1345,7 +1349,7 @@ struct wireless_dev {
|
||||||
struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
|
struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
|
||||||
struct cfg80211_internal_bss *current_bss; /* associated / joined */
|
struct cfg80211_internal_bss *current_bss; /* associated / joined */
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
/* wext data */
|
/* wext data */
|
||||||
struct {
|
struct {
|
||||||
struct cfg80211_ibss_params ibss;
|
struct cfg80211_ibss_params ibss;
|
||||||
|
|
|
@ -323,18 +323,19 @@ typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
|
||||||
*/
|
*/
|
||||||
struct iw_handler_def
|
struct iw_handler_def
|
||||||
{
|
{
|
||||||
/* Number of handlers defined (more precisely, index of the
|
|
||||||
* last defined handler + 1) */
|
|
||||||
__u16 num_standard;
|
|
||||||
__u16 num_private;
|
|
||||||
/* Number of private arg description */
|
|
||||||
__u16 num_private_args;
|
|
||||||
|
|
||||||
/* Array of handlers for standard ioctls
|
/* Array of handlers for standard ioctls
|
||||||
* We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT]
|
* We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT]
|
||||||
*/
|
*/
|
||||||
const iw_handler * standard;
|
const iw_handler * standard;
|
||||||
|
/* Number of handlers defined (more precisely, index of the
|
||||||
|
* last defined handler + 1) */
|
||||||
|
__u16 num_standard;
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEXT_PRIV
|
||||||
|
__u16 num_private;
|
||||||
|
/* Number of private arg description */
|
||||||
|
__u16 num_private_args;
|
||||||
/* Array of handlers for private ioctls
|
/* Array of handlers for private ioctls
|
||||||
* Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
|
* Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
|
||||||
*/
|
*/
|
||||||
|
@ -344,6 +345,7 @@ struct iw_handler_def
|
||||||
* can put it in any order you want and should not leave holes...
|
* can put it in any order you want and should not leave holes...
|
||||||
* We will automatically export that to user space... */
|
* We will automatically export that to user space... */
|
||||||
const struct iw_priv_args * private_args;
|
const struct iw_priv_args * private_args;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* New location of get_wireless_stats, to de-bloat struct net_device.
|
/* New location of get_wireless_stats, to de-bloat struct net_device.
|
||||||
* The old pointer in struct net_device will be gradually phased
|
* The old pointer in struct net_device will be gradually phased
|
||||||
|
|
|
@ -80,7 +80,7 @@ struct net {
|
||||||
#ifdef CONFIG_XFRM
|
#ifdef CONFIG_XFRM
|
||||||
struct netns_xfrm xfrm;
|
struct netns_xfrm xfrm;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_WEXT_CORE
|
||||||
struct sk_buff_head wext_nlevents;
|
struct sk_buff_head wext_nlevents;
|
||||||
#endif
|
#endif
|
||||||
struct net_generic *gen;
|
struct net_generic *gen;
|
||||||
|
|
|
@ -1,29 +1,19 @@
|
||||||
#ifndef __NET_WEXT_H
|
#ifndef __NET_WEXT_H
|
||||||
#define __NET_WEXT_H
|
#define __NET_WEXT_H
|
||||||
|
|
||||||
/*
|
#include <net/iw_handler.h>
|
||||||
* wireless extensions interface to the core code
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct net;
|
struct net;
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_WEXT_CORE
|
||||||
extern int wext_proc_init(struct net *net);
|
|
||||||
extern void wext_proc_exit(struct net *net);
|
|
||||||
extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
|
extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
|
||||||
void __user *arg);
|
void __user *arg);
|
||||||
extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
|
extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
|
||||||
unsigned long arg);
|
unsigned long arg);
|
||||||
|
|
||||||
extern struct iw_statistics *get_wireless_stats(struct net_device *dev);
|
extern struct iw_statistics *get_wireless_stats(struct net_device *dev);
|
||||||
|
extern int call_commit_handler(struct net_device *dev);
|
||||||
#else
|
#else
|
||||||
static inline int wext_proc_init(struct net *net)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static inline void wext_proc_exit(struct net *net)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
|
static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
|
||||||
void __user *arg)
|
void __user *arg)
|
||||||
{
|
{
|
||||||
|
@ -36,4 +26,35 @@ static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEXT_PROC
|
||||||
|
extern int wext_proc_init(struct net *net);
|
||||||
|
extern void wext_proc_exit(struct net *net);
|
||||||
|
#else
|
||||||
|
static inline int wext_proc_init(struct net *net)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline void wext_proc_exit(struct net *net)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEXT_PRIV
|
||||||
|
int ioctl_private_call(struct net_device *dev, struct iwreq *iwr,
|
||||||
|
unsigned int cmd, struct iw_request_info *info,
|
||||||
|
iw_handler handler);
|
||||||
|
int compat_private_call(struct net_device *dev, struct iwreq *iwr,
|
||||||
|
unsigned int cmd, struct iw_request_info *info,
|
||||||
|
iw_handler handler);
|
||||||
|
int iw_handler_get_private(struct net_device * dev,
|
||||||
|
struct iw_request_info * info,
|
||||||
|
union iwreq_data * wrqu,
|
||||||
|
char * extra);
|
||||||
|
#else
|
||||||
|
#define ioctl_private_call NULL
|
||||||
|
#define compat_private_call NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* __NET_WEXT_H */
|
#endif /* __NET_WEXT_H */
|
||||||
|
|
|
@ -543,8 +543,12 @@ int netdev_register_kobject(struct net_device *net)
|
||||||
*groups++ = &netstat_group;
|
*groups++ = &netstat_group;
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT_SYSFS
|
#ifdef CONFIG_WIRELESS_EXT_SYSFS
|
||||||
if (net->wireless_handlers || net->ieee80211_ptr)
|
if (net->ieee80211_ptr)
|
||||||
*groups++ = &wireless_group;
|
*groups++ = &wireless_group;
|
||||||
|
#ifdef CONFIG_WIRELESS_EXT
|
||||||
|
else if (net->wireless_handlers)
|
||||||
|
*groups++ = &wireless_group;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif /* CONFIG_SYSFS */
|
#endif /* CONFIG_SYSFS */
|
||||||
|
|
||||||
|
|
|
@ -905,11 +905,11 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
|
||||||
if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
|
if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
|
||||||
err = dev_ioctl(net, cmd, argp);
|
err = dev_ioctl(net, cmd, argp);
|
||||||
} else
|
} else
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_WEXT_CORE
|
||||||
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
|
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
|
||||||
err = dev_ioctl(net, cmd, argp);
|
err = dev_ioctl(net, cmd, argp);
|
||||||
} else
|
} else
|
||||||
#endif /* CONFIG_WIRELESS_EXT */
|
#endif
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case FIOSETOWN:
|
case FIOSETOWN:
|
||||||
case SIOCSPGRP:
|
case SIOCSPGRP:
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
config WIRELESS_EXT
|
||||||
|
bool
|
||||||
|
|
||||||
|
config WEXT_CORE
|
||||||
|
def_bool y
|
||||||
|
depends on CFG80211_WEXT || WIRELESS_EXT
|
||||||
|
|
||||||
|
config WEXT_PROC
|
||||||
|
def_bool y
|
||||||
|
depends on PROC_FS
|
||||||
|
depends on WEXT_CORE
|
||||||
|
|
||||||
|
config WEXT_SPY
|
||||||
|
bool
|
||||||
|
|
||||||
|
config WEXT_PRIV
|
||||||
|
bool
|
||||||
|
|
||||||
config CFG80211
|
config CFG80211
|
||||||
tristate "cfg80211 - wireless configuration API"
|
tristate "cfg80211 - wireless configuration API"
|
||||||
depends on RFKILL || !RFKILL
|
depends on RFKILL || !RFKILL
|
||||||
|
@ -56,6 +74,12 @@ config CFG80211_REG_DEBUG
|
||||||
|
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
|
config CFG80211_DEFAULT_PS_VALUE
|
||||||
|
int
|
||||||
|
default 1 if CFG80211_DEFAULT_PS
|
||||||
|
default 0
|
||||||
|
depends on CFG80211
|
||||||
|
|
||||||
config CFG80211_DEFAULT_PS
|
config CFG80211_DEFAULT_PS
|
||||||
bool "enable powersave by default"
|
bool "enable powersave by default"
|
||||||
depends on CFG80211
|
depends on CFG80211
|
||||||
|
@ -67,14 +91,10 @@ config CFG80211_DEFAULT_PS
|
||||||
applications instead -- they need to register their network
|
applications instead -- they need to register their network
|
||||||
latency requirement, see Documentation/power/pm_qos_interface.txt.
|
latency requirement, see Documentation/power/pm_qos_interface.txt.
|
||||||
|
|
||||||
config CFG80211_DEFAULT_PS_VALUE
|
|
||||||
int
|
|
||||||
default 1 if CFG80211_DEFAULT_PS
|
|
||||||
default 0
|
|
||||||
|
|
||||||
config CFG80211_DEBUGFS
|
config CFG80211_DEBUGFS
|
||||||
bool "cfg80211 DebugFS entries"
|
bool "cfg80211 DebugFS entries"
|
||||||
depends on CFG80211 && DEBUG_FS
|
depends on CFG80211
|
||||||
|
depends on DEBUG_FS
|
||||||
---help---
|
---help---
|
||||||
You can enable this if you want to debugfs entries for cfg80211.
|
You can enable this if you want to debugfs entries for cfg80211.
|
||||||
|
|
||||||
|
@ -83,6 +103,7 @@ config CFG80211_DEBUGFS
|
||||||
config WIRELESS_OLD_REGULATORY
|
config WIRELESS_OLD_REGULATORY
|
||||||
bool "Old wireless static regulatory definitions"
|
bool "Old wireless static regulatory definitions"
|
||||||
default n
|
default n
|
||||||
|
depends on CFG80211
|
||||||
---help---
|
---help---
|
||||||
This option enables the old static regulatory information
|
This option enables the old static regulatory information
|
||||||
and uses it within the new framework. This option is available
|
and uses it within the new framework. This option is available
|
||||||
|
@ -94,20 +115,19 @@ config WIRELESS_OLD_REGULATORY
|
||||||
|
|
||||||
Say N and if you say Y, please tell us why. The default is N.
|
Say N and if you say Y, please tell us why. The default is N.
|
||||||
|
|
||||||
config WIRELESS_EXT
|
config CFG80211_WEXT
|
||||||
bool "Wireless extensions"
|
bool "cfg80211 wireless extensions compatibility"
|
||||||
|
depends on CFG80211
|
||||||
|
select WEXT_CORE
|
||||||
default y
|
default y
|
||||||
---help---
|
help
|
||||||
This option enables the legacy wireless extensions
|
Enable this option if you need old userspace for wireless
|
||||||
(wireless network interface configuration via ioctls.)
|
extensions with cfg80211-based drivers.
|
||||||
|
|
||||||
Say Y unless you've upgraded all your userspace to use
|
|
||||||
nl80211 instead of wireless extensions.
|
|
||||||
|
|
||||||
config WIRELESS_EXT_SYSFS
|
config WIRELESS_EXT_SYSFS
|
||||||
bool "Wireless extensions sysfs files"
|
bool "Wireless extensions sysfs files"
|
||||||
default y
|
default y
|
||||||
depends on WIRELESS_EXT && SYSFS
|
depends on WEXT_CORE && SYSFS
|
||||||
help
|
help
|
||||||
This option enables the deprecated wireless statistics
|
This option enables the deprecated wireless statistics
|
||||||
files in /sys/class/net/*/wireless/. The same information
|
files in /sys/class/net/*/wireless/. The same information
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
obj-$(CONFIG_WIRELESS_EXT) += wext.o
|
|
||||||
obj-$(CONFIG_CFG80211) += cfg80211.o
|
obj-$(CONFIG_CFG80211) += cfg80211.o
|
||||||
obj-$(CONFIG_LIB80211) += lib80211.o
|
obj-$(CONFIG_LIB80211) += lib80211.o
|
||||||
obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
|
obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
|
||||||
obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
|
obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
|
||||||
obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
|
obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_WEXT_CORE) += wext-core.o
|
||||||
|
obj-$(CONFIG_WEXT_PROC) += wext-proc.o
|
||||||
|
obj-$(CONFIG_WEXT_SPY) += wext-spy.o
|
||||||
|
obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
|
||||||
|
|
||||||
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
|
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
|
||||||
cfg80211-y += mlme.o ibss.o sme.o chan.o
|
cfg80211-y += mlme.o ibss.o sme.o chan.o
|
||||||
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
|
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
|
||||||
cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o
|
cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
|
||||||
|
|
||||||
ccflags-y += -D__CHECK_ENDIAN__
|
ccflags-y += -D__CHECK_ENDIAN__
|
||||||
|
|
|
@ -358,6 +358,10 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
|
||||||
INIT_LIST_HEAD(&rdev->bss_list);
|
INIT_LIST_HEAD(&rdev->bss_list);
|
||||||
INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
|
INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
|
||||||
|
|
||||||
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
|
rdev->wiphy.wext = &cfg80211_wext_handler;
|
||||||
|
#endif
|
||||||
|
|
||||||
device_initialize(&rdev->wiphy.dev);
|
device_initialize(&rdev->wiphy.dev);
|
||||||
rdev->wiphy.dev.class = &ieee80211_class;
|
rdev->wiphy.dev.class = &ieee80211_class;
|
||||||
rdev->wiphy.dev.platform_data = rdev;
|
rdev->wiphy.dev.platform_data = rdev;
|
||||||
|
@ -672,9 +676,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||||
wdev->netdev = dev;
|
wdev->netdev = dev;
|
||||||
wdev->sme_state = CFG80211_SME_IDLE;
|
wdev->sme_state = CFG80211_SME_IDLE;
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
if (!dev->wireless_handlers)
|
|
||||||
dev->wireless_handlers = &cfg80211_wext_handler;
|
|
||||||
wdev->wext.default_key = -1;
|
wdev->wext.default_key = -1;
|
||||||
wdev->wext.default_mgmt_key = -1;
|
wdev->wext.default_mgmt_key = -1;
|
||||||
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||||
|
@ -696,7 +698,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
kfree(wdev->wext.ie);
|
kfree(wdev->wext.ie);
|
||||||
wdev->wext.ie = NULL;
|
wdev->wext.ie = NULL;
|
||||||
wdev->wext.ie_len = 0;
|
wdev->wext.ie_len = 0;
|
||||||
|
@ -728,7 +730,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
cfg80211_lock_rdev(rdev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
@ -766,7 +768,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||||
sysfs_remove_link(&dev->dev.kobj, "phy80211");
|
sysfs_remove_link(&dev->dev.kobj, "phy80211");
|
||||||
list_del_init(&wdev->list);
|
list_del_init(&wdev->list);
|
||||||
rdev->devlist_generation++;
|
rdev->devlist_generation++;
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
kfree(wdev->wext.keys);
|
kfree(wdev->wext.keys);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
struct cfg80211_bss *bss;
|
struct cfg80211_bss *bss;
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
union iwreq_data wrqu;
|
union iwreq_data wrqu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
||||||
|
|
||||||
nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
|
nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
memset(&wrqu, 0, sizeof(wrqu));
|
memset(&wrqu, 0, sizeof(wrqu));
|
||||||
memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
|
memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
|
||||||
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
|
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
|
||||||
|
@ -96,7 +96,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
||||||
kfree(wdev->connect_keys);
|
kfree(wdev->connect_keys);
|
||||||
wdev->connect_keys = connkeys;
|
wdev->connect_keys = connkeys;
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
wdev->wext.ibss.channel = params->channel;
|
wdev->wext.ibss.channel = params->channel;
|
||||||
#endif
|
#endif
|
||||||
err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
|
err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
|
||||||
|
@ -154,7 +154,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
|
||||||
|
|
||||||
wdev->current_bss = NULL;
|
wdev->current_bss = NULL;
|
||||||
wdev->ssid_len = 0;
|
wdev->ssid_len = 0;
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
if (!nowext)
|
if (!nowext)
|
||||||
wdev->wext.ibss.ssid_len = 0;
|
wdev->wext.ibss.ssid_len = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -203,7 +203,7 @@ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev)
|
struct wireless_dev *wdev)
|
||||||
{
|
{
|
||||||
|
|
|
@ -331,7 +331,7 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
|
||||||
{
|
{
|
||||||
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
union iwreq_data wrqu;
|
union iwreq_data wrqu;
|
||||||
char *buf = kmalloc(128, gfp);
|
char *buf = kmalloc(128, gfp);
|
||||||
|
|
||||||
|
|
|
@ -1264,7 +1264,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (!err)
|
if (!err)
|
||||||
err = func(&rdev->wiphy, dev, key.idx);
|
err = func(&rdev->wiphy, dev, key.idx);
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (func == rdev->ops->set_default_key)
|
if (func == rdev->ops->set_default_key)
|
||||||
dev->ieee80211_ptr->wext.default_key = key.idx;
|
dev->ieee80211_ptr->wext.default_key = key.idx;
|
||||||
|
@ -1365,7 +1365,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (!err)
|
if (!err)
|
||||||
err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
|
err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (key.idx == dev->ieee80211_ptr->wext.default_key)
|
if (key.idx == dev->ieee80211_ptr->wext.default_key)
|
||||||
dev->ieee80211_ptr->wext.default_key = -1;
|
dev->ieee80211_ptr->wext.default_key = -1;
|
||||||
|
|
|
@ -22,7 +22,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
|
||||||
{
|
{
|
||||||
struct cfg80211_scan_request *request;
|
struct cfg80211_scan_request *request;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
union iwreq_data wrqu;
|
union iwreq_data wrqu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
|
||||||
else
|
else
|
||||||
nl80211_send_scan_done(rdev, dev);
|
nl80211_send_scan_done(rdev, dev);
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
if (!request->aborted) {
|
if (!request->aborted) {
|
||||||
memset(&wrqu, 0, sizeof(wrqu));
|
memset(&wrqu, 0, sizeof(wrqu));
|
||||||
|
|
||||||
|
@ -592,7 +592,7 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_unlink_bss);
|
EXPORT_SYMBOL(cfg80211_unlink_bss);
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
int cfg80211_wext_siwscan(struct net_device *dev,
|
int cfg80211_wext_siwscan(struct net_device *dev,
|
||||||
struct iw_request_info *info,
|
struct iw_request_info *info,
|
||||||
union iwreq_data *wrqu, char *extra)
|
union iwreq_data *wrqu, char *extra)
|
||||||
|
|
|
@ -345,7 +345,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
u8 *country_ie;
|
u8 *country_ie;
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
union iwreq_data wrqu;
|
union iwreq_data wrqu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -362,7 +362,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||||
resp_ie, resp_ie_len,
|
resp_ie, resp_ie_len,
|
||||||
status, GFP_KERNEL);
|
status, GFP_KERNEL);
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
if (wextev) {
|
if (wextev) {
|
||||||
if (req_ie && status == WLAN_STATUS_SUCCESS) {
|
if (req_ie && status == WLAN_STATUS_SUCCESS) {
|
||||||
memset(&wrqu, 0, sizeof(wrqu));
|
memset(&wrqu, 0, sizeof(wrqu));
|
||||||
|
@ -477,7 +477,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
|
||||||
const u8 *resp_ie, size_t resp_ie_len)
|
const u8 *resp_ie, size_t resp_ie_len)
|
||||||
{
|
{
|
||||||
struct cfg80211_bss *bss;
|
struct cfg80211_bss *bss;
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
union iwreq_data wrqu;
|
union iwreq_data wrqu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -512,7 +512,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
|
||||||
req_ie, req_ie_len, resp_ie, resp_ie_len,
|
req_ie, req_ie_len, resp_ie, resp_ie_len,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
if (req_ie) {
|
if (req_ie) {
|
||||||
memset(&wrqu, 0, sizeof(wrqu));
|
memset(&wrqu, 0, sizeof(wrqu));
|
||||||
wrqu.data.length = req_ie_len;
|
wrqu.data.length = req_ie_len;
|
||||||
|
@ -573,7 +573,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||||
int i;
|
int i;
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
union iwreq_data wrqu;
|
union iwreq_data wrqu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -631,7 +631,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
|
rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
|
||||||
|
|
||||||
#ifdef CONFIG_WIRELESS_EXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
memset(&wrqu, 0, sizeof(wrqu));
|
memset(&wrqu, 0, sizeof(wrqu));
|
||||||
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
||||||
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
|
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,248 @@
|
||||||
|
/*
|
||||||
|
* This file implement the Wireless Extensions priv API.
|
||||||
|
*
|
||||||
|
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
|
||||||
|
* Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
|
||||||
|
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
|
||||||
|
*
|
||||||
|
* (As all part of the Linux kernel, this file is GPL)
|
||||||
|
*/
|
||||||
|
#include <linux/wireless.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <net/iw_handler.h>
|
||||||
|
#include <net/wext.h>
|
||||||
|
|
||||||
|
int iw_handler_get_private(struct net_device * dev,
|
||||||
|
struct iw_request_info * info,
|
||||||
|
union iwreq_data * wrqu,
|
||||||
|
char * extra)
|
||||||
|
{
|
||||||
|
/* Check if the driver has something to export */
|
||||||
|
if ((dev->wireless_handlers->num_private_args == 0) ||
|
||||||
|
(dev->wireless_handlers->private_args == NULL))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* Check if there is enough buffer up there */
|
||||||
|
if (wrqu->data.length < dev->wireless_handlers->num_private_args) {
|
||||||
|
/* User space can't know in advance how large the buffer
|
||||||
|
* needs to be. Give it a hint, so that we can support
|
||||||
|
* any size buffer we want somewhat efficiently... */
|
||||||
|
wrqu->data.length = dev->wireless_handlers->num_private_args;
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the number of available ioctls. */
|
||||||
|
wrqu->data.length = dev->wireless_handlers->num_private_args;
|
||||||
|
|
||||||
|
/* Copy structure to the user buffer. */
|
||||||
|
memcpy(extra, dev->wireless_handlers->private_args,
|
||||||
|
sizeof(struct iw_priv_args) * wrqu->data.length);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Size (in bytes) of the various private data types */
|
||||||
|
static const char iw_priv_type_size[] = {
|
||||||
|
0, /* IW_PRIV_TYPE_NONE */
|
||||||
|
1, /* IW_PRIV_TYPE_BYTE */
|
||||||
|
1, /* IW_PRIV_TYPE_CHAR */
|
||||||
|
0, /* Not defined */
|
||||||
|
sizeof(__u32), /* IW_PRIV_TYPE_INT */
|
||||||
|
sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */
|
||||||
|
sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */
|
||||||
|
0, /* Not defined */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_priv_size(__u16 args)
|
||||||
|
{
|
||||||
|
int num = args & IW_PRIV_SIZE_MASK;
|
||||||
|
int type = (args & IW_PRIV_TYPE_MASK) >> 12;
|
||||||
|
|
||||||
|
return num * iw_priv_type_size[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adjust_priv_size(__u16 args, struct iw_point *iwp)
|
||||||
|
{
|
||||||
|
int num = iwp->length;
|
||||||
|
int max = args & IW_PRIV_SIZE_MASK;
|
||||||
|
int type = (args & IW_PRIV_TYPE_MASK) >> 12;
|
||||||
|
|
||||||
|
/* Make sure the driver doesn't goof up */
|
||||||
|
if (max < num)
|
||||||
|
num = max;
|
||||||
|
|
||||||
|
return num * iw_priv_type_size[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper to call a private Wireless Extension handler.
|
||||||
|
* We do various checks and also take care of moving data between
|
||||||
|
* user space and kernel space.
|
||||||
|
* It's not as nice and slimline as the standard wrapper. The cause
|
||||||
|
* is struct iw_priv_args, which was not really designed for the
|
||||||
|
* job we are going here.
|
||||||
|
*
|
||||||
|
* IMPORTANT : This function prevent to set and get data on the same
|
||||||
|
* IOCTL and enforce the SET/GET convention. Not doing it would be
|
||||||
|
* far too hairy...
|
||||||
|
* If you need to set and get data at the same time, please don't use
|
||||||
|
* a iw_handler but process it in your ioctl handler (i.e. use the
|
||||||
|
* old driver API).
|
||||||
|
*/
|
||||||
|
static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd,
|
||||||
|
const struct iw_priv_args **descrp)
|
||||||
|
{
|
||||||
|
const struct iw_priv_args *descr;
|
||||||
|
int i, extra_size;
|
||||||
|
|
||||||
|
descr = NULL;
|
||||||
|
for (i = 0; i < dev->wireless_handlers->num_private_args; i++) {
|
||||||
|
if (cmd == dev->wireless_handlers->private_args[i].cmd) {
|
||||||
|
descr = &dev->wireless_handlers->private_args[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extra_size = 0;
|
||||||
|
if (descr) {
|
||||||
|
if (IW_IS_SET(cmd)) {
|
||||||
|
int offset = 0; /* For sub-ioctls */
|
||||||
|
/* Check for sub-ioctl handler */
|
||||||
|
if (descr->name[0] == '\0')
|
||||||
|
/* Reserve one int for sub-ioctl index */
|
||||||
|
offset = sizeof(__u32);
|
||||||
|
|
||||||
|
/* Size of set arguments */
|
||||||
|
extra_size = get_priv_size(descr->set_args);
|
||||||
|
|
||||||
|
/* Does it fits in iwr ? */
|
||||||
|
if ((descr->set_args & IW_PRIV_SIZE_FIXED) &&
|
||||||
|
((extra_size + offset) <= IFNAMSIZ))
|
||||||
|
extra_size = 0;
|
||||||
|
} else {
|
||||||
|
/* Size of get arguments */
|
||||||
|
extra_size = get_priv_size(descr->get_args);
|
||||||
|
|
||||||
|
/* Does it fits in iwr ? */
|
||||||
|
if ((descr->get_args & IW_PRIV_SIZE_FIXED) &&
|
||||||
|
(extra_size <= IFNAMSIZ))
|
||||||
|
extra_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*descrp = descr;
|
||||||
|
return extra_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd,
|
||||||
|
const struct iw_priv_args *descr,
|
||||||
|
iw_handler handler, struct net_device *dev,
|
||||||
|
struct iw_request_info *info, int extra_size)
|
||||||
|
{
|
||||||
|
char *extra;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* Check what user space is giving us */
|
||||||
|
if (IW_IS_SET(cmd)) {
|
||||||
|
if (!iwp->pointer && iwp->length != 0)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK))
|
||||||
|
return -E2BIG;
|
||||||
|
} else if (!iwp->pointer)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
extra = kmalloc(extra_size, GFP_KERNEL);
|
||||||
|
if (!extra)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* If it is a SET, get all the extra data in here */
|
||||||
|
if (IW_IS_SET(cmd) && (iwp->length != 0)) {
|
||||||
|
if (copy_from_user(extra, iwp->pointer, extra_size)) {
|
||||||
|
err = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the handler */
|
||||||
|
err = handler(dev, info, (union iwreq_data *) iwp, extra);
|
||||||
|
|
||||||
|
/* If we have something to return to the user */
|
||||||
|
if (!err && IW_IS_GET(cmd)) {
|
||||||
|
/* Adjust for the actual length if it's variable,
|
||||||
|
* avoid leaking kernel bits outside.
|
||||||
|
*/
|
||||||
|
if (!(descr->get_args & IW_PRIV_SIZE_FIXED))
|
||||||
|
extra_size = adjust_priv_size(descr->get_args, iwp);
|
||||||
|
|
||||||
|
if (copy_to_user(iwp->pointer, extra, extra_size))
|
||||||
|
err = -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree(extra);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ioctl_private_call(struct net_device *dev, struct iwreq *iwr,
|
||||||
|
unsigned int cmd, struct iw_request_info *info,
|
||||||
|
iw_handler handler)
|
||||||
|
{
|
||||||
|
int extra_size = 0, ret = -EINVAL;
|
||||||
|
const struct iw_priv_args *descr;
|
||||||
|
|
||||||
|
extra_size = get_priv_descr_and_size(dev, cmd, &descr);
|
||||||
|
|
||||||
|
/* Check if we have a pointer to user space data or not. */
|
||||||
|
if (extra_size == 0) {
|
||||||
|
/* No extra arguments. Trivial to handle */
|
||||||
|
ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u));
|
||||||
|
} else {
|
||||||
|
ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr,
|
||||||
|
handler, dev, info, extra_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call commit handler if needed and defined */
|
||||||
|
if (ret == -EIWCOMMIT)
|
||||||
|
ret = call_commit_handler(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
int compat_private_call(struct net_device *dev, struct iwreq *iwr,
|
||||||
|
unsigned int cmd, struct iw_request_info *info,
|
||||||
|
iw_handler handler)
|
||||||
|
{
|
||||||
|
const struct iw_priv_args *descr;
|
||||||
|
int ret, extra_size;
|
||||||
|
|
||||||
|
extra_size = get_priv_descr_and_size(dev, cmd, &descr);
|
||||||
|
|
||||||
|
/* Check if we have a pointer to user space data or not. */
|
||||||
|
if (extra_size == 0) {
|
||||||
|
/* No extra arguments. Trivial to handle */
|
||||||
|
ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u));
|
||||||
|
} else {
|
||||||
|
struct compat_iw_point *iwp_compat;
|
||||||
|
struct iw_point iwp;
|
||||||
|
|
||||||
|
iwp_compat = (struct compat_iw_point *) &iwr->u.data;
|
||||||
|
iwp.pointer = compat_ptr(iwp_compat->pointer);
|
||||||
|
iwp.length = iwp_compat->length;
|
||||||
|
iwp.flags = iwp_compat->flags;
|
||||||
|
|
||||||
|
ret = ioctl_private_iw_point(&iwp, cmd, descr,
|
||||||
|
handler, dev, info, extra_size);
|
||||||
|
|
||||||
|
iwp_compat->pointer = ptr_to_compat(iwp.pointer);
|
||||||
|
iwp_compat->length = iwp.length;
|
||||||
|
iwp_compat->flags = iwp.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call commit handler if needed and defined */
|
||||||
|
if (ret == -EIWCOMMIT)
|
||||||
|
ret = call_commit_handler(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* This file implement the Wireless Extensions proc API.
|
||||||
|
*
|
||||||
|
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
|
||||||
|
* Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
|
||||||
|
*
|
||||||
|
* (As all part of the Linux kernel, this file is GPL)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The /proc/net/wireless file is a human readable user-space interface
|
||||||
|
* exporting various wireless specific statistics from the wireless devices.
|
||||||
|
* This is the most popular part of the Wireless Extensions ;-)
|
||||||
|
*
|
||||||
|
* This interface is a pure clone of /proc/net/dev (in net/core/dev.c).
|
||||||
|
* The content of the file is basically the content of "struct iw_statistics".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/proc_fs.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/wireless.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
#include <net/iw_handler.h>
|
||||||
|
#include <net/wext.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void wireless_seq_printf_stats(struct seq_file *seq,
|
||||||
|
struct net_device *dev)
|
||||||
|
{
|
||||||
|
/* Get stats from the driver */
|
||||||
|
struct iw_statistics *stats = get_wireless_stats(dev);
|
||||||
|
static struct iw_statistics nullstats = {};
|
||||||
|
|
||||||
|
/* show device if it's wireless regardless of current stats */
|
||||||
|
if (!stats) {
|
||||||
|
#ifdef CONFIG_WIRELESS_EXT
|
||||||
|
if (dev->wireless_handlers)
|
||||||
|
stats = &nullstats;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_CFG80211
|
||||||
|
if (dev->ieee80211_ptr)
|
||||||
|
stats = &nullstats;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats) {
|
||||||
|
seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d "
|
||||||
|
"%6d %6d %6d\n",
|
||||||
|
dev->name, stats->status, stats->qual.qual,
|
||||||
|
stats->qual.updated & IW_QUAL_QUAL_UPDATED
|
||||||
|
? '.' : ' ',
|
||||||
|
((__s32) stats->qual.level) -
|
||||||
|
((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
|
||||||
|
stats->qual.updated & IW_QUAL_LEVEL_UPDATED
|
||||||
|
? '.' : ' ',
|
||||||
|
((__s32) stats->qual.noise) -
|
||||||
|
((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
|
||||||
|
stats->qual.updated & IW_QUAL_NOISE_UPDATED
|
||||||
|
? '.' : ' ',
|
||||||
|
stats->discard.nwid, stats->discard.code,
|
||||||
|
stats->discard.fragment, stats->discard.retries,
|
||||||
|
stats->discard.misc, stats->miss.beacon);
|
||||||
|
|
||||||
|
if (stats != &nullstats)
|
||||||
|
stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
* Print info for /proc/net/wireless (print all entries)
|
||||||
|
*/
|
||||||
|
static int wireless_dev_seq_show(struct seq_file *seq, void *v)
|
||||||
|
{
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
|
if (v == SEQ_START_TOKEN)
|
||||||
|
seq_printf(seq, "Inter-| sta-| Quality | Discarded "
|
||||||
|
"packets | Missed | WE\n"
|
||||||
|
" face | tus | link level noise | nwid "
|
||||||
|
"crypt frag retry misc | beacon | %d\n",
|
||||||
|
WIRELESS_EXT);
|
||||||
|
else
|
||||||
|
wireless_seq_printf_stats(seq, v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos)
|
||||||
|
{
|
||||||
|
struct net *net = seq_file_net(seq);
|
||||||
|
loff_t off;
|
||||||
|
struct net_device *dev;
|
||||||
|
|
||||||
|
rtnl_lock();
|
||||||
|
if (!*pos)
|
||||||
|
return SEQ_START_TOKEN;
|
||||||
|
|
||||||
|
off = 1;
|
||||||
|
for_each_netdev(net, dev)
|
||||||
|
if (off++ == *pos)
|
||||||
|
return dev;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||||
|
{
|
||||||
|
struct net *net = seq_file_net(seq);
|
||||||
|
|
||||||
|
++*pos;
|
||||||
|
|
||||||
|
return v == SEQ_START_TOKEN ?
|
||||||
|
first_net_device(net) : next_net_device(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wireless_dev_seq_stop(struct seq_file *seq, void *v)
|
||||||
|
{
|
||||||
|
rtnl_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct seq_operations wireless_seq_ops = {
|
||||||
|
.start = wireless_dev_seq_start,
|
||||||
|
.next = wireless_dev_seq_next,
|
||||||
|
.stop = wireless_dev_seq_stop,
|
||||||
|
.show = wireless_dev_seq_show,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int seq_open_wireless(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return seq_open_net(inode, file, &wireless_seq_ops,
|
||||||
|
sizeof(struct seq_net_private));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations wireless_seq_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = seq_open_wireless,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = seq_release_net,
|
||||||
|
};
|
||||||
|
|
||||||
|
int wext_proc_init(struct net *net)
|
||||||
|
{
|
||||||
|
/* Create /proc/net/wireless entry */
|
||||||
|
if (!proc_net_fops_create(net, "wireless", S_IRUGO, &wireless_seq_fops))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wext_proc_exit(struct net *net)
|
||||||
|
{
|
||||||
|
proc_net_remove(net, "wireless");
|
||||||
|
}
|
|
@ -0,0 +1,231 @@
|
||||||
|
/*
|
||||||
|
* This file implement the Wireless Extensions spy API.
|
||||||
|
*
|
||||||
|
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
|
||||||
|
* Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
|
||||||
|
*
|
||||||
|
* (As all part of the Linux kernel, this file is GPL)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/wireless.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <net/iw_handler.h>
|
||||||
|
#include <net/arp.h>
|
||||||
|
#include <net/wext.h>
|
||||||
|
|
||||||
|
static inline struct iw_spy_data *get_spydata(struct net_device *dev)
|
||||||
|
{
|
||||||
|
/* This is the new way */
|
||||||
|
if (dev->wireless_data)
|
||||||
|
return dev->wireless_data->spy_data;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iw_handler_set_spy(struct net_device * dev,
|
||||||
|
struct iw_request_info * info,
|
||||||
|
union iwreq_data * wrqu,
|
||||||
|
char * extra)
|
||||||
|
{
|
||||||
|
struct iw_spy_data * spydata = get_spydata(dev);
|
||||||
|
struct sockaddr * address = (struct sockaddr *) extra;
|
||||||
|
|
||||||
|
/* Make sure driver is not buggy or using the old API */
|
||||||
|
if (!spydata)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* Disable spy collection while we copy the addresses.
|
||||||
|
* While we copy addresses, any call to wireless_spy_update()
|
||||||
|
* will NOP. This is OK, as anyway the addresses are changing. */
|
||||||
|
spydata->spy_number = 0;
|
||||||
|
|
||||||
|
/* We want to operate without locking, because wireless_spy_update()
|
||||||
|
* most likely will happen in the interrupt handler, and therefore
|
||||||
|
* have its own locking constraints and needs performance.
|
||||||
|
* The rtnl_lock() make sure we don't race with the other iw_handlers.
|
||||||
|
* This make sure wireless_spy_update() "see" that the spy list
|
||||||
|
* is temporarily disabled. */
|
||||||
|
smp_wmb();
|
||||||
|
|
||||||
|
/* Are there are addresses to copy? */
|
||||||
|
if (wrqu->data.length > 0) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Copy addresses */
|
||||||
|
for (i = 0; i < wrqu->data.length; i++)
|
||||||
|
memcpy(spydata->spy_address[i], address[i].sa_data,
|
||||||
|
ETH_ALEN);
|
||||||
|
/* Reset stats */
|
||||||
|
memset(spydata->spy_stat, 0,
|
||||||
|
sizeof(struct iw_quality) * IW_MAX_SPY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure above is updated before re-enabling */
|
||||||
|
smp_wmb();
|
||||||
|
|
||||||
|
/* Enable addresses */
|
||||||
|
spydata->spy_number = wrqu->data.length;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iw_handler_set_spy);
|
||||||
|
|
||||||
|
int iw_handler_get_spy(struct net_device * dev,
|
||||||
|
struct iw_request_info * info,
|
||||||
|
union iwreq_data * wrqu,
|
||||||
|
char * extra)
|
||||||
|
{
|
||||||
|
struct iw_spy_data * spydata = get_spydata(dev);
|
||||||
|
struct sockaddr * address = (struct sockaddr *) extra;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Make sure driver is not buggy or using the old API */
|
||||||
|
if (!spydata)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
wrqu->data.length = spydata->spy_number;
|
||||||
|
|
||||||
|
/* Copy addresses. */
|
||||||
|
for (i = 0; i < spydata->spy_number; i++) {
|
||||||
|
memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
|
||||||
|
address[i].sa_family = AF_UNIX;
|
||||||
|
}
|
||||||
|
/* Copy stats to the user buffer (just after). */
|
||||||
|
if (spydata->spy_number > 0)
|
||||||
|
memcpy(extra + (sizeof(struct sockaddr) *spydata->spy_number),
|
||||||
|
spydata->spy_stat,
|
||||||
|
sizeof(struct iw_quality) * spydata->spy_number);
|
||||||
|
/* Reset updated flags. */
|
||||||
|
for (i = 0; i < spydata->spy_number; i++)
|
||||||
|
spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iw_handler_get_spy);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
* Standard Wireless Handler : set spy threshold
|
||||||
|
*/
|
||||||
|
int iw_handler_set_thrspy(struct net_device * dev,
|
||||||
|
struct iw_request_info *info,
|
||||||
|
union iwreq_data * wrqu,
|
||||||
|
char * extra)
|
||||||
|
{
|
||||||
|
struct iw_spy_data * spydata = get_spydata(dev);
|
||||||
|
struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
|
||||||
|
|
||||||
|
/* Make sure driver is not buggy or using the old API */
|
||||||
|
if (!spydata)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* Just do it */
|
||||||
|
memcpy(&(spydata->spy_thr_low), &(threshold->low),
|
||||||
|
2 * sizeof(struct iw_quality));
|
||||||
|
|
||||||
|
/* Clear flag */
|
||||||
|
memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iw_handler_set_thrspy);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
* Standard Wireless Handler : get spy threshold
|
||||||
|
*/
|
||||||
|
int iw_handler_get_thrspy(struct net_device * dev,
|
||||||
|
struct iw_request_info *info,
|
||||||
|
union iwreq_data * wrqu,
|
||||||
|
char * extra)
|
||||||
|
{
|
||||||
|
struct iw_spy_data * spydata = get_spydata(dev);
|
||||||
|
struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
|
||||||
|
|
||||||
|
/* Make sure driver is not buggy or using the old API */
|
||||||
|
if (!spydata)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* Just do it */
|
||||||
|
memcpy(&(threshold->low), &(spydata->spy_thr_low),
|
||||||
|
2 * sizeof(struct iw_quality));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iw_handler_get_thrspy);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
* Prepare and send a Spy Threshold event
|
||||||
|
*/
|
||||||
|
static void iw_send_thrspy_event(struct net_device * dev,
|
||||||
|
struct iw_spy_data * spydata,
|
||||||
|
unsigned char * address,
|
||||||
|
struct iw_quality * wstats)
|
||||||
|
{
|
||||||
|
union iwreq_data wrqu;
|
||||||
|
struct iw_thrspy threshold;
|
||||||
|
|
||||||
|
/* Init */
|
||||||
|
wrqu.data.length = 1;
|
||||||
|
wrqu.data.flags = 0;
|
||||||
|
/* Copy address */
|
||||||
|
memcpy(threshold.addr.sa_data, address, ETH_ALEN);
|
||||||
|
threshold.addr.sa_family = ARPHRD_ETHER;
|
||||||
|
/* Copy stats */
|
||||||
|
memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
|
||||||
|
/* Copy also thresholds */
|
||||||
|
memcpy(&(threshold.low), &(spydata->spy_thr_low),
|
||||||
|
2 * sizeof(struct iw_quality));
|
||||||
|
|
||||||
|
/* Send event to user space */
|
||||||
|
wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
* Call for the driver to update the spy data.
|
||||||
|
* For now, the spy data is a simple array. As the size of the array is
|
||||||
|
* small, this is good enough. If we wanted to support larger number of
|
||||||
|
* spy addresses, we should use something more efficient...
|
||||||
|
*/
|
||||||
|
void wireless_spy_update(struct net_device * dev,
|
||||||
|
unsigned char * address,
|
||||||
|
struct iw_quality * wstats)
|
||||||
|
{
|
||||||
|
struct iw_spy_data * spydata = get_spydata(dev);
|
||||||
|
int i;
|
||||||
|
int match = -1;
|
||||||
|
|
||||||
|
/* Make sure driver is not buggy or using the old API */
|
||||||
|
if (!spydata)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Update all records that match */
|
||||||
|
for (i = 0; i < spydata->spy_number; i++)
|
||||||
|
if (!compare_ether_addr(address, spydata->spy_address[i])) {
|
||||||
|
memcpy(&(spydata->spy_stat[i]), wstats,
|
||||||
|
sizeof(struct iw_quality));
|
||||||
|
match = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate an event if we cross the spy threshold.
|
||||||
|
* To avoid event storms, we have a simple hysteresis : we generate
|
||||||
|
* event only when we go under the low threshold or above the
|
||||||
|
* high threshold. */
|
||||||
|
if (match >= 0) {
|
||||||
|
if (spydata->spy_thr_under[match]) {
|
||||||
|
if (wstats->level > spydata->spy_thr_high.level) {
|
||||||
|
spydata->spy_thr_under[match] = 0;
|
||||||
|
iw_send_thrspy_event(dev, spydata,
|
||||||
|
address, wstats);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (wstats->level < spydata->spy_thr_low.level) {
|
||||||
|
spydata->spy_thr_under[match] = 1;
|
||||||
|
iw_send_thrspy_event(dev, spydata,
|
||||||
|
address, wstats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(wireless_spy_update);
|
Loading…
Reference in New Issue