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