diff options
| author | wbx <wbx@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2006-03-14 21:11:36 +0000 | 
|---|---|---|
| committer | wbx <wbx@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2006-03-14 21:11:36 +0000 | 
| commit | 2315b47b10b345d339b0c296bbe7f373074bc3d6 (patch) | |
| tree | 81567c5e5245c6ab4ad096f0c6fe49de13ef2dbf | |
| parent | 70696f02f2abcad8648a81a2f7aae949ca4d717f (diff) | |
wireless extension 18 for 2.4 kernels, needed for xsupplicant
git-svn-id: svn://svn.openwrt.org/openwrt/trunk/openwrt@3367 3c298f89-4303-0410-b956-a3cf2f4a3e73
| -rw-r--r-- | target/linux/generic-2.4/patches/100-wireless-extension.patch | 1121 | 
1 files changed, 1121 insertions, 0 deletions
diff --git a/target/linux/generic-2.4/patches/100-wireless-extension.patch b/target/linux/generic-2.4/patches/100-wireless-extension.patch new file mode 100644 index 000000000..88e91831f --- /dev/null +++ b/target/linux/generic-2.4/patches/100-wireless-extension.patch @@ -0,0 +1,1121 @@ +diff -Nur linux-2.4.32/include/linux/netdevice.h linux-2.4.32-we/include/linux/netdevice.h +--- linux-2.4.32/include/linux/netdevice.h	2004-11-17 12:54:22.000000000 +0100 ++++ linux-2.4.32-we/include/linux/netdevice.h	2006-03-13 12:10:57.000000000 +0100 +@@ -295,7 +295,9 @@ +  + 	/* List of functions to handle Wireless Extensions (instead of ioctl). + 	 * See <net/iw_handler.h> for details. Jean II */ +-	struct iw_handler_def *	wireless_handlers; ++	const struct iw_handler_def *	wireless_handlers; ++	/* Instance data managed by the core of Wireless Extensions. */ ++	struct iw_public_data *	wireless_data; +  + 	struct ethtool_ops *ethtool_ops; +  +diff -Nur linux-2.4.32/include/linux/wireless.h linux-2.4.32-we/include/linux/wireless.h +--- linux-2.4.32/include/linux/wireless.h	2003-11-28 19:26:21.000000000 +0100 ++++ linux-2.4.32-we/include/linux/wireless.h	2006-03-13 12:11:02.000000000 +0100 +@@ -1,10 +1,10 @@ + /* +  * This file define a set of standard wireless extensions +  * +- * Version :	16	2.4.03 ++ * Version :	18	12.3.05 +  * +  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com> +- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. ++ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. +  */ +  + #ifndef _LINUX_WIRELESS_H +@@ -47,12 +47,12 @@ +  *	# include/net/iw_handler.h +  * +  * Note as well that /proc/net/wireless implementation has now moved in : +- *	# include/linux/wireless.c ++ *	# net/core/wireless.c +  * +  * Wireless Events (2002 -> onward) : +  * -------------------------------- +  * Events are defined at the end of this file, and implemented in : +- *	# include/linux/wireless.c ++ *	# net/core/wireless.c +  * +  * Other comments : +  * -------------- +@@ -82,7 +82,7 @@ +  * (there is some stuff that will be added in the future...) +  * I just plan to increment with each new version. +  */ +-#define WIRELESS_EXT	16 ++#define WIRELESS_EXT	18 +  + /* +  * Changes : +@@ -175,6 +175,28 @@ +  *	- Remove IW_MAX_GET_SPY because conflict with enhanced spy support +  *	- Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" +  *	- Add IW_ENCODE_TEMP and iw_range->encoding_login_index ++ * ++ * V16 to V17 ++ * ---------- ++ *	- Add flags to frequency -> auto/fixed ++ *	- Document (struct iw_quality *)->updated, add new flags (INVALID) ++ *	- Wireless Event capability in struct iw_range ++ *	- Add support for relative TxPower (yick !) ++ * ++ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>) ++ * ---------- ++ *	- Add support for WPA/WPA2 ++ *	- Add extended encoding configuration (SIOCSIWENCODEEXT and ++ *	  SIOCGIWENCODEEXT) ++ *	- Add SIOCSIWGENIE/SIOCGIWGENIE ++ *	- Add SIOCSIWMLME ++ *	- Add SIOCSIWPMKSA ++ *	- Add struct iw_range bit field for supported encoding capabilities ++ *	- Add optional scan request parameters for SIOCSIWSCAN ++ *	- Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA ++ *	  related parameters (extensible up to 4096 parameter values) ++ *	- Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, ++ *	  IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND +  */ +  + /**************************** CONSTANTS ****************************/ +@@ -249,9 +271,33 @@ + #define SIOCSIWPOWER	0x8B2C		/* set Power Management settings */ + #define SIOCGIWPOWER	0x8B2D		/* get Power Management settings */ +  ++/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). ++ * This ioctl uses struct iw_point and data buffer that includes IE id and len ++ * fields. More than one IE may be included in the request. Setting the generic ++ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers ++ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers ++ * are required to report the used IE as a wireless event, e.g., when ++ * associating with an AP. */ ++#define SIOCSIWGENIE	0x8B30		/* set generic IE */ ++#define SIOCGIWGENIE	0x8B31		/* get generic IE */ ++ ++/* WPA : IEEE 802.11 MLME requests */ ++#define SIOCSIWMLME	0x8B16		/* request MLME operation; uses ++					 * struct iw_mlme */ ++/* WPA : Authentication mode parameters */ ++#define SIOCSIWAUTH	0x8B32		/* set authentication mode params */ ++#define SIOCGIWAUTH	0x8B33		/* get authentication mode params */ ++ ++/* WPA : Extended version of encoding configuration */ ++#define SIOCSIWENCODEEXT 0x8B34		/* set encoding token & mode */ ++#define SIOCGIWENCODEEXT 0x8B35		/* get encoding token & mode */ ++ ++/* WPA2 : PMKSA cache management */ ++#define SIOCSIWPMKSA	0x8B36		/* PMKSA cache operation */ ++ + /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ +  +-/* These 16 ioctl are wireless device private. ++/* These 32 ioctl are wireless device private, for 16 commands. +  * Each driver is free to use them for whatever purpose it chooses, +  * however the driver *must* export the description of those ioctls +  * with SIOCGIWPRIV and *must* use arguments as defined below. +@@ -266,8 +312,8 @@ +  * We now have 32 commands, so a bit more space ;-). +  * Also, all 'odd' commands are only usable by root and don't return the +  * content of ifr/iwr to user (but you are not obliged to use the set/get +- * convention, just use every other two command). +- * And I repeat : you are not obliged to use them with iwspy, but you ++ * convention, just use every other two command). More details in iwpriv.c. ++ * And I repeat : you are not forced to use them with iwpriv, but you +  * must be compliant with it. +  */ +  +@@ -290,6 +336,34 @@ + #define IWEVCUSTOM	0x8C02		/* Driver specific ascii string */ + #define IWEVREGISTERED	0x8C03		/* Discovered a new node (AP mode) */ + #define IWEVEXPIRED	0x8C04		/* Expired a node (AP mode) */ ++#define IWEVGENIE	0x8C05		/* Generic IE (WPA, RSN, WMM, ..) ++					 * (scan results); This includes id and ++					 * length fields. One IWEVGENIE may ++					 * contain more than one IE. Scan ++					 * results may contain one or more ++					 * IWEVGENIE events. */ ++#define IWEVMICHAELMICFAILURE 0x8C06	/* Michael MIC failure ++					 * (struct iw_michaelmicfailure) ++					 */ ++#define IWEVASSOCREQIE	0x8C07		/* IEs used in (Re)Association Request. ++					 * The data includes id and length ++					 * fields and may contain more than one ++					 * IE. This event is required in ++					 * Managed mode if the driver ++					 * generates its own WPA/RSN IE. This ++					 * should be sent just before ++					 * IWEVREGISTERED event for the ++					 * association. */ ++#define IWEVASSOCRESPIE	0x8C08		/* IEs used in (Re)Association ++					 * Response. The data includes id and ++					 * length fields and may contain more ++					 * than one IE. This may be sent ++					 * between IWEVASSOCREQIE and ++					 * IWEVREGISTERED events for the ++					 * association. */ ++#define IWEVPMKIDCAND	0x8C09		/* PMKID candidate for RSN ++					 * pre-authentication ++					 * (struct iw_pmkid_cand) */ +  + #define IWEVFIRST	0x8C00 +  +@@ -352,6 +426,18 @@ + #define IW_MODE_SECOND	5	/* Secondary master/repeater (backup) */ + #define IW_MODE_MONITOR	6	/* Passive monitor (listen only) */ +  ++/* Statistics flags (bitmask in updated) */ ++#define IW_QUAL_QUAL_UPDATED	0x1	/* Value was updated since last read */ ++#define IW_QUAL_LEVEL_UPDATED	0x2 ++#define IW_QUAL_NOISE_UPDATED	0x4 ++#define IW_QUAL_QUAL_INVALID	0x10	/* Driver doesn't provide value */ ++#define IW_QUAL_LEVEL_INVALID	0x20 ++#define IW_QUAL_NOISE_INVALID	0x40 ++ ++/* Frequency flags */ ++#define IW_FREQ_AUTO		0x00	/* Let the driver decides */ ++#define IW_FREQ_FIXED		0x01	/* Force a specific value */ ++ + /* Maximum number of size of encoding token available +  * they are listed in the range structure */ + #define IW_MAX_ENCODING_SIZES	8 +@@ -390,6 +476,7 @@ + #define IW_TXPOW_TYPE		0x00FF	/* Type of value */ + #define IW_TXPOW_DBM		0x0000	/* Value is in dBm */ + #define IW_TXPOW_MWATT		0x0001	/* Value is in mW */ ++#define IW_TXPOW_RELATIVE	0x0002	/* Value is in arbitrary units */ + #define IW_TXPOW_RANGE		0x1000	/* Range of value between min/max */ +  + /* Retry limits and lifetime flags available */ +@@ -412,12 +499,113 @@ + #define IW_SCAN_THIS_MODE	0x0020	/* Scan only this Mode */ + #define IW_SCAN_ALL_RATE	0x0040	/* Scan all Bit-Rates */ + #define IW_SCAN_THIS_RATE	0x0080	/* Scan only this Bit-Rate */ ++/* struct iw_scan_req scan_type */ ++#define IW_SCAN_TYPE_ACTIVE 0 ++#define IW_SCAN_TYPE_PASSIVE 1 + /* Maximum size of returned data */ + #define IW_SCAN_MAX_DATA	4096	/* In bytes */ +  + /* Max number of char in custom event - use multiple of them if needed */ + #define IW_CUSTOM_MAX		256	/* In bytes */ +  ++/* Generic information element */ ++#define IW_GENERIC_IE_MAX	1024 ++ ++/* MLME requests (SIOCSIWMLME / struct iw_mlme) */ ++#define IW_MLME_DEAUTH		0 ++#define IW_MLME_DISASSOC	1 ++ ++/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ ++#define IW_AUTH_INDEX		0x0FFF ++#define IW_AUTH_FLAGS		0xF000 ++/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) ++ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the ++ * parameter that is being set/get to; value will be read/written to ++ * struct iw_param value field) */ ++#define IW_AUTH_WPA_VERSION		0 ++#define IW_AUTH_CIPHER_PAIRWISE		1 ++#define IW_AUTH_CIPHER_GROUP		2 ++#define IW_AUTH_KEY_MGMT		3 ++#define IW_AUTH_TKIP_COUNTERMEASURES	4 ++#define IW_AUTH_DROP_UNENCRYPTED	5 ++#define IW_AUTH_80211_AUTH_ALG		6 ++#define IW_AUTH_WPA_ENABLED		7 ++#define IW_AUTH_RX_UNENCRYPTED_EAPOL	8 ++#define IW_AUTH_ROAMING_CONTROL		9 ++#define IW_AUTH_PRIVACY_INVOKED		10 ++ ++/* IW_AUTH_WPA_VERSION values (bit field) */ ++#define IW_AUTH_WPA_VERSION_DISABLED	0x00000001 ++#define IW_AUTH_WPA_VERSION_WPA		0x00000002 ++#define IW_AUTH_WPA_VERSION_WPA2	0x00000004 ++ ++/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ ++#define IW_AUTH_CIPHER_NONE	0x00000001 ++#define IW_AUTH_CIPHER_WEP40	0x00000002 ++#define IW_AUTH_CIPHER_TKIP	0x00000004 ++#define IW_AUTH_CIPHER_CCMP	0x00000008 ++#define IW_AUTH_CIPHER_WEP104	0x00000010 ++ ++/* IW_AUTH_KEY_MGMT values (bit field) */ ++#define IW_AUTH_KEY_MGMT_802_1X	1 ++#define IW_AUTH_KEY_MGMT_PSK	2 ++ ++/* IW_AUTH_80211_AUTH_ALG values (bit field) */ ++#define IW_AUTH_ALG_OPEN_SYSTEM	0x00000001 ++#define IW_AUTH_ALG_SHARED_KEY	0x00000002 ++#define IW_AUTH_ALG_LEAP	0x00000004 ++ ++/* IW_AUTH_ROAMING_CONTROL values */ ++#define IW_AUTH_ROAMING_ENABLE	0	/* driver/firmware based roaming */ ++#define IW_AUTH_ROAMING_DISABLE	1	/* user space program used for roaming ++					 * control */ ++ ++/* SIOCSIWENCODEEXT definitions */ ++#define IW_ENCODE_SEQ_MAX_SIZE	8 ++/* struct iw_encode_ext ->alg */ ++#define IW_ENCODE_ALG_NONE	0 ++#define IW_ENCODE_ALG_WEP	1 ++#define IW_ENCODE_ALG_TKIP	2 ++#define IW_ENCODE_ALG_CCMP	3 ++/* struct iw_encode_ext ->ext_flags */ ++#define IW_ENCODE_EXT_TX_SEQ_VALID	0x00000001 ++#define IW_ENCODE_EXT_RX_SEQ_VALID	0x00000002 ++#define IW_ENCODE_EXT_GROUP_KEY		0x00000004 ++#define IW_ENCODE_EXT_SET_TX_KEY	0x00000008 ++ ++/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ ++#define IW_MICFAILURE_KEY_ID	0x00000003 /* Key ID 0..3 */ ++#define IW_MICFAILURE_GROUP	0x00000004 ++#define IW_MICFAILURE_PAIRWISE	0x00000008 ++#define IW_MICFAILURE_STAKEY	0x00000010 ++#define IW_MICFAILURE_COUNT	0x00000060 /* 1 or 2 (0 = count not supported) ++					    */ ++ ++/* Bit field values for enc_capa in struct iw_range */ ++#define IW_ENC_CAPA_WPA		0x00000001 ++#define IW_ENC_CAPA_WPA2	0x00000002 ++#define IW_ENC_CAPA_CIPHER_TKIP	0x00000004 ++#define IW_ENC_CAPA_CIPHER_CCMP	0x00000008 ++ ++/* Event capability macros - in (struct iw_range *)->event_capa ++ * Because we have more than 32 possible events, we use an array of ++ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ ++#define IW_EVENT_CAPA_BASE(cmd)		((cmd >= SIOCIWFIRSTPRIV) ? \ ++					 (cmd - SIOCIWFIRSTPRIV + 0x60) : \ ++					 (cmd - SIOCSIWCOMMIT)) ++#define IW_EVENT_CAPA_INDEX(cmd)	(IW_EVENT_CAPA_BASE(cmd) >> 5) ++#define IW_EVENT_CAPA_MASK(cmd)		(1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) ++/* Event capability constants - event autogenerated by the kernel ++ * This list is valid for most 802.11 devices, customise as needed... */ ++#define IW_EVENT_CAPA_K_0	(IW_EVENT_CAPA_MASK(0x8B04) | \ ++				 IW_EVENT_CAPA_MASK(0x8B06) | \ ++				 IW_EVENT_CAPA_MASK(0x8B1A)) ++#define IW_EVENT_CAPA_K_1	(IW_EVENT_CAPA_MASK(0x8B2A)) ++/* "Easy" macro to set events in iw_range (less efficient) */ ++#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) ++#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } ++ ++ + /****************************** TYPES ******************************/ +  + /* --------------------------- SUBTYPES --------------------------- */ +@@ -456,7 +644,7 @@ + 	__s32		m;		/* Mantissa */ + 	__s16		e;		/* Exponent */ + 	__u8		i;		/* List index (when in range struct) */ +-	__u8		pad;		/* Unused - just for alignement */ ++	__u8		flags;		/* Flags (fixed/auto) */ + }; +  + /* +@@ -507,6 +695,132 @@ + 	struct iw_quality	high;		/* High threshold */ + }; +  ++/* ++ *	Optional data for scan request ++ * ++ *	Note: these optional parameters are controlling parameters for the ++ *	scanning behavior, these do not apply to getting scan results ++ *	(SIOCGIWSCAN). Drivers are expected to keep a local BSS table and ++ *	provide a merged results with all BSSes even if the previous scan ++ *	request limited scanning to a subset, e.g., by specifying an SSID. ++ *	Especially, scan results are required to include an entry for the ++ *	current BSS if the driver is in Managed mode and associated with an AP. ++ */ ++struct	iw_scan_req ++{ ++	__u8		scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ ++	__u8		essid_len; ++	__u8		num_channels; /* num entries in channel_list; ++				       * 0 = scan all allowed channels */ ++	__u8		flags; /* reserved as padding; use zero, this may ++				* be used in the future for adding flags ++				* to request different scan behavior */ ++	struct sockaddr	bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or ++				* individual address of a specific BSS */ ++ ++	/* ++	 * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using ++	 * the current ESSID. This allows scan requests for specific ESSID ++	 * without having to change the current ESSID and potentially breaking ++	 * the current association. ++	 */ ++	__u8		essid[IW_ESSID_MAX_SIZE]; ++ ++	/* ++	 * Optional parameters for changing the default scanning behavior. ++	 * These are based on the MLME-SCAN.request from IEEE Std 802.11. ++	 * TU is 1.024 ms. If these are set to 0, driver is expected to use ++	 * reasonable default values. min_channel_time defines the time that ++	 * will be used to wait for the first reply on each channel. If no ++	 * replies are received, next channel will be scanned after this. If ++	 * replies are received, total time waited on the channel is defined by ++	 * max_channel_time. ++	 */ ++	__u32		min_channel_time; /* in TU */ ++	__u32		max_channel_time; /* in TU */ ++ ++	struct iw_freq	channel_list[IW_MAX_FREQUENCIES]; ++}; ++ ++/* ------------------------- WPA SUPPORT ------------------------- */ ++ ++/* ++ *	Extended data structure for get/set encoding (this is used with ++ *	SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* ++ *	flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and ++ *	only the data contents changes (key data -> this structure, including ++ *	key data). ++ * ++ *	If the new key is the first group key, it will be set as the default ++ *	TX key. Otherwise, default TX key index is only changed if ++ *	IW_ENCODE_EXT_SET_TX_KEY flag is set. ++ * ++ *	Key will be changed with SIOCSIWENCODEEXT in all cases except for ++ *	special "change TX key index" operation which is indicated by setting ++ *	key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. ++ * ++ *	tx_seq/rx_seq are only used when respective ++ *	IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal ++ *	TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start ++ *	TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally ++ *	used only by an Authenticator (AP or an IBSS station) to get the ++ *	current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and ++ *	RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for ++ *	debugging/testing. ++ */ ++struct	iw_encode_ext ++{ ++	__u32		ext_flags; /* IW_ENCODE_EXT_* */ ++	__u8		tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ ++	__u8		rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ ++	struct sockaddr	addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast ++			       * (group) keys or unicast address for ++			       * individual keys */ ++	__u16		alg; /* IW_ENCODE_ALG_* */ ++	__u16		key_len; ++	__u8		key[0]; ++}; ++ ++/* SIOCSIWMLME data */ ++struct	iw_mlme ++{ ++	__u16		cmd; /* IW_MLME_* */ ++	__u16		reason_code; ++	struct sockaddr	addr; ++}; ++ ++/* SIOCSIWPMKSA data */ ++#define IW_PMKSA_ADD		1 ++#define IW_PMKSA_REMOVE		2 ++#define IW_PMKSA_FLUSH		3 ++ ++#define IW_PMKID_LEN	16 ++ ++struct	iw_pmksa ++{ ++	__u32		cmd; /* IW_PMKSA_* */ ++	struct sockaddr	bssid; ++	__u8		pmkid[IW_PMKID_LEN]; ++}; ++ ++/* IWEVMICHAELMICFAILURE data */ ++struct	iw_michaelmicfailure ++{ ++	__u32		flags; ++	struct sockaddr	src_addr; ++	__u8		tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ ++}; ++ ++/* IWEVPMKIDCAND data */ ++#define IW_PMKID_CAND_PREAUTH	0x00000001 /* RNS pre-authentication enabled */ ++struct	iw_pmkid_cand ++{ ++	__u32		flags; /* IW_PMKID_CAND_* */ ++	__u32		index; /* the smaller the index, the higher the ++				* priority */ ++	struct sockaddr	bssid; ++}; ++ + /* ------------------------ WIRELESS STATS ------------------------ */ + /* +  * Wireless statistics (used for /proc/net/wireless) +@@ -610,11 +924,12 @@ + 	/* Old Frequency (backward compat - moved lower ) */ + 	__u16		old_num_channels; + 	__u8		old_num_frequency; +-	/* Filler to keep "version" at the same offset */ +-	__s32		old_freq[6]; ++ ++	/* Wireless event capability bitmasks */ ++	__u32		event_capa[6]; +  + 	/* signal level threshold range */ +-	__s32	sensitivity; ++	__s32		sensitivity; +  + 	/* Quality of link & SNR stuff */ + 	/* Quality range (link, level, noise) +@@ -685,6 +1000,8 @@ + 	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */ + 	/* Note : this frequency list doesn't need to fit channel numbers, + 	 * because each entry contain its channel index */ ++ ++	__u32		enc_capa; /* IW_ENC_CAPA_* bit field */ + }; +  + /* +diff -Nur linux-2.4.32/include/net/iw_handler.h linux-2.4.32-we/include/net/iw_handler.h +--- linux-2.4.32/include/net/iw_handler.h	2003-11-28 19:26:21.000000000 +0100 ++++ linux-2.4.32-we/include/net/iw_handler.h	2006-03-13 12:10:57.000000000 +0100 +@@ -1,10 +1,10 @@ + /* +  * This file define the new driver API for Wireless Extensions +  * +- * Version :	5	4.12.02 ++ * Version :	6	21.6.04 +  * +  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com> +- * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved. ++ * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved. +  */ +  + #ifndef _IW_HANDLER_H +@@ -206,7 +206,7 @@ +  * will be needed... +  * I just plan to increment with each new version. +  */ +-#define IW_HANDLER_VERSION	5 ++#define IW_HANDLER_VERSION	6 +  + /* +  * Changes : +@@ -224,11 +224,18 @@ +  * V4 to V5 +  * -------- +  *	- Add new spy support : struct iw_spy_data & prototypes ++ * ++ * V5 to V6 ++ * -------- ++ *	- Change the way we get to spy_data method for added safety ++ *	- Remove spy #ifdef, they are always on -> cleaner code ++ *	- Add IW_DESCR_FLAG_NOMAX flag for very large requests ++ *	- Start migrating get_wireless_stats to struct iw_handler_def +  */ +  + /**************************** CONSTANTS ****************************/ +  +-/* Enable enhanced spy support. Disable to reduce footprint */ ++/* Enhanced spy support available */ + #define IW_WIRELESS_SPY + #define IW_WIRELESS_THRSPY +  +@@ -258,6 +265,7 @@ + #define IW_DESCR_FLAG_EVENT	0x0002	/* Generate an event on SET */ + #define IW_DESCR_FLAG_RESTRICT	0x0004	/* GET : request is ROOT only */ + 				/* SET : Omit payload from generated iwevent */ ++#define IW_DESCR_FLAG_NOMAX	0x0008	/* GET : no limit on request size */ + /* Driver level flags */ + #define IW_DESCR_FLAG_WAIT	0x0100	/* Wait for driver event */ +  +@@ -311,23 +319,25 @@ + 	/* Array of handlers for standard ioctls + 	 * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME] + 	 */ +-	iw_handler *		standard; ++	const iw_handler *	standard; +  + 	/* Array of handlers for private ioctls + 	 * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV] + 	 */ +-	iw_handler *		private; ++	const iw_handler *	private; +  + 	/* Arguments of private handler. This one is just a list, so you + 	 * can put it in any order you want and should not leave holes... + 	 * We will automatically export that to user space... */ +-	struct iw_priv_args *	private_args; ++	const struct iw_priv_args *	private_args; +  +-	/* Driver enhanced spy support */ +-	long			spy_offset;	/* Spy data offset */ ++	/* This field will be *removed* in the next version of WE */ ++	long			spy_offset;	/* DO NOT USE */ +  +-	/* In the long term, get_wireless_stats will move from +-	 * 'struct net_device' to here, to minimise bloat. */ ++	/* New location of get_wireless_stats, to de-bloat struct net_device. ++	 * The old pointer in struct net_device will be gradually phased ++	 * out, and drivers are encouraged to use this one... */ ++	struct iw_statistics*	(*get_wireless_stats)(struct net_device *dev); + }; +  + /* ---------------------- IOCTL DESCRIPTION ---------------------- */ +@@ -374,18 +384,29 @@ +  */ + struct iw_spy_data + { +-#ifdef IW_WIRELESS_SPY + 	/* --- Standard spy support --- */ + 	int			spy_number; + 	u_char			spy_address[IW_MAX_SPY][ETH_ALEN]; + 	struct iw_quality	spy_stat[IW_MAX_SPY]; +-#ifdef IW_WIRELESS_THRSPY + 	/* --- Enhanced spy support (event) */ + 	struct iw_quality	spy_thr_low;	/* Low threshold */ + 	struct iw_quality	spy_thr_high;	/* High threshold */ + 	u_char			spy_thr_under[IW_MAX_SPY]; +-#endif /* IW_WIRELESS_THRSPY */ +-#endif /* IW_WIRELESS_SPY */ ++}; ++ ++/* --------------------- DEVICE WIRELESS DATA --------------------- */ ++/* ++ * This is all the wireless data specific to a device instance that ++ * is managed by the core of Wireless Extensions. ++ * We only keep pointer to those structures, so that a driver is free ++ * to share them between instances. ++ * This structure should be initialised before registering the device. ++ * Access to this data follow the same rules as any other struct net_device ++ * data (i.e. valid as long as struct net_device exist, same locking rules). ++ */ ++struct iw_public_data { ++	/* Driver enhanced spy support */ ++	struct iw_spy_data *	spy_data; + }; +  + /**************************** PROTOTYPES ****************************/ +diff -Nur linux-2.4.32/net/core/dev.c linux-2.4.32-we/net/core/dev.c +--- linux-2.4.32/net/core/dev.c	2005-04-04 03:42:20.000000000 +0200 ++++ linux-2.4.32-we/net/core/dev.c	2006-03-13 12:10:57.000000000 +0100 +@@ -2426,7 +2426,7 @@ + 				/* Follow me in net/core/wireless.c */ + 				ret = wireless_process_ioctl(&ifr, cmd); + 				rtnl_unlock(); +-				if (!ret && IW_IS_GET(cmd) && ++				if (IW_IS_GET(cmd) && + 				    copy_to_user(arg, &ifr, sizeof(struct ifreq))) + 					return -EFAULT; + 				return ret; +diff -Nur linux-2.4.32/net/core/wireless.c linux-2.4.32-we/net/core/wireless.c +--- linux-2.4.32/net/core/wireless.c	2003-11-28 19:26:21.000000000 +0100 ++++ linux-2.4.32-we/net/core/wireless.c	2006-03-13 12:11:02.000000000 +0100 +@@ -2,7 +2,7 @@ +  * This file implement the Wireless Extensions APIs. +  * +  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com> +- * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved. ++ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. +  * +  * (As all part of the Linux kernel, this file is GPL) +  */ +@@ -48,6 +48,16 @@ +  *	o Add common spy support : iw_handler_set_spy(), wireless_spy_update() +  *	o Add enhanced spy support : iw_handler_set_thrspy() and event. +  *	o Add WIRELESS_EXT version display in /proc/net/wireless ++ * ++ * v6 - 18.06.04 - Jean II ++ *	o Change get_spydata() method for added safety ++ *	o Remove spy #ifdef, they are always on -> cleaner code ++ *	o Allow any size GET request if user specifies length > max ++ *		and if request has IW_DESCR_FLAG_NOMAX flag or is SIOCGIWPRIV ++ *	o Start migrating get_wireless_stats to struct iw_handler_def ++ *	o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus ++ * Based on patch from Pavel Roskin <proski@gnu.org> : ++ *	o Fix kernel data leak to user space in private handler handling +  */ +  + /***************************** INCLUDES *****************************/ +@@ -64,11 +74,7 @@ +  + /**************************** CONSTANTS ****************************/ +  +-/* Enough lenience, let's make sure things are proper... */ +-#define WE_STRICT_WRITE		/* Check write buffer size */ +-/* I'll probably drop both the define and kernel message in the next version */ +- +-/* Debuging stuff */ ++/* Debugging stuff */ + #undef WE_IOCTL_DEBUG		/* Debug IOCTL API */ + #undef WE_EVENT_DEBUG		/* Debug Event dispatcher */ + #undef WE_SPY_DEBUG		/* Debug enhanced spy support */ +@@ -131,14 +137,14 @@ + 	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, + 	/* SIOCGIWAP */ + 	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP}, +-	/* -- hole -- */ +-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, ++	/* SIOCSIWMLME */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_mlme), sizeof(struct iw_mlme), 0}, + 	/* SIOCGIWAPLIST */ +-	{ IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0}, ++	{ IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, IW_DESCR_FLAG_NOMAX}, + 	/* SIOCSIWSCAN */ +-	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, ++	{ IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_scan_req), 0}, + 	/* SIOCGIWSCAN */ +-	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0}, ++	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, IW_DESCR_FLAG_NOMAX}, + 	/* SIOCSIWESSID */ + 	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT}, + 	/* SIOCGIWESSID */ +@@ -179,6 +185,25 @@ + 	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, + 	/* SIOCGIWPOWER */ + 	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, ++	/* -- hole -- */ ++	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, ++	/* -- hole -- */ ++	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, ++	/* SIOCSIWGENIE */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0}, ++	/* SIOCGIWGENIE */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0}, ++	/* SIOCSIWAUTH */ ++	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, ++	/* SIOCGIWAUTH */ ++	{ IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, ++	/* SIOCSIWENCODEEXT */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0}, ++	/* SIOCGIWENCODEEXT */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0}, ++	/* SIOCSIWPMKSA */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_pmksa), sizeof(struct iw_pmksa), 0}, ++	/* -- hole -- */ + }; + static const int standard_ioctl_num = (sizeof(standard_ioctl) / + 				       sizeof(struct iw_ioctl_description)); +@@ -198,12 +223,22 @@ + 	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, + 	/* IWEVEXPIRED */ + 	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, ++	/* IWEVGENIE */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0}, ++	/* IWEVMICHAELMICFAILURE */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_michaelmicfailure), 0}, ++	/* IWEVASSOCREQIE */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0}, ++	/* IWEVASSOCRESPIE */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0}, ++	/* IWEVPMKIDCAND */ ++	{ IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_pmkid_cand), 0}, + }; + static const int standard_event_num = (sizeof(standard_event) / + 				       sizeof(struct iw_ioctl_description)); +  + /* Size (in bytes) of the various private data types */ +-static const char priv_type_size[] = { ++static const char iw_priv_type_size[] = { + 	0,				/* IW_PRIV_TYPE_NONE */ + 	1,				/* IW_PRIV_TYPE_BYTE */ + 	1,				/* IW_PRIV_TYPE_CHAR */ +@@ -270,12 +305,15 @@ +  */ + static inline struct iw_statistics *get_wireless_stats(struct net_device *dev) + { ++	/* New location */ ++	if((dev->wireless_handlers != NULL) && ++	   (dev->wireless_handlers->get_wireless_stats != NULL)) ++		return dev->wireless_handlers->get_wireless_stats(dev); ++ ++	/* Old location, will be phased out in next WE */ + 	return (dev->get_wireless_stats ? + 		dev->get_wireless_stats(dev) : + 		(struct iw_statistics *) NULL); +-	/* In the future, get_wireless_stats may move from 'struct net_device' +-	 * to 'struct iw_handler_def', to de-bloat struct net_device. +-	 * Definitely worse a thought... */ + } +  + /* ---------------------------------------------------------------- */ +@@ -310,14 +348,32 @@ +  + /* ---------------------------------------------------------------- */ + /* +- * Number of private arguments ++ * Calculate size of private arguments +  */ + static inline int get_priv_size(__u16	args) + { + 	int	num = args & IW_PRIV_SIZE_MASK; + 	int	type = (args & IW_PRIV_TYPE_MASK) >> 12; +  +-	return num * priv_type_size[type]; ++	return num * iw_priv_type_size[type]; ++} ++ ++/* ---------------------------------------------------------------- */ ++/* ++ * Re-calculate the size of private arguments ++ */ ++static inline int adjust_priv_size(__u16		args, ++				   union iwreq_data *	wrqu) ++{ ++	int	num = wrqu->data.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]; + } +  +  +@@ -350,11 +406,14 @@ + 			       dev->name, + 			       stats->status, + 			       stats->qual.qual, +-			       stats->qual.updated & 1 ? '.' : ' ', ++			       stats->qual.updated & IW_QUAL_QUAL_UPDATED ++			       ? '.' : ' ', + 			       ((__u8) stats->qual.level), +-			       stats->qual.updated & 2 ? '.' : ' ', ++			       stats->qual.updated & IW_QUAL_LEVEL_UPDATED ++			       ? '.' : ' ', + 			       ((__u8) stats->qual.noise), +-			       stats->qual.updated & 4 ? '.' : ' ', ++			       stats->qual.updated & IW_QUAL_NOISE_UPDATED ++			       ? '.' : ' ', + 			       stats->discard.nwid, + 			       stats->discard.code, + 			       stats->discard.fragment, +@@ -470,13 +529,15 @@ + 	/* Check NULL pointer */ + 	if(iwr->u.data.pointer == NULL) + 		return -EFAULT; +-#ifdef WE_STRICT_WRITE ++ + 	/* Check if there is enough buffer up there */ + 	if(iwr->u.data.length < dev->wireless_handlers->num_private_args) { +-		printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.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... */ ++		iwr->u.data.length = dev->wireless_handlers->num_private_args; + 		return -E2BIG; + 	} +-#endif	/* WE_STRICT_WRITE */ +  + 	/* Set the number of available ioctls. */ + 	iwr->u.data.length = dev->wireless_handlers->num_private_args; +@@ -505,7 +566,6 @@ + 	const struct iw_ioctl_description *	descr; + 	struct iw_request_info			info; + 	int					ret = -EINVAL; +-	int					user_size = 0; +  + 	/* Get the description of the IOCTL */ + 	if((cmd - SIOCIWFIRST) >= standard_ioctl_num) +@@ -536,8 +596,14 @@ + #endif	/* WE_SET_EVENT */ + 	} else { + 		char *	extra; ++		int	extra_size; ++		int	user_length = 0; + 		int	err; +  ++		/* Calculate space needed by arguments. Always allocate ++		 * for max space. Easier, and won't last long... */ ++		extra_size = descr->max_tokens * descr->token_size; ++ + 		/* Check what user space is giving us */ + 		if(IW_IS_SET(cmd)) { + 			/* Check NULL pointer */ +@@ -554,18 +620,33 @@ + 			if(iwr->u.data.pointer == NULL) + 				return -EFAULT; + 			/* Save user space buffer size for checking */ +-			user_size = iwr->u.data.length; ++			user_length = iwr->u.data.length; ++ ++			/* Don't check if user_length > max to allow forward ++			 * compatibility. The test user_length < min is ++			 * implied by the test at the end. */ ++ ++			/* Support for very large requests */ ++			if((descr->flags & IW_DESCR_FLAG_NOMAX) && ++			   (user_length > descr->max_tokens)) { ++				/* Allow userspace to GET more than max so ++				 * we can support any size GET requests. ++				 * There is still a limit : -ENOMEM. */ ++				extra_size = user_length * descr->token_size; ++				/* Note : user_length is originally a __u16, ++				 * and token_size is controlled by us, ++				 * so extra_size won't get negative and ++				 * won't overflow... */ ++			} + 		} +  + #ifdef WE_IOCTL_DEBUG + 		printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n", +-		       dev->name, descr->max_tokens * descr->token_size); ++		       dev->name, extra_size); + #endif	/* WE_IOCTL_DEBUG */ +  +-		/* Always allocate for max space. Easier, and won't last +-		 * long... */ +-		extra = kmalloc(descr->max_tokens * descr->token_size, +-				GFP_KERNEL); ++		/* Create the kernel buffer */ ++		extra = kmalloc(extra_size, GFP_KERNEL); + 		if (extra == NULL) { + 			return -ENOMEM; + 		} +@@ -591,14 +672,11 @@ +  + 		/* If we have something to return to the user */ + 		if (!ret && IW_IS_GET(cmd)) { +-#ifdef WE_STRICT_WRITE + 			/* Check if there is enough buffer up there */ +-			if(user_size < iwr->u.data.length) { +-				printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length); ++			if(user_length < iwr->u.data.length) { + 				kfree(extra); + 				return -E2BIG; + 			} +-#endif	/* WE_STRICT_WRITE */ +  + 			err = copy_to_user(iwr->u.data.pointer, extra, + 					   iwr->u.data.length * +@@ -661,7 +739,7 @@ + 				     iw_handler		handler) + { + 	struct iwreq *			iwr = (struct iwreq *) ifr; +-	struct iw_priv_args *		descr = NULL; ++	const struct iw_priv_args *	descr = NULL; + 	struct iw_request_info		info; + 	int				extra_size = 0; + 	int				i; +@@ -701,7 +779,7 @@ + 			   ((extra_size + offset) <= IFNAMSIZ)) + 				extra_size = 0; + 		} else { +-			/* Size of set arguments */ ++			/* Size of get arguments */ + 			extra_size = get_priv_size(descr->get_args); +  + 			/* Does it fits in iwr ? */ +@@ -771,6 +849,14 @@ +  + 		/* If we have something to return to the user */ + 		if (!ret && 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, ++							      &(iwr->u)); ++			} ++ + 			err = copy_to_user(iwr->u.data.pointer, extra, + 					   extra_size); + 			if (err) +@@ -1042,9 +1128,25 @@ +  * One of the main advantage of centralising spy support here is that +  * it becomes much easier to improve and extend it without having to touch +  * the drivers. One example is the addition of the Spy-Threshold events. +- * Note : IW_WIRELESS_SPY is defined in iw_handler.h +  */ +  ++/* ---------------------------------------------------------------- */ ++/* ++ * Return the pointer to the spy data in the driver. ++ * Because this is called on the Rx path via wireless_spy_update(), ++ * we want it to be efficient... ++ */ ++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); ++ ++	/* This is the old way. Doesn't work for multi-headed drivers. ++	 * It will be removed in the next version of WE. */ ++	return (dev->priv + dev->wireless_handlers->spy_offset); ++} ++ + /*------------------------------------------------------------------*/ + /* +  * Standard Wireless Handler : set Spy List +@@ -1054,16 +1156,26 @@ + 		       union iwreq_data *	wrqu, + 		       char *			extra) + { +-#ifdef IW_WIRELESS_SPY +-	struct iw_spy_data *	spydata = (dev->priv + +-					   dev->wireless_handlers->spy_offset); ++	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. +-	 * As we don't disable interrupts, we need to do this to avoid races. +-	 * As we are the only writer, this is good enough. */ ++	 * 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. */ ++	wmb(); ++ + 	/* Are there are addresses to copy? */ + 	if(wrqu->data.length > 0) { + 		int i; +@@ -1089,13 +1201,14 @@ + 			       spydata->spy_address[i][5]); + #endif	/* WE_SPY_DEBUG */ + 	} ++ ++	/* Make sure above is updated before re-enabling */ ++	wmb(); ++ + 	/* Enable addresses */ + 	spydata->spy_number = wrqu->data.length; +  + 	return 0; +-#else /* IW_WIRELESS_SPY */ +-	return -EOPNOTSUPP; +-#endif /* IW_WIRELESS_SPY */ + } +  + /*------------------------------------------------------------------*/ +@@ -1107,12 +1220,14 @@ + 		       union iwreq_data *	wrqu, + 		       char *			extra) + { +-#ifdef IW_WIRELESS_SPY +-	struct iw_spy_data *	spydata = (dev->priv + +-					   dev->wireless_handlers->spy_offset); ++	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. */ +@@ -1129,9 +1244,6 @@ + 	for(i = 0; i < spydata->spy_number; i++) + 		spydata->spy_stat[i].updated = 0; + 	return 0; +-#else /* IW_WIRELESS_SPY */ +-	return -EOPNOTSUPP; +-#endif /* IW_WIRELESS_SPY */ + } +  + /*------------------------------------------------------------------*/ +@@ -1143,11 +1255,13 @@ + 			  union iwreq_data *	wrqu, + 			  char *		extra) + { +-#ifdef IW_WIRELESS_THRSPY +-	struct iw_spy_data *	spydata = (dev->priv + +-					   dev->wireless_handlers->spy_offset); ++	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)); +@@ -1160,9 +1274,6 @@ + #endif	/* WE_SPY_DEBUG */ +  + 	return 0; +-#else /* IW_WIRELESS_THRSPY */ +-	return -EOPNOTSUPP; +-#endif /* IW_WIRELESS_THRSPY */ + } +  + /*------------------------------------------------------------------*/ +@@ -1174,22 +1285,20 @@ + 			  union iwreq_data *	wrqu, + 			  char *		extra) + { +-#ifdef IW_WIRELESS_THRSPY +-	struct iw_spy_data *	spydata = (dev->priv + +-					   dev->wireless_handlers->spy_offset); ++	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; +-#else /* IW_WIRELESS_THRSPY */ +-	return -EOPNOTSUPP; +-#endif /* IW_WIRELESS_THRSPY */ + } +  +-#ifdef IW_WIRELESS_THRSPY + /*------------------------------------------------------------------*/ + /* +  * Prepare and send a Spy Threshold event +@@ -1227,7 +1336,6 @@ + 	/* Send event to user space */ + 	wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold); + } +-#endif /* IW_WIRELESS_THRSPY */ +  + /* ---------------------------------------------------------------- */ + /* +@@ -1240,12 +1348,14 @@ + 			 unsigned char *	address, + 			 struct iw_quality *	wstats) + { +-#ifdef IW_WIRELESS_SPY +-	struct iw_spy_data *	spydata = (dev->priv + +-					   dev->wireless_handlers->spy_offset); ++	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; ++ + #ifdef WE_SPY_DEBUG + 	printk(KERN_DEBUG "wireless_spy_update() :  offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]); + #endif	/* WE_SPY_DEBUG */ +@@ -1257,7 +1367,7 @@ + 			       sizeof(struct iw_quality)); + 			match = i; + 		} +-#ifdef IW_WIRELESS_THRSPY ++ + 	/* 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 +@@ -1277,6 +1387,4 @@ + 			} + 		} + 	} +-#endif /* IW_WIRELESS_THRSPY */ +-#endif /* IW_WIRELESS_SPY */ + }  | 
