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