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"
|
||||
depends on ISA && WLAN_PRE80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
---help---
|
||||
The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is
|
||||
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"
|
||||
depends on PCMCIA && WLAN_PRE80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
help
|
||||
Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA
|
||||
(PC-card) wireless Ethernet networking card to your computer. This
|
||||
|
@ -102,6 +106,7 @@ config PCMCIA_NETWAVE
|
|||
tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
|
||||
depends on PCMCIA && WLAN_PRE80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
help
|
||||
Say Y here if you intend to attach this type of PCMCIA (PC-card)
|
||||
wireless Ethernet networking card to your computer.
|
||||
|
@ -123,6 +128,8 @@ config PCMCIA_RAYCS
|
|||
tristate "Aviator/Raytheon 2.4GHz wireless support"
|
||||
depends on PCMCIA && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
---help---
|
||||
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
|
||||
(PC-card) wireless Ethernet networking card to your computer.
|
||||
|
@ -136,6 +143,7 @@ config LIBERTAS
|
|||
tristate "Marvell 8xxx Libertas WLAN driver support"
|
||||
depends on WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select LIB80211
|
||||
select FW_LOADER
|
||||
---help---
|
||||
|
@ -190,6 +198,8 @@ config AIRO
|
|||
depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN)
|
||||
select WIRELESS_EXT
|
||||
select CRYPTO
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
---help---
|
||||
This is the standard Linux driver to support Cisco/Aironet ISA and
|
||||
PCI 802.11 wireless cards.
|
||||
|
@ -207,6 +217,7 @@ config ATMEL
|
|||
tristate "Atmel at76c50x chipset 802.11b support"
|
||||
depends on (PCI || PCMCIA) && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
select CRC32
|
||||
---help---
|
||||
|
@ -269,7 +280,8 @@ config PCMCIA_WL3501
|
|||
tristate "Planet WL3501 PCMCIA cards"
|
||||
depends on EXPERIMENTAL && PCMCIA && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
---help---
|
||||
select WEXT_SPY
|
||||
help
|
||||
A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
|
||||
It has basic support for Linux wireless extensions and initial
|
||||
micro support for ethtool.
|
||||
|
@ -278,6 +290,8 @@ config PRISM54
|
|||
tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)'
|
||||
depends on PCI && EXPERIMENTAL && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This enables support for FullMAC PCI/Cardbus prism54 devices. This
|
||||
|
@ -300,6 +314,7 @@ config USB_ZD1201
|
|||
tristate "USB ZD1201 based Wireless device support"
|
||||
depends on USB && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
---help---
|
||||
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)"
|
||||
depends on WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select CRYPTO
|
||||
select CRYPTO_ARC4
|
||||
select CRYPTO_ECB
|
||||
|
|
|
@ -6,6 +6,8 @@ config IPW2100
|
|||
tristate "Intel PRO/Wireless 2100 Network Connection"
|
||||
depends on PCI && WLAN_80211 && CFG80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
select LIB80211
|
||||
select LIBIPW
|
||||
|
@ -65,6 +67,8 @@ config IPW2200
|
|||
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
|
||||
depends on PCI && WLAN_80211 && CFG80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
select LIB80211
|
||||
select LIBIPW
|
||||
|
@ -152,6 +156,7 @@ config LIBIPW
|
|||
tristate
|
||||
depends on PCI && WLAN_80211 && CFG80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select CRYPTO
|
||||
select CRYPTO_ARC4
|
||||
select CRYPTO_ECB
|
||||
|
|
|
@ -3,6 +3,8 @@ config HERMES
|
|||
depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
|
||||
depends on CFG80211
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
select CRYPTO
|
||||
select CRYPTO_MICHAEL_MIC
|
||||
|
|
|
@ -1171,6 +1171,10 @@ struct wiphy {
|
|||
struct net *_net;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
const struct iw_handler_def *wext;
|
||||
#endif
|
||||
|
||||
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 *current_bss; /* associated / joined */
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
/* wext data */
|
||||
struct {
|
||||
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
|
||||
{
|
||||
/* 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
|
||||
* We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT]
|
||||
*/
|
||||
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
|
||||
* 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...
|
||||
* We will automatically export that to user space... */
|
||||
const struct iw_priv_args * private_args;
|
||||
#endif
|
||||
|
||||
/* New location of get_wireless_stats, to de-bloat struct net_device.
|
||||
* The old pointer in struct net_device will be gradually phased
|
||||
|
|
|
@ -80,7 +80,7 @@ struct net {
|
|||
#ifdef CONFIG_XFRM
|
||||
struct netns_xfrm xfrm;
|
||||
#endif
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
struct sk_buff_head wext_nlevents;
|
||||
#endif
|
||||
struct net_generic *gen;
|
||||
|
|
|
@ -1,29 +1,19 @@
|
|||
#ifndef __NET_WEXT_H
|
||||
#define __NET_WEXT_H
|
||||
|
||||
/*
|
||||
* wireless extensions interface to the core code
|
||||
*/
|
||||
#include <net/iw_handler.h>
|
||||
|
||||
struct net;
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
extern int wext_proc_init(struct net *net);
|
||||
extern void wext_proc_exit(struct net *net);
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
|
||||
void __user *arg);
|
||||
extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
extern struct iw_statistics *get_wireless_stats(struct net_device *dev);
|
||||
extern int call_commit_handler(struct net_device *dev);
|
||||
#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,
|
||||
void __user *arg)
|
||||
{
|
||||
|
@ -36,4 +26,35 @@ static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
|
|||
}
|
||||
#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 */
|
||||
|
|
|
@ -543,8 +543,12 @@ int netdev_register_kobject(struct net_device *net)
|
|||
*groups++ = &netstat_group;
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT_SYSFS
|
||||
if (net->wireless_handlers || net->ieee80211_ptr)
|
||||
if (net->ieee80211_ptr)
|
||||
*groups++ = &wireless_group;
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
else if (net->wireless_handlers)
|
||||
*groups++ = &wireless_group;
|
||||
#endif
|
||||
#endif
|
||||
#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)) {
|
||||
err = dev_ioctl(net, cmd, argp);
|
||||
} else
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
|
||||
err = dev_ioctl(net, cmd, argp);
|
||||
} else
|
||||
#endif /* CONFIG_WIRELESS_EXT */
|
||||
#endif
|
||||
switch (cmd) {
|
||||
case FIOSETOWN:
|
||||
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
|
||||
tristate "cfg80211 - wireless configuration API"
|
||||
depends on RFKILL || !RFKILL
|
||||
|
@ -56,6 +74,12 @@ config CFG80211_REG_DEBUG
|
|||
|
||||
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
|
||||
bool "enable powersave by default"
|
||||
depends on CFG80211
|
||||
|
@ -67,14 +91,10 @@ config CFG80211_DEFAULT_PS
|
|||
applications instead -- they need to register their network
|
||||
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
|
||||
bool "cfg80211 DebugFS entries"
|
||||
depends on CFG80211 && DEBUG_FS
|
||||
depends on CFG80211
|
||||
depends on DEBUG_FS
|
||||
---help---
|
||||
You can enable this if you want to debugfs entries for cfg80211.
|
||||
|
||||
|
@ -83,6 +103,7 @@ config CFG80211_DEBUGFS
|
|||
config WIRELESS_OLD_REGULATORY
|
||||
bool "Old wireless static regulatory definitions"
|
||||
default n
|
||||
depends on CFG80211
|
||||
---help---
|
||||
This option enables the old static regulatory information
|
||||
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.
|
||||
|
||||
config WIRELESS_EXT
|
||||
bool "Wireless extensions"
|
||||
config CFG80211_WEXT
|
||||
bool "cfg80211 wireless extensions compatibility"
|
||||
depends on CFG80211
|
||||
select WEXT_CORE
|
||||
default y
|
||||
---help---
|
||||
This option enables the legacy wireless extensions
|
||||
(wireless network interface configuration via ioctls.)
|
||||
|
||||
Say Y unless you've upgraded all your userspace to use
|
||||
nl80211 instead of wireless extensions.
|
||||
help
|
||||
Enable this option if you need old userspace for wireless
|
||||
extensions with cfg80211-based drivers.
|
||||
|
||||
config WIRELESS_EXT_SYSFS
|
||||
bool "Wireless extensions sysfs files"
|
||||
default y
|
||||
depends on WIRELESS_EXT && SYSFS
|
||||
depends on WEXT_CORE && SYSFS
|
||||
help
|
||||
This option enables the deprecated wireless statistics
|
||||
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_LIB80211) += lib80211.o
|
||||
obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
|
||||
obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.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 += mlme.o ibss.o sme.o chan.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__
|
||||
|
|
|
@ -358,6 +358,10 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
|
|||
INIT_LIST_HEAD(&rdev->bss_list);
|
||||
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);
|
||||
rdev->wiphy.dev.class = &ieee80211_class;
|
||||
rdev->wiphy.dev.platform_data = rdev;
|
||||
|
@ -672,9 +676,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
|||
wdev->netdev = dev;
|
||||
wdev->sme_state = CFG80211_SME_IDLE;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
if (!dev->wireless_handlers)
|
||||
dev->wireless_handlers = &cfg80211_wext_handler;
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
wdev->wext.default_key = -1;
|
||||
wdev->wext.default_mgmt_key = -1;
|
||||
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
|
@ -696,7 +698,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
|||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
wdev_lock(wdev);
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
kfree(wdev->wext.ie);
|
||||
wdev->wext.ie = NULL;
|
||||
wdev->wext.ie_len = 0;
|
||||
|
@ -728,7 +730,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
|||
mutex_unlock(&rdev->devlist_mtx);
|
||||
dev_put(dev);
|
||||
}
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
cfg80211_lock_rdev(rdev);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(wdev);
|
||||
|
@ -766,7 +768,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
|||
sysfs_remove_link(&dev->dev.kobj, "phy80211");
|
||||
list_del_init(&wdev->list);
|
||||
rdev->devlist_generation++;
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
kfree(wdev->wext.keys);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
|||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_bss *bss;
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
union iwreq_data wrqu;
|
||||
#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,
|
||||
GFP_KERNEL);
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
|
||||
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
|
||||
|
@ -96,7 +96,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
|||
kfree(wdev->connect_keys);
|
||||
wdev->connect_keys = connkeys;
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
wdev->wext.ibss.channel = params->channel;
|
||||
#endif
|
||||
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->ssid_len = 0;
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (!nowext)
|
||||
wdev->wext.ibss.ssid_len = 0;
|
||||
#endif
|
||||
|
@ -203,7 +203,7 @@ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
||||
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 cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
union iwreq_data wrqu;
|
||||
char *buf = kmalloc(128, gfp);
|
||||
|
||||
|
|
|
@ -1264,7 +1264,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!err)
|
||||
err = func(&rdev->wiphy, dev, key.idx);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (!err) {
|
||||
if (func == rdev->ops->set_default_key)
|
||||
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)
|
||||
err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (!err) {
|
||||
if (key.idx == dev->ieee80211_ptr->wext.default_key)
|
||||
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 net_device *dev;
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
union iwreq_data wrqu;
|
||||
#endif
|
||||
|
||||
|
@ -47,7 +47,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
|
|||
else
|
||||
nl80211_send_scan_done(rdev, dev);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (!request->aborted) {
|
||||
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);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
int cfg80211_wext_siwscan(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
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;
|
||||
u8 *country_ie;
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
union iwreq_data wrqu;
|
||||
#endif
|
||||
|
||||
|
@ -362,7 +362,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
|||
resp_ie, resp_ie_len,
|
||||
status, GFP_KERNEL);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (wextev) {
|
||||
if (req_ie && status == WLAN_STATUS_SUCCESS) {
|
||||
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)
|
||||
{
|
||||
struct cfg80211_bss *bss;
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
union iwreq_data wrqu;
|
||||
#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,
|
||||
GFP_KERNEL);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
if (req_ie) {
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
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 cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
int i;
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
union iwreq_data wrqu;
|
||||
#endif
|
||||
|
||||
|
@ -631,7 +631,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
|||
for (i = 0; i < 6; i++)
|
||||
rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_EXT
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
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