Root/target/linux/generic-2.4/patches/100-wireless-extension.patch

1--- a/include/linux/netdevice.h
2+++ b/include/linux/netdevice.h
3@@ -295,7 +295,9 @@ struct net_device
4 
5     /* List of functions to handle Wireless Extensions (instead of ioctl).
6      * See <net/iw_handler.h> for details. Jean II */
7- struct iw_handler_def * wireless_handlers;
8+ const struct iw_handler_def * wireless_handlers;
9+ /* Instance data managed by the core of Wireless Extensions. */
10+ struct iw_public_data * wireless_data;
11 
12     struct ethtool_ops *ethtool_ops;
13 
14--- a/include/linux/wireless.h
15+++ b/include/linux/wireless.h
16@@ -1,10 +1,10 @@
17 /*
18  * This file define a set of standard wireless extensions
19  *
20- * Version : 16 2.4.03
21+ * Version : 18 12.3.05
22  *
23  * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
24- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
25+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
26  */
27 
28 #ifndef _LINUX_WIRELESS_H
29@@ -47,12 +47,12 @@
30  * # include/net/iw_handler.h
31  *
32  * Note as well that /proc/net/wireless implementation has now moved in :
33- * # include/linux/wireless.c
34+ * # net/core/wireless.c
35  *
36  * Wireless Events (2002 -> onward) :
37  * --------------------------------
38  * Events are defined at the end of this file, and implemented in :
39- * # include/linux/wireless.c
40+ * # net/core/wireless.c
41  *
42  * Other comments :
43  * --------------
44@@ -82,7 +82,7 @@
45  * (there is some stuff that will be added in the future...)
46  * I just plan to increment with each new version.
47  */
48-#define WIRELESS_EXT 16
49+#define WIRELESS_EXT 18
50 
51 /*
52  * Changes :
53@@ -175,6 +175,28 @@
54  * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
55  * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
56  * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
57+ *
58+ * V16 to V17
59+ * ----------
60+ * - Add flags to frequency -> auto/fixed
61+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
62+ * - Wireless Event capability in struct iw_range
63+ * - Add support for relative TxPower (yick !)
64+ *
65+ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
66+ * ----------
67+ * - Add support for WPA/WPA2
68+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
69+ * SIOCGIWENCODEEXT)
70+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
71+ * - Add SIOCSIWMLME
72+ * - Add SIOCSIWPMKSA
73+ * - Add struct iw_range bit field for supported encoding capabilities
74+ * - Add optional scan request parameters for SIOCSIWSCAN
75+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
76+ * related parameters (extensible up to 4096 parameter values)
77+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
78+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
79  */
80 
81 /**************************** CONSTANTS ****************************/
82@@ -249,9 +271,33 @@
83 #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
84 #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
85 
86+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
87+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
88+ * fields. More than one IE may be included in the request. Setting the generic
89+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
90+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
91+ * are required to report the used IE as a wireless event, e.g., when
92+ * associating with an AP. */
93+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
94+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
95+
96+/* WPA : IEEE 802.11 MLME requests */
97+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
98+ * struct iw_mlme */
99+/* WPA : Authentication mode parameters */
100+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
101+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
102+
103+/* WPA : Extended version of encoding configuration */
104+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
105+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
106+
107+/* WPA2 : PMKSA cache management */
108+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
109+
110 /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
111 
112-/* These 16 ioctl are wireless device private.
113+/* These 32 ioctl are wireless device private, for 16 commands.
114  * Each driver is free to use them for whatever purpose it chooses,
115  * however the driver *must* export the description of those ioctls
116  * with SIOCGIWPRIV and *must* use arguments as defined below.
117@@ -266,8 +312,8 @@
118  * We now have 32 commands, so a bit more space ;-).
119  * Also, all 'odd' commands are only usable by root and don't return the
120  * content of ifr/iwr to user (but you are not obliged to use the set/get
121- * convention, just use every other two command).
122- * And I repeat : you are not obliged to use them with iwspy, but you
123+ * convention, just use every other two command). More details in iwpriv.c.
124+ * And I repeat : you are not forced to use them with iwpriv, but you
125  * must be compliant with it.
126  */
127 
128@@ -290,6 +336,34 @@
129 #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
130 #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
131 #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
132+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
133+ * (scan results); This includes id and
134+ * length fields. One IWEVGENIE may
135+ * contain more than one IE. Scan
136+ * results may contain one or more
137+ * IWEVGENIE events. */
138+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
139+ * (struct iw_michaelmicfailure)
140+ */
141+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
142+ * The data includes id and length
143+ * fields and may contain more than one
144+ * IE. This event is required in
145+ * Managed mode if the driver
146+ * generates its own WPA/RSN IE. This
147+ * should be sent just before
148+ * IWEVREGISTERED event for the
149+ * association. */
150+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
151+ * Response. The data includes id and
152+ * length fields and may contain more
153+ * than one IE. This may be sent
154+ * between IWEVASSOCREQIE and
155+ * IWEVREGISTERED events for the
156+ * association. */
157+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
158+ * pre-authentication
159+ * (struct iw_pmkid_cand) */
160 
161 #define IWEVFIRST 0x8C00
162 
163@@ -352,6 +426,18 @@
164 #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
165 #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
166 
167+/* Statistics flags (bitmask in updated) */
168+#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */
169+#define IW_QUAL_LEVEL_UPDATED 0x2
170+#define IW_QUAL_NOISE_UPDATED 0x4
171+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
172+#define IW_QUAL_LEVEL_INVALID 0x20
173+#define IW_QUAL_NOISE_INVALID 0x40
174+
175+/* Frequency flags */
176+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
177+#define IW_FREQ_FIXED 0x01 /* Force a specific value */
178+
179 /* Maximum number of size of encoding token available
180  * they are listed in the range structure */
181 #define IW_MAX_ENCODING_SIZES 8
182@@ -390,6 +476,7 @@
183 #define IW_TXPOW_TYPE 0x00FF /* Type of value */
184 #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
185 #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
186+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */
187 #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
188 
189 /* Retry limits and lifetime flags available */
190@@ -412,12 +499,113 @@
191 #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
192 #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
193 #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
194+/* struct iw_scan_req scan_type */
195+#define IW_SCAN_TYPE_ACTIVE 0
196+#define IW_SCAN_TYPE_PASSIVE 1
197 /* Maximum size of returned data */
198 #define IW_SCAN_MAX_DATA 4096 /* In bytes */
199 
200 /* Max number of char in custom event - use multiple of them if needed */
201 #define IW_CUSTOM_MAX 256 /* In bytes */
202 
203+/* Generic information element */
204+#define IW_GENERIC_IE_MAX 1024
205+
206+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
207+#define IW_MLME_DEAUTH 0
208+#define IW_MLME_DISASSOC 1
209+
210+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
211+#define IW_AUTH_INDEX 0x0FFF
212+#define IW_AUTH_FLAGS 0xF000
213+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
214+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
215+ * parameter that is being set/get to; value will be read/written to
216+ * struct iw_param value field) */
217+#define IW_AUTH_WPA_VERSION 0
218+#define IW_AUTH_CIPHER_PAIRWISE 1
219+#define IW_AUTH_CIPHER_GROUP 2
220+#define IW_AUTH_KEY_MGMT 3
221+#define IW_AUTH_TKIP_COUNTERMEASURES 4
222+#define IW_AUTH_DROP_UNENCRYPTED 5
223+#define IW_AUTH_80211_AUTH_ALG 6
224+#define IW_AUTH_WPA_ENABLED 7
225+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
226+#define IW_AUTH_ROAMING_CONTROL 9
227+#define IW_AUTH_PRIVACY_INVOKED 10
228+
229+/* IW_AUTH_WPA_VERSION values (bit field) */
230+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
231+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
232+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
233+
234+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
235+#define IW_AUTH_CIPHER_NONE 0x00000001
236+#define IW_AUTH_CIPHER_WEP40 0x00000002
237+#define IW_AUTH_CIPHER_TKIP 0x00000004
238+#define IW_AUTH_CIPHER_CCMP 0x00000008
239+#define IW_AUTH_CIPHER_WEP104 0x00000010
240+
241+/* IW_AUTH_KEY_MGMT values (bit field) */
242+#define IW_AUTH_KEY_MGMT_802_1X 1
243+#define IW_AUTH_KEY_MGMT_PSK 2
244+
245+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
246+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
247+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
248+#define IW_AUTH_ALG_LEAP 0x00000004
249+
250+/* IW_AUTH_ROAMING_CONTROL values */
251+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
252+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
253+ * control */
254+
255+/* SIOCSIWENCODEEXT definitions */
256+#define IW_ENCODE_SEQ_MAX_SIZE 8
257+/* struct iw_encode_ext ->alg */
258+#define IW_ENCODE_ALG_NONE 0
259+#define IW_ENCODE_ALG_WEP 1
260+#define IW_ENCODE_ALG_TKIP 2
261+#define IW_ENCODE_ALG_CCMP 3
262+/* struct iw_encode_ext ->ext_flags */
263+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
264+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
265+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
266+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
267+
268+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
269+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
270+#define IW_MICFAILURE_GROUP 0x00000004
271+#define IW_MICFAILURE_PAIRWISE 0x00000008
272+#define IW_MICFAILURE_STAKEY 0x00000010
273+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
274+ */
275+
276+/* Bit field values for enc_capa in struct iw_range */
277+#define IW_ENC_CAPA_WPA 0x00000001
278+#define IW_ENC_CAPA_WPA2 0x00000002
279+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
280+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
281+
282+/* Event capability macros - in (struct iw_range *)->event_capa
283+ * Because we have more than 32 possible events, we use an array of
284+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
285+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \
286+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \
287+ (cmd - SIOCSIWCOMMIT))
288+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5)
289+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
290+/* Event capability constants - event autogenerated by the kernel
291+ * This list is valid for most 802.11 devices, customise as needed... */
292+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \
293+ IW_EVENT_CAPA_MASK(0x8B06) | \
294+ IW_EVENT_CAPA_MASK(0x8B1A))
295+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A))
296+/* "Easy" macro to set events in iw_range (less efficient) */
297+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
298+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
299+
300+
301 /****************************** TYPES ******************************/
302 
303 /* --------------------------- SUBTYPES --------------------------- */
304@@ -456,7 +644,7 @@ struct iw_freq
305     __s32 m; /* Mantissa */
306     __s16 e; /* Exponent */
307     __u8 i; /* List index (when in range struct) */
308- __u8 pad; /* Unused - just for alignement */
309+ __u8 flags; /* Flags (fixed/auto) */
310 };
311 
312 /*
313@@ -507,6 +695,132 @@ struct iw_thrspy
314     struct iw_quality high; /* High threshold */
315 };
316 
317+/*
318+ * Optional data for scan request
319+ *
320+ * Note: these optional parameters are controlling parameters for the
321+ * scanning behavior, these do not apply to getting scan results
322+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
323+ * provide a merged results with all BSSes even if the previous scan
324+ * request limited scanning to a subset, e.g., by specifying an SSID.
325+ * Especially, scan results are required to include an entry for the
326+ * current BSS if the driver is in Managed mode and associated with an AP.
327+ */
328+struct iw_scan_req
329+{
330+ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
331+ __u8 essid_len;
332+ __u8 num_channels; /* num entries in channel_list;
333+ * 0 = scan all allowed channels */
334+ __u8 flags; /* reserved as padding; use zero, this may
335+ * be used in the future for adding flags
336+ * to request different scan behavior */
337+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
338+ * individual address of a specific BSS */
339+
340+ /*
341+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
342+ * the current ESSID. This allows scan requests for specific ESSID
343+ * without having to change the current ESSID and potentially breaking
344+ * the current association.
345+ */
346+ __u8 essid[IW_ESSID_MAX_SIZE];
347+
348+ /*
349+ * Optional parameters for changing the default scanning behavior.
350+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
351+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
352+ * reasonable default values. min_channel_time defines the time that
353+ * will be used to wait for the first reply on each channel. If no
354+ * replies are received, next channel will be scanned after this. If
355+ * replies are received, total time waited on the channel is defined by
356+ * max_channel_time.
357+ */
358+ __u32 min_channel_time; /* in TU */
359+ __u32 max_channel_time; /* in TU */
360+
361+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
362+};
363+
364+/* ------------------------- WPA SUPPORT ------------------------- */
365+
366+/*
367+ * Extended data structure for get/set encoding (this is used with
368+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
369+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
370+ * only the data contents changes (key data -> this structure, including
371+ * key data).
372+ *
373+ * If the new key is the first group key, it will be set as the default
374+ * TX key. Otherwise, default TX key index is only changed if
375+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
376+ *
377+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
378+ * special "change TX key index" operation which is indicated by setting
379+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
380+ *
381+ * tx_seq/rx_seq are only used when respective
382+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
383+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
384+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
385+ * used only by an Authenticator (AP or an IBSS station) to get the
386+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
387+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
388+ * debugging/testing.
389+ */
390+struct iw_encode_ext
391+{
392+ __u32 ext_flags; /* IW_ENCODE_EXT_* */
393+ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
394+ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
395+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
396+ * (group) keys or unicast address for
397+ * individual keys */
398+ __u16 alg; /* IW_ENCODE_ALG_* */
399+ __u16 key_len;
400+ __u8 key[0];
401+};
402+
403+/* SIOCSIWMLME data */
404+struct iw_mlme
405+{
406+ __u16 cmd; /* IW_MLME_* */
407+ __u16 reason_code;
408+ struct sockaddr addr;
409+};
410+
411+/* SIOCSIWPMKSA data */
412+#define IW_PMKSA_ADD 1
413+#define IW_PMKSA_REMOVE 2
414+#define IW_PMKSA_FLUSH 3
415+
416+#define IW_PMKID_LEN 16
417+
418+struct iw_pmksa
419+{
420+ __u32 cmd; /* IW_PMKSA_* */
421+ struct sockaddr bssid;
422+ __u8 pmkid[IW_PMKID_LEN];
423+};
424+
425+/* IWEVMICHAELMICFAILURE data */
426+struct iw_michaelmicfailure
427+{
428+ __u32 flags;
429+ struct sockaddr src_addr;
430+ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
431+};
432+
433+/* IWEVPMKIDCAND data */
434+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
435+struct iw_pmkid_cand
436+{
437+ __u32 flags; /* IW_PMKID_CAND_* */
438+ __u32 index; /* the smaller the index, the higher the
439+ * priority */
440+ struct sockaddr bssid;
441+};
442+
443 /* ------------------------ WIRELESS STATS ------------------------ */
444 /*
445  * Wireless statistics (used for /proc/net/wireless)
446@@ -610,11 +924,12 @@ struct iw_range
447     /* Old Frequency (backward compat - moved lower ) */
448     __u16 old_num_channels;
449     __u8 old_num_frequency;
450- /* Filler to keep "version" at the same offset */
451- __s32 old_freq[6];
452+
453+ /* Wireless event capability bitmasks */
454+ __u32 event_capa[6];
455 
456     /* signal level threshold range */
457- __s32 sensitivity;
458+ __s32 sensitivity;
459 
460     /* Quality of link & SNR stuff */
461     /* Quality range (link, level, noise)
462@@ -685,6 +1000,8 @@ struct iw_range
463     struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
464     /* Note : this frequency list doesn't need to fit channel numbers,
465      * because each entry contain its channel index */
466+
467+ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
468 };
469 
470 /*
471--- a/include/net/iw_handler.h
472+++ b/include/net/iw_handler.h
473@@ -1,10 +1,10 @@
474 /*
475  * This file define the new driver API for Wireless Extensions
476  *
477- * Version : 5 4.12.02
478+ * Version : 6 21.6.04
479  *
480  * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
481- * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
482+ * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved.
483  */
484 
485 #ifndef _IW_HANDLER_H
486@@ -206,7 +206,7 @@
487  * will be needed...
488  * I just plan to increment with each new version.
489  */
490-#define IW_HANDLER_VERSION 5
491+#define IW_HANDLER_VERSION 6
492 
493 /*
494  * Changes :
495@@ -224,11 +224,18 @@
496  * V4 to V5
497  * --------
498  * - Add new spy support : struct iw_spy_data & prototypes
499+ *
500+ * V5 to V6
501+ * --------
502+ * - Change the way we get to spy_data method for added safety
503+ * - Remove spy #ifdef, they are always on -> cleaner code
504+ * - Add IW_DESCR_FLAG_NOMAX flag for very large requests
505+ * - Start migrating get_wireless_stats to struct iw_handler_def
506  */
507 
508 /**************************** CONSTANTS ****************************/
509 
510-/* Enable enhanced spy support. Disable to reduce footprint */
511+/* Enhanced spy support available */
512 #define IW_WIRELESS_SPY
513 #define IW_WIRELESS_THRSPY
514 
515@@ -258,6 +265,7 @@
516 #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
517 #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
518                 /* SET : Omit payload from generated iwevent */
519+#define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */
520 /* Driver level flags */
521 #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
522 
523@@ -311,23 +319,25 @@ struct iw_handler_def
524     /* Array of handlers for standard ioctls
525      * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
526      */
527- iw_handler * standard;
528+ const iw_handler * standard;
529 
530     /* Array of handlers for private ioctls
531      * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
532      */
533- iw_handler * private;
534+ const iw_handler * private;
535 
536     /* Arguments of private handler. This one is just a list, so you
537      * can put it in any order you want and should not leave holes...
538      * We will automatically export that to user space... */
539- struct iw_priv_args * private_args;
540+ const struct iw_priv_args * private_args;
541 
542- /* Driver enhanced spy support */
543- long spy_offset; /* Spy data offset */
544+ /* This field will be *removed* in the next version of WE */
545+ long spy_offset; /* DO NOT USE */
546 
547- /* In the long term, get_wireless_stats will move from
548- * 'struct net_device' to here, to minimise bloat. */
549+ /* New location of get_wireless_stats, to de-bloat struct net_device.
550+ * The old pointer in struct net_device will be gradually phased
551+ * out, and drivers are encouraged to use this one... */
552+ struct iw_statistics* (*get_wireless_stats)(struct net_device *dev);
553 };
554 
555 /* ---------------------- IOCTL DESCRIPTION ---------------------- */
556@@ -374,18 +384,29 @@ struct iw_ioctl_description
557  */
558 struct iw_spy_data
559 {
560-#ifdef IW_WIRELESS_SPY
561     /* --- Standard spy support --- */
562     int spy_number;
563     u_char spy_address[IW_MAX_SPY][ETH_ALEN];
564     struct iw_quality spy_stat[IW_MAX_SPY];
565-#ifdef IW_WIRELESS_THRSPY
566     /* --- Enhanced spy support (event) */
567     struct iw_quality spy_thr_low; /* Low threshold */
568     struct iw_quality spy_thr_high; /* High threshold */
569     u_char spy_thr_under[IW_MAX_SPY];
570-#endif /* IW_WIRELESS_THRSPY */
571-#endif /* IW_WIRELESS_SPY */
572+};
573+
574+/* --------------------- DEVICE WIRELESS DATA --------------------- */
575+/*
576+ * This is all the wireless data specific to a device instance that
577+ * is managed by the core of Wireless Extensions.
578+ * We only keep pointer to those structures, so that a driver is free
579+ * to share them between instances.
580+ * This structure should be initialised before registering the device.
581+ * Access to this data follow the same rules as any other struct net_device
582+ * data (i.e. valid as long as struct net_device exist, same locking rules).
583+ */
584+struct iw_public_data {
585+ /* Driver enhanced spy support */
586+ struct iw_spy_data * spy_data;
587 };
588 
589 /**************************** PROTOTYPES ****************************/
590--- a/net/core/dev.c
591+++ b/net/core/dev.c
592@@ -2426,7 +2426,7 @@ int dev_ioctl(unsigned int cmd, void *ar
593                 /* Follow me in net/core/wireless.c */
594                 ret = wireless_process_ioctl(&ifr, cmd);
595                 rtnl_unlock();
596- if (!ret && IW_IS_GET(cmd) &&
597+ if (IW_IS_GET(cmd) &&
598                     copy_to_user(arg, &ifr, sizeof(struct ifreq)))
599                     return -EFAULT;
600                 return ret;
601--- a/net/core/wireless.c
602+++ b/net/core/wireless.c
603@@ -2,7 +2,7 @@
604  * This file implement the Wireless Extensions APIs.
605  *
606  * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
607- * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
608+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
609  *
610  * (As all part of the Linux kernel, this file is GPL)
611  */
612@@ -48,6 +48,16 @@
613  * o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
614  * o Add enhanced spy support : iw_handler_set_thrspy() and event.
615  * o Add WIRELESS_EXT version display in /proc/net/wireless
616+ *
617+ * v6 - 18.06.04 - Jean II
618+ * o Change get_spydata() method for added safety
619+ * o Remove spy #ifdef, they are always on -> cleaner code
620+ * o Allow any size GET request if user specifies length > max
621+ * and if request has IW_DESCR_FLAG_NOMAX flag or is SIOCGIWPRIV
622+ * o Start migrating get_wireless_stats to struct iw_handler_def
623+ * o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus
624+ * Based on patch from Pavel Roskin <proski@gnu.org> :
625+ * o Fix kernel data leak to user space in private handler handling
626  */
627 
628 /***************************** INCLUDES *****************************/
629@@ -64,11 +74,7 @@
630 
631 /**************************** CONSTANTS ****************************/
632 
633-/* Enough lenience, let's make sure things are proper... */
634-#define WE_STRICT_WRITE /* Check write buffer size */
635-/* I'll probably drop both the define and kernel message in the next version */
636-
637-/* Debuging stuff */
638+/* Debugging stuff */
639 #undef WE_IOCTL_DEBUG /* Debug IOCTL API */
640 #undef WE_EVENT_DEBUG /* Debug Event dispatcher */
641 #undef WE_SPY_DEBUG /* Debug enhanced spy support */
642@@ -131,14 +137,14 @@ static const struct iw_ioctl_description
643     { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
644     /* SIOCGIWAP */
645     { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
646- /* -- hole -- */
647- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
648+ /* SIOCSIWMLME */
649+ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_mlme), sizeof(struct iw_mlme), 0},
650     /* SIOCGIWAPLIST */
651- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
652+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, IW_DESCR_FLAG_NOMAX},
653     /* SIOCSIWSCAN */
654- { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
655+ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_scan_req), 0},
656     /* SIOCGIWSCAN */
657- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0},
658+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, IW_DESCR_FLAG_NOMAX},
659     /* SIOCSIWESSID */
660     { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT},
661     /* SIOCGIWESSID */
662@@ -179,6 +185,25 @@ static const struct iw_ioctl_description
663     { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
664     /* SIOCGIWPOWER */
665     { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
666+ /* -- hole -- */
667+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
668+ /* -- hole -- */
669+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
670+ /* SIOCSIWGENIE */
671+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
672+ /* SIOCGIWGENIE */
673+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
674+ /* SIOCSIWAUTH */
675+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
676+ /* SIOCGIWAUTH */
677+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
678+ /* SIOCSIWENCODEEXT */
679+ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0},
680+ /* SIOCGIWENCODEEXT */
681+ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0},
682+ /* SIOCSIWPMKSA */
683+ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_pmksa), sizeof(struct iw_pmksa), 0},
684+ /* -- hole -- */
685 };
686 static const int standard_ioctl_num = (sizeof(standard_ioctl) /
687                        sizeof(struct iw_ioctl_description));
688@@ -198,12 +223,22 @@ static const struct iw_ioctl_description
689     { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
690     /* IWEVEXPIRED */
691     { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
692+ /* IWEVGENIE */
693+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
694+ /* IWEVMICHAELMICFAILURE */
695+ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_michaelmicfailure), 0},
696+ /* IWEVASSOCREQIE */
697+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
698+ /* IWEVASSOCRESPIE */
699+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
700+ /* IWEVPMKIDCAND */
701+ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_pmkid_cand), 0},
702 };
703 static const int standard_event_num = (sizeof(standard_event) /
704                        sizeof(struct iw_ioctl_description));
705 
706 /* Size (in bytes) of the various private data types */
707-static const char priv_type_size[] = {
708+static const char iw_priv_type_size[] = {
709     0, /* IW_PRIV_TYPE_NONE */
710     1, /* IW_PRIV_TYPE_BYTE */
711     1, /* IW_PRIV_TYPE_CHAR */
712@@ -270,12 +305,15 @@ static inline iw_handler get_handler(str
713  */
714 static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
715 {
716+ /* New location */
717+ if((dev->wireless_handlers != NULL) &&
718+ (dev->wireless_handlers->get_wireless_stats != NULL))
719+ return dev->wireless_handlers->get_wireless_stats(dev);
720+
721+ /* Old location, will be phased out in next WE */
722     return (dev->get_wireless_stats ?
723         dev->get_wireless_stats(dev) :
724         (struct iw_statistics *) NULL);
725- /* In the future, get_wireless_stats may move from 'struct net_device'
726- * to 'struct iw_handler_def', to de-bloat struct net_device.
727- * Definitely worse a thought... */
728 }
729 
730 /* ---------------------------------------------------------------- */
731@@ -310,14 +348,32 @@ static inline int call_commit_handler(st
732 
733 /* ---------------------------------------------------------------- */
734 /*
735- * Number of private arguments
736+ * Calculate size of private arguments
737  */
738 static inline int get_priv_size(__u16 args)
739 {
740     int num = args & IW_PRIV_SIZE_MASK;
741     int type = (args & IW_PRIV_TYPE_MASK) >> 12;
742 
743- return num * priv_type_size[type];
744+ return num * iw_priv_type_size[type];
745+}
746+
747+/* ---------------------------------------------------------------- */
748+/*
749+ * Re-calculate the size of private arguments
750+ */
751+static inline int adjust_priv_size(__u16 args,
752+ union iwreq_data * wrqu)
753+{
754+ int num = wrqu->data.length;
755+ int max = args & IW_PRIV_SIZE_MASK;
756+ int type = (args & IW_PRIV_TYPE_MASK) >> 12;
757+
758+ /* Make sure the driver doesn't goof up */
759+ if (max < num)
760+ num = max;
761+
762+ return num * iw_priv_type_size[type];
763 }
764 
765 
766@@ -350,11 +406,14 @@ static inline int sprintf_wireless_stats
767                    dev->name,
768                    stats->status,
769                    stats->qual.qual,
770- stats->qual.updated & 1 ? '.' : ' ',
771+ stats->qual.updated & IW_QUAL_QUAL_UPDATED
772+ ? '.' : ' ',
773                    ((__u8) stats->qual.level),
774- stats->qual.updated & 2 ? '.' : ' ',
775+ stats->qual.updated & IW_QUAL_LEVEL_UPDATED
776+ ? '.' : ' ',
777                    ((__u8) stats->qual.noise),
778- stats->qual.updated & 4 ? '.' : ' ',
779+ stats->qual.updated & IW_QUAL_NOISE_UPDATED
780+ ? '.' : ' ',
781                    stats->discard.nwid,
782                    stats->discard.code,
783                    stats->discard.fragment,
784@@ -470,13 +529,15 @@ static inline int ioctl_export_private(s
785     /* Check NULL pointer */
786     if(iwr->u.data.pointer == NULL)
787         return -EFAULT;
788-#ifdef WE_STRICT_WRITE
789+
790     /* Check if there is enough buffer up there */
791     if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
792- 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);
793+ /* User space can't know in advance how large the buffer
794+ * needs to be. Give it a hint, so that we can support
795+ * any size buffer we want somewhat efficiently... */
796+ iwr->u.data.length = dev->wireless_handlers->num_private_args;
797         return -E2BIG;
798     }
799-#endif /* WE_STRICT_WRITE */
800 
801     /* Set the number of available ioctls. */
802     iwr->u.data.length = dev->wireless_handlers->num_private_args;
803@@ -505,7 +566,6 @@ static inline int ioctl_standard_call(st
804     const struct iw_ioctl_description * descr;
805     struct iw_request_info info;
806     int ret = -EINVAL;
807- int user_size = 0;
808 
809     /* Get the description of the IOCTL */
810     if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
811@@ -536,8 +596,14 @@ static inline int ioctl_standard_call(st
812 #endif /* WE_SET_EVENT */
813     } else {
814         char * extra;
815+ int extra_size;
816+ int user_length = 0;
817         int err;
818 
819+ /* Calculate space needed by arguments. Always allocate
820+ * for max space. Easier, and won't last long... */
821+ extra_size = descr->max_tokens * descr->token_size;
822+
823         /* Check what user space is giving us */
824         if(IW_IS_SET(cmd)) {
825             /* Check NULL pointer */
826@@ -554,18 +620,33 @@ static inline int ioctl_standard_call(st
827             if(iwr->u.data.pointer == NULL)
828                 return -EFAULT;
829             /* Save user space buffer size for checking */
830- user_size = iwr->u.data.length;
831+ user_length = iwr->u.data.length;
832+
833+ /* Don't check if user_length > max to allow forward
834+ * compatibility. The test user_length < min is
835+ * implied by the test at the end. */
836+
837+ /* Support for very large requests */
838+ if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
839+ (user_length > descr->max_tokens)) {
840+ /* Allow userspace to GET more than max so
841+ * we can support any size GET requests.
842+ * There is still a limit : -ENOMEM. */
843+ extra_size = user_length * descr->token_size;
844+ /* Note : user_length is originally a __u16,
845+ * and token_size is controlled by us,
846+ * so extra_size won't get negative and
847+ * won't overflow... */
848+ }
849         }
850 
851 #ifdef WE_IOCTL_DEBUG
852         printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
853- dev->name, descr->max_tokens * descr->token_size);
854+ dev->name, extra_size);
855 #endif /* WE_IOCTL_DEBUG */
856 
857- /* Always allocate for max space. Easier, and won't last
858- * long... */
859- extra = kmalloc(descr->max_tokens * descr->token_size,
860- GFP_KERNEL);
861+ /* Create the kernel buffer */
862+ extra = kmalloc(extra_size, GFP_KERNEL);
863         if (extra == NULL) {
864             return -ENOMEM;
865         }
866@@ -591,14 +672,11 @@ static inline int ioctl_standard_call(st
867 
868         /* If we have something to return to the user */
869         if (!ret && IW_IS_GET(cmd)) {
870-#ifdef WE_STRICT_WRITE
871             /* Check if there is enough buffer up there */
872- if(user_size < iwr->u.data.length) {
873- printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length);
874+ if(user_length < iwr->u.data.length) {
875                 kfree(extra);
876                 return -E2BIG;
877             }
878-#endif /* WE_STRICT_WRITE */
879 
880             err = copy_to_user(iwr->u.data.pointer, extra,
881                        iwr->u.data.length *
882@@ -661,7 +739,7 @@ static inline int ioctl_private_call(str
883                      iw_handler handler)
884 {
885     struct iwreq * iwr = (struct iwreq *) ifr;
886- struct iw_priv_args * descr = NULL;
887+ const struct iw_priv_args * descr = NULL;
888     struct iw_request_info info;
889     int extra_size = 0;
890     int i;
891@@ -701,7 +779,7 @@ static inline int ioctl_private_call(str
892                ((extra_size + offset) <= IFNAMSIZ))
893                 extra_size = 0;
894         } else {
895- /* Size of set arguments */
896+ /* Size of get arguments */
897             extra_size = get_priv_size(descr->get_args);
898 
899             /* Does it fits in iwr ? */
900@@ -771,6 +849,14 @@ static inline int ioctl_private_call(str
901 
902         /* If we have something to return to the user */
903         if (!ret && IW_IS_GET(cmd)) {
904+
905+ /* Adjust for the actual length if it's variable,
906+ * avoid leaking kernel bits outside. */
907+ if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) {
908+ extra_size = adjust_priv_size(descr->get_args,
909+ &(iwr->u));
910+ }
911+
912             err = copy_to_user(iwr->u.data.pointer, extra,
913                        extra_size);
914             if (err)
915@@ -1043,9 +1129,25 @@ void wireless_send_event(struct net_devi
916  * One of the main advantage of centralising spy support here is that
917  * it becomes much easier to improve and extend it without having to touch
918  * the drivers. One example is the addition of the Spy-Threshold events.
919- * Note : IW_WIRELESS_SPY is defined in iw_handler.h
920  */
921 
922+/* ---------------------------------------------------------------- */
923+/*
924+ * Return the pointer to the spy data in the driver.
925+ * Because this is called on the Rx path via wireless_spy_update(),
926+ * we want it to be efficient...
927+ */
928+static inline struct iw_spy_data * get_spydata(struct net_device *dev)
929+{
930+ /* This is the new way */
931+ if(dev->wireless_data)
932+ return(dev->wireless_data->spy_data);
933+
934+ /* This is the old way. Doesn't work for multi-headed drivers.
935+ * It will be removed in the next version of WE. */
936+ return (dev->priv + dev->wireless_handlers->spy_offset);
937+}
938+
939 /*------------------------------------------------------------------*/
940 /*
941  * Standard Wireless Handler : set Spy List
942@@ -1055,16 +1157,26 @@ int iw_handler_set_spy(struct net_device
943                union iwreq_data * wrqu,
944                char * extra)
945 {
946-#ifdef IW_WIRELESS_SPY
947- struct iw_spy_data * spydata = (dev->priv +
948- dev->wireless_handlers->spy_offset);
949+ struct iw_spy_data * spydata = get_spydata(dev);
950     struct sockaddr * address = (struct sockaddr *) extra;
951 
952+ /* Make sure driver is not buggy or using the old API */
953+ if(!spydata)
954+ return -EOPNOTSUPP;
955+
956     /* Disable spy collection while we copy the addresses.
957- * As we don't disable interrupts, we need to do this to avoid races.
958- * As we are the only writer, this is good enough. */
959+ * While we copy addresses, any call to wireless_spy_update()
960+ * will NOP. This is OK, as anyway the addresses are changing. */
961     spydata->spy_number = 0;
962 
963+ /* We want to operate without locking, because wireless_spy_update()
964+ * most likely will happen in the interrupt handler, and therefore
965+ * have its own locking constraints and needs performance.
966+ * The rtnl_lock() make sure we don't race with the other iw_handlers.
967+ * This make sure wireless_spy_update() "see" that the spy list
968+ * is temporarily disabled. */
969+ wmb();
970+
971     /* Are there are addresses to copy? */
972     if(wrqu->data.length > 0) {
973         int i;
974@@ -1090,13 +1202,14 @@ int iw_handler_set_spy(struct net_device
975                    spydata->spy_address[i][5]);
976 #endif /* WE_SPY_DEBUG */
977     }
978+
979+ /* Make sure above is updated before re-enabling */
980+ wmb();
981+
982     /* Enable addresses */
983     spydata->spy_number = wrqu->data.length;
984 
985     return 0;
986-#else /* IW_WIRELESS_SPY */
987- return -EOPNOTSUPP;
988-#endif /* IW_WIRELESS_SPY */
989 }
990 
991 /*------------------------------------------------------------------*/
992@@ -1108,12 +1221,14 @@ int iw_handler_get_spy(struct net_device
993                union iwreq_data * wrqu,
994                char * extra)
995 {
996-#ifdef IW_WIRELESS_SPY
997- struct iw_spy_data * spydata = (dev->priv +
998- dev->wireless_handlers->spy_offset);
999+ struct iw_spy_data * spydata = get_spydata(dev);
1000     struct sockaddr * address = (struct sockaddr *) extra;
1001     int i;
1002 
1003+ /* Make sure driver is not buggy or using the old API */
1004+ if(!spydata)
1005+ return -EOPNOTSUPP;
1006+
1007     wrqu->data.length = spydata->spy_number;
1008 
1009     /* Copy addresses. */
1010@@ -1130,9 +1245,6 @@ int iw_handler_get_spy(struct net_device
1011     for(i = 0; i < spydata->spy_number; i++)
1012         spydata->spy_stat[i].updated = 0;
1013     return 0;
1014-#else /* IW_WIRELESS_SPY */
1015- return -EOPNOTSUPP;
1016-#endif /* IW_WIRELESS_SPY */
1017 }
1018 
1019 /*------------------------------------------------------------------*/
1020@@ -1144,11 +1256,13 @@ int iw_handler_set_thrspy(struct net_dev
1021               union iwreq_data * wrqu,
1022               char * extra)
1023 {
1024-#ifdef IW_WIRELESS_THRSPY
1025- struct iw_spy_data * spydata = (dev->priv +
1026- dev->wireless_handlers->spy_offset);
1027+ struct iw_spy_data * spydata = get_spydata(dev);
1028     struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
1029 
1030+ /* Make sure driver is not buggy or using the old API */
1031+ if(!spydata)
1032+ return -EOPNOTSUPP;
1033+
1034     /* Just do it */
1035     memcpy(&(spydata->spy_thr_low), &(threshold->low),
1036            2 * sizeof(struct iw_quality));
1037@@ -1161,9 +1275,6 @@ int iw_handler_set_thrspy(struct net_dev
1038 #endif /* WE_SPY_DEBUG */
1039 
1040     return 0;
1041-#else /* IW_WIRELESS_THRSPY */
1042- return -EOPNOTSUPP;
1043-#endif /* IW_WIRELESS_THRSPY */
1044 }
1045 
1046 /*------------------------------------------------------------------*/
1047@@ -1175,22 +1286,20 @@ int iw_handler_get_thrspy(struct net_dev
1048               union iwreq_data * wrqu,
1049               char * extra)
1050 {
1051-#ifdef IW_WIRELESS_THRSPY
1052- struct iw_spy_data * spydata = (dev->priv +
1053- dev->wireless_handlers->spy_offset);
1054+ struct iw_spy_data * spydata = get_spydata(dev);
1055     struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
1056 
1057+ /* Make sure driver is not buggy or using the old API */
1058+ if(!spydata)
1059+ return -EOPNOTSUPP;
1060+
1061     /* Just do it */
1062     memcpy(&(threshold->low), &(spydata->spy_thr_low),
1063            2 * sizeof(struct iw_quality));
1064 
1065     return 0;
1066-#else /* IW_WIRELESS_THRSPY */
1067- return -EOPNOTSUPP;
1068-#endif /* IW_WIRELESS_THRSPY */
1069 }
1070 
1071-#ifdef IW_WIRELESS_THRSPY
1072 /*------------------------------------------------------------------*/
1073 /*
1074  * Prepare and send a Spy Threshold event
1075@@ -1228,7 +1337,6 @@ static void iw_send_thrspy_event(struct
1076     /* Send event to user space */
1077     wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
1078 }
1079-#endif /* IW_WIRELESS_THRSPY */
1080 
1081 /* ---------------------------------------------------------------- */
1082 /*
1083@@ -1241,12 +1349,14 @@ void wireless_spy_update(struct net_devi
1084              unsigned char * address,
1085              struct iw_quality * wstats)
1086 {
1087-#ifdef IW_WIRELESS_SPY
1088- struct iw_spy_data * spydata = (dev->priv +
1089- dev->wireless_handlers->spy_offset);
1090+ struct iw_spy_data * spydata = get_spydata(dev);
1091     int i;
1092     int match = -1;
1093 
1094+ /* Make sure driver is not buggy or using the old API */
1095+ if(!spydata)
1096+ return;
1097+
1098 #ifdef WE_SPY_DEBUG
1099     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]);
1100 #endif /* WE_SPY_DEBUG */
1101@@ -1258,7 +1368,7 @@ void wireless_spy_update(struct net_devi
1102                    sizeof(struct iw_quality));
1103             match = i;
1104         }
1105-#ifdef IW_WIRELESS_THRSPY
1106+
1107     /* Generate an event if we cross the spy threshold.
1108      * To avoid event storms, we have a simple hysteresis : we generate
1109      * event only when we go under the low threshold or above the
1110@@ -1278,6 +1388,4 @@ void wireless_spy_update(struct net_devi
1111             }
1112         }
1113     }
1114-#endif /* IW_WIRELESS_THRSPY */
1115-#endif /* IW_WIRELESS_SPY */
1116 }
1117

Archive Download this file



interactive