da65961b1fb1a5c854194bbaf5569059d33ded3f
[openwrt/staging/yousong.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 }