forked from mirrors/linux
		
	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
					
				
					 22 changed files with 1248 additions and 1245 deletions
				
			
		|  | @ -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--- | ||||
|  | @ -266,18 +277,21 @@ config AIRO_CS | |||
| 	  Cisco Linux utilities can be used to configure the card. | ||||
| 
 | ||||
| config PCMCIA_WL3501 | ||||
|       tristate "Planet WL3501 PCMCIA cards" | ||||
|       depends on EXPERIMENTAL && PCMCIA && WLAN_80211 | ||||
|       select WIRELESS_EXT | ||||
|        ---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. | ||||
| 	tristate "Planet WL3501 PCMCIA cards" | ||||
| 	depends on EXPERIMENTAL && PCMCIA && WLAN_80211 | ||||
| 	select WIRELESS_EXT | ||||
| 	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. | ||||
| 
 | ||||
| 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
											
										
									
								
							
							
								
								
									
										248
									
								
								net/wireless/wext-priv.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								net/wireless/wext-priv.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||
							
								
								
									
										155
									
								
								net/wireless/wext-proc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								net/wireless/wext-proc.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -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"); | ||||
| } | ||||
							
								
								
									
										231
									
								
								net/wireless/wext-spy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								net/wireless/wext-spy.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -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 a new issue
	
	 Johannes Berg
						Johannes Berg