]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/files/iw249_we17-13.diff
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / files / iw249_we17-13.diff
1 diff -u -p linux/include/linux/netdevice.we16.h linux/include/linux/netdevice.h
2 --- linux/include/linux/netdevice.we16.h        2005-02-03 14:54:56.000000000 -0800
3 +++ linux/include/linux/netdevice.h     2005-02-03 15:43:30.000000000 -0800
4 @@ -295,7 +295,9 @@ struct net_device
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 -u -p linux/include/linux/wireless.we16.h linux/include/linux/wireless.h
16 --- linux/include/linux/wireless.we16.h 2005-02-03 14:55:04.000000000 -0800
17 +++ linux/include/linux/wireless.h      2005-02-03 15:44:48.000000000 -0800
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 :   17      21.6.04
24   *
25   * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
26 - * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
27 + * Copyright (c) 1997-2004 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   17
52  
53  /*
54   * Changes :
55 @@ -175,6 +175,13 @@
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  
68  /**************************** CONSTANTS ****************************/
69 @@ -251,7 +258,7 @@
70  
71  /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
72  
73 -/* These 16 ioctl are wireless device private.
74 +/* These 32 ioctl are wireless device private, for 16 commands.
75   * Each driver is free to use them for whatever purpose it chooses,
76   * however the driver *must* export the description of those ioctls
77   * with SIOCGIWPRIV and *must* use arguments as defined below.
78 @@ -266,8 +273,8 @@
79   * We now have 32 commands, so a bit more space ;-).
80   * Also, all 'odd' commands are only usable by root and don't return the
81   * content of ifr/iwr to user (but you are not obliged to use the set/get
82 - * convention, just use every other two command).
83 - * And I repeat : you are not obliged to use them with iwspy, but you
84 + * convention, just use every other two command). More details in iwpriv.c.
85 + * And I repeat : you are not forced to use them with iwpriv, but you
86   * must be compliant with it.
87   */
88  
89 @@ -352,6 +359,18 @@
90  #define IW_MODE_SECOND 5       /* Secondary master/repeater (backup) */
91  #define IW_MODE_MONITOR        6       /* Passive monitor (listen only) */
92  
93 +/* Statistics flags (bitmask in updated) */
94 +#define IW_QUAL_QUAL_UPDATED   0x1     /* Value was updated since last read */
95 +#define IW_QUAL_LEVEL_UPDATED  0x2
96 +#define IW_QUAL_NOISE_UPDATED  0x4
97 +#define IW_QUAL_QUAL_INVALID   0x10    /* Driver doesn't provide value */
98 +#define IW_QUAL_LEVEL_INVALID  0x20
99 +#define IW_QUAL_NOISE_INVALID  0x40
100 +
101 +/* Frequency flags */
102 +#define IW_FREQ_AUTO           0x00    /* Let the driver decides */
103 +#define IW_FREQ_FIXED          0x01    /* Force a specific value */
104 +
105  /* Maximum number of size of encoding token available
106   * they are listed in the range structure */
107  #define IW_MAX_ENCODING_SIZES  8
108 @@ -390,6 +409,7 @@
109  #define IW_TXPOW_TYPE          0x00FF  /* Type of value */
110  #define IW_TXPOW_DBM           0x0000  /* Value is in dBm */
111  #define IW_TXPOW_MWATT         0x0001  /* Value is in mW */
112 +#define IW_TXPOW_RELATIVE      0x0002  /* Value is in arbitrary units */
113  #define IW_TXPOW_RANGE         0x1000  /* Range of value between min/max */
114  
115  /* Retry limits and lifetime flags available */
116 @@ -418,6 +438,25 @@
117  /* Max number of char in custom event - use multiple of them if needed */
118  #define IW_CUSTOM_MAX          256     /* In bytes */
119  
120 +/* Event capability macros - in (struct iw_range *)->event_capa
121 + * Because we have more than 32 possible events, we use an array of
122 + * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
123 +#define IW_EVENT_CAPA_BASE(cmd)                ((cmd >= SIOCIWFIRSTPRIV) ? \
124 +                                        (cmd - SIOCIWFIRSTPRIV + 0x60) : \
125 +                                        (cmd - SIOCSIWCOMMIT))
126 +#define IW_EVENT_CAPA_INDEX(cmd)       (IW_EVENT_CAPA_BASE(cmd) >> 5)
127 +#define IW_EVENT_CAPA_MASK(cmd)                (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
128 +/* Event capability constants - event autogenerated by the kernel
129 + * This list is valid for most 802.11 devices, customise as needed... */
130 +#define IW_EVENT_CAPA_K_0      (IW_EVENT_CAPA_MASK(0x8B04) | \
131 +                                IW_EVENT_CAPA_MASK(0x8B06) | \
132 +                                IW_EVENT_CAPA_MASK(0x8B1A))
133 +#define IW_EVENT_CAPA_K_1      (IW_EVENT_CAPA_MASK(0x8B2A))
134 +/* "Easy" macro to set events in iw_range (less efficient) */
135 +#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
136 +#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
137 +
138 +
139  /****************************** TYPES ******************************/
140  
141  /* --------------------------- SUBTYPES --------------------------- */
142 @@ -456,7 +495,7 @@ struct      iw_freq
143         __s32           m;              /* Mantissa */
144         __s16           e;              /* Exponent */
145         __u8            i;              /* List index (when in range struct) */
146 -       __u8            pad;            /* Unused - just for alignement */
147 +       __u8            flags;          /* Flags (fixed/auto) */
148  };
149  
150  /*
151 @@ -610,11 +649,12 @@ struct    iw_range
152         /* Old Frequency (backward compat - moved lower ) */
153         __u16           old_num_channels;
154         __u8            old_num_frequency;
155 -       /* Filler to keep "version" at the same offset */
156 -       __s32           old_freq[6];
157 +
158 +       /* Wireless event capability bitmasks */
159 +       __u32           event_capa[6];
160  
161         /* signal level threshold range */
162 -       __s32   sensitivity;
163 +       __s32           sensitivity;
164  
165         /* Quality of link & SNR stuff */
166         /* Quality range (link, level, noise)
167 diff -u -p linux/include/net/iw_handler.we16.h linux/include/net/iw_handler.h
168 --- linux/include/net/iw_handler.we16.h 2005-02-03 14:55:26.000000000 -0800
169 +++ linux/include/net/iw_handler.h      2005-02-03 15:47:04.000000000 -0800
170 @@ -1,10 +1,10 @@
171  /*
172   * This file define the new driver API for Wireless Extensions
173   *
174 - * Version :   5       4.12.02
175 + * Version :   6       21.6.04
176   *
177   * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
178 - * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
179 + * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved.
180   */
181  
182  #ifndef _IW_HANDLER_H
183 @@ -206,7 +206,7 @@
184   * will be needed...
185   * I just plan to increment with each new version.
186   */
187 -#define IW_HANDLER_VERSION     5
188 +#define IW_HANDLER_VERSION     6
189  
190  /*
191   * Changes :
192 @@ -224,11 +224,18 @@
193   * V4 to V5
194   * --------
195   *     - Add new spy support : struct iw_spy_data & prototypes
196 + *
197 + * V5 to V6
198 + * --------
199 + *     - Change the way we get to spy_data method for added safety
200 + *     - Remove spy #ifdef, they are always on -> cleaner code
201 + *     - Add IW_DESCR_FLAG_NOMAX flag for very large requests
202 + *     - Start migrating get_wireless_stats to struct iw_handler_def
203   */
204  
205  /**************************** CONSTANTS ****************************/
206  
207 -/* Enable enhanced spy support. Disable to reduce footprint */
208 +/* Enhanced spy support available */
209  #define IW_WIRELESS_SPY
210  #define IW_WIRELESS_THRSPY
211  
212 @@ -258,6 +265,7 @@
213  #define IW_DESCR_FLAG_EVENT    0x0002  /* Generate an event on SET */
214  #define IW_DESCR_FLAG_RESTRICT 0x0004  /* GET : request is ROOT only */
215                                 /* SET : Omit payload from generated iwevent */
216 +#define IW_DESCR_FLAG_NOMAX    0x0008  /* GET : no limit on request size */
217  /* Driver level flags */
218  #define IW_DESCR_FLAG_WAIT     0x0100  /* Wait for driver event */
219  
220 @@ -311,23 +319,25 @@ struct iw_handler_def
221         /* Array of handlers for standard ioctls
222          * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
223          */
224 -       iw_handler *            standard;
225 +       const iw_handler *      standard;
226  
227         /* Array of handlers for private ioctls
228          * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
229          */
230 -       iw_handler *            private;
231 +       const iw_handler *      private;
232  
233         /* Arguments of private handler. This one is just a list, so you
234          * can put it in any order you want and should not leave holes...
235          * We will automatically export that to user space... */
236 -       struct iw_priv_args *   private_args;
237 +       const struct iw_priv_args *     private_args;
238  
239 -       /* Driver enhanced spy support */
240 -       long                    spy_offset;     /* Spy data offset */
241 +       /* This field will be *removed* in the next version of WE */
242 +       long                    spy_offset;     /* DO NOT USE */
243  
244 -       /* In the long term, get_wireless_stats will move from
245 -        * 'struct net_device' to here, to minimise bloat. */
246 +       /* New location of get_wireless_stats, to de-bloat struct net_device.
247 +        * The old pointer in struct net_device will be gradually phased
248 +        * out, and drivers are encouraged to use this one... */
249 +       struct iw_statistics*   (*get_wireless_stats)(struct net_device *dev);
250  };
251  
252  /* ---------------------- IOCTL DESCRIPTION ---------------------- */
253 @@ -374,18 +384,29 @@ struct iw_ioctl_description
254   */
255  struct iw_spy_data
256  {
257 -#ifdef IW_WIRELESS_SPY
258         /* --- Standard spy support --- */
259         int                     spy_number;
260         u_char                  spy_address[IW_MAX_SPY][ETH_ALEN];
261         struct iw_quality       spy_stat[IW_MAX_SPY];
262 -#ifdef IW_WIRELESS_THRSPY
263         /* --- Enhanced spy support (event) */
264         struct iw_quality       spy_thr_low;    /* Low threshold */
265         struct iw_quality       spy_thr_high;   /* High threshold */
266         u_char                  spy_thr_under[IW_MAX_SPY];
267 -#endif /* IW_WIRELESS_THRSPY */
268 -#endif /* IW_WIRELESS_SPY */
269 +};
270 +
271 +/* --------------------- DEVICE WIRELESS DATA --------------------- */
272 +/*
273 + * This is all the wireless data specific to a device instance that
274 + * is managed by the core of Wireless Extensions.
275 + * We only keep pointer to those structures, so that a driver is free
276 + * to share them between instances.
277 + * This structure should be initialised before registering the device.
278 + * Access to this data follow the same rules as any other struct net_device
279 + * data (i.e. valid as long as struct net_device exist, same locking rules).
280 + */
281 +struct iw_public_data {
282 +       /* Driver enhanced spy support */
283 +       struct iw_spy_data *    spy_data;
284  };
285  
286  /**************************** PROTOTYPES ****************************/
287 diff -u -p linux/net/core/dev.we16.c linux/net/core/dev.c
288 --- linux/net/core/dev.we16.c   2005-02-03 14:55:56.000000000 -0800
289 +++ linux/net/core/dev.c        2005-02-03 15:28:48.000000000 -0800
290 @@ -2426,7 +2426,7 @@ int dev_ioctl(unsigned int cmd, void *ar
291                                 /* Follow me in net/core/wireless.c */
292                                 ret = wireless_process_ioctl(&ifr, cmd);
293                                 rtnl_unlock();
294 -                               if (!ret && IW_IS_GET(cmd) &&
295 +                               if (IW_IS_GET(cmd) &&
296                                     copy_to_user(arg, &ifr, sizeof(struct ifreq)))
297                                         return -EFAULT;
298                                 return ret;
299 diff -u -p linux/net/core/wireless.we16.c linux/net/core/wireless.c
300 --- linux/net/core/wireless.we16.c      2005-02-03 14:56:09.000000000 -0800
301 +++ linux/net/core/wireless.c   2005-02-03 16:33:22.000000000 -0800
302 @@ -2,7 +2,7 @@
303   * This file implement the Wireless Extensions APIs.
304   *
305   * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
306 - * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
307 + * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
308   *
309   * (As all part of the Linux kernel, this file is GPL)
310   */
311 @@ -48,6 +48,16 @@
312   *     o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
313   *     o Add enhanced spy support : iw_handler_set_thrspy() and event.
314   *     o Add WIRELESS_EXT version display in /proc/net/wireless
315 + *
316 + * v6 - 18.06.04 - Jean II
317 + *     o Change get_spydata() method for added safety
318 + *     o Remove spy #ifdef, they are always on -> cleaner code
319 + *     o Allow any size GET request if user specifies length > max
320 + *             and if request has IW_DESCR_FLAG_NOMAX flag or is SIOCGIWPRIV
321 + *     o Start migrating get_wireless_stats to struct iw_handler_def
322 + *     o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus
323 + * Based on patch from Pavel Roskin <proski@gnu.org> :
324 + *     o Fix kernel data leak to user space in private handler handling
325   */
326  
327  /***************************** INCLUDES *****************************/
328 @@ -64,11 +74,7 @@
329  
330  /**************************** CONSTANTS ****************************/
331  
332 -/* Enough lenience, let's make sure things are proper... */
333 -#define WE_STRICT_WRITE                /* Check write buffer size */
334 -/* I'll probably drop both the define and kernel message in the next version */
335 -
336 -/* Debuging stuff */
337 +/* Debugging stuff */
338  #undef WE_IOCTL_DEBUG          /* Debug IOCTL API */
339  #undef WE_EVENT_DEBUG          /* Debug Event dispatcher */
340  #undef WE_SPY_DEBUG            /* Debug enhanced spy support */
341 @@ -134,11 +140,11 @@ static const struct iw_ioctl_description
342         /* -- hole -- */
343         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
344         /* SIOCGIWAPLIST */
345 -       { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
346 +       { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, IW_DESCR_FLAG_NOMAX},
347         /* SIOCSIWSCAN */
348         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
349         /* SIOCGIWSCAN */
350 -       { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0},
351 +       { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, IW_DESCR_FLAG_NOMAX},
352         /* SIOCSIWESSID */
353         { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT},
354         /* SIOCGIWESSID */
355 @@ -203,7 +209,7 @@ static const int standard_event_num = (s
356                                        sizeof(struct iw_ioctl_description));
357  
358  /* Size (in bytes) of the various private data types */
359 -static const char priv_type_size[] = {
360 +static const char iw_priv_type_size[] = {
361         0,                              /* IW_PRIV_TYPE_NONE */
362         1,                              /* IW_PRIV_TYPE_BYTE */
363         1,                              /* IW_PRIV_TYPE_CHAR */
364 @@ -270,12 +276,15 @@ static inline iw_handler get_handler(str
365   */
366  static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
367  {
368 +       /* New location */
369 +       if((dev->wireless_handlers != NULL) &&
370 +          (dev->wireless_handlers->get_wireless_stats != NULL))
371 +               return dev->wireless_handlers->get_wireless_stats(dev);
372 +
373 +       /* Old location, will be phased out in next WE */
374         return (dev->get_wireless_stats ?
375                 dev->get_wireless_stats(dev) :
376                 (struct iw_statistics *) NULL);
377 -       /* In the future, get_wireless_stats may move from 'struct net_device'
378 -        * to 'struct iw_handler_def', to de-bloat struct net_device.
379 -        * Definitely worse a thought... */
380  }
381  
382  /* ---------------------------------------------------------------- */
383 @@ -310,14 +319,32 @@ static inline int call_commit_handler(st
384  
385  /* ---------------------------------------------------------------- */
386  /*
387 - * Number of private arguments
388 + * Calculate size of private arguments
389   */
390  static inline int get_priv_size(__u16  args)
391  {
392         int     num = args & IW_PRIV_SIZE_MASK;
393         int     type = (args & IW_PRIV_TYPE_MASK) >> 12;
394  
395 -       return num * priv_type_size[type];
396 +       return num * iw_priv_type_size[type];
397 +}
398 +
399 +/* ---------------------------------------------------------------- */
400 +/*
401 + * Re-calculate the size of private arguments
402 + */
403 +static inline int adjust_priv_size(__u16               args,
404 +                                  union iwreq_data *   wrqu)
405 +{
406 +       int     num = wrqu->data.length;
407 +       int     max = args & IW_PRIV_SIZE_MASK;
408 +       int     type = (args & IW_PRIV_TYPE_MASK) >> 12;
409 +
410 +       /* Make sure the driver doesn't goof up */
411 +       if (max < num)
412 +               num = max;
413 +
414 +       return num * iw_priv_type_size[type];
415  }
416  
417  
418 @@ -350,11 +377,14 @@ static inline int sprintf_wireless_stats
419                                dev->name,
420                                stats->status,
421                                stats->qual.qual,
422 -                              stats->qual.updated & 1 ? '.' : ' ',
423 +                              stats->qual.updated & IW_QUAL_QUAL_UPDATED
424 +                              ? '.' : ' ',
425                                ((__u8) stats->qual.level),
426 -                              stats->qual.updated & 2 ? '.' : ' ',
427 +                              stats->qual.updated & IW_QUAL_LEVEL_UPDATED
428 +                              ? '.' : ' ',
429                                ((__u8) stats->qual.noise),
430 -                              stats->qual.updated & 4 ? '.' : ' ',
431 +                              stats->qual.updated & IW_QUAL_NOISE_UPDATED
432 +                              ? '.' : ' ',
433                                stats->discard.nwid,
434                                stats->discard.code,
435                                stats->discard.fragment,
436 @@ -470,13 +500,15 @@ static inline int ioctl_export_private(s
437         /* Check NULL pointer */
438         if(iwr->u.data.pointer == NULL)
439                 return -EFAULT;
440 -#ifdef WE_STRICT_WRITE
441 +
442         /* Check if there is enough buffer up there */
443         if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
444 -               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);
445 +               /* User space can't know in advance how large the buffer
446 +                * needs to be. Give it a hint, so that we can support
447 +                * any size buffer we want somewhat efficiently... */
448 +               iwr->u.data.length = dev->wireless_handlers->num_private_args;
449                 return -E2BIG;
450         }
451 -#endif /* WE_STRICT_WRITE */
452  
453         /* Set the number of available ioctls. */
454         iwr->u.data.length = dev->wireless_handlers->num_private_args;
455 @@ -505,7 +537,6 @@ static inline int ioctl_standard_call(st
456         const struct iw_ioctl_description *     descr;
457         struct iw_request_info                  info;
458         int                                     ret = -EINVAL;
459 -       int                                     user_size = 0;
460  
461         /* Get the description of the IOCTL */
462         if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
463 @@ -536,8 +567,14 @@ static inline int ioctl_standard_call(st
464  #endif /* WE_SET_EVENT */
465         } else {
466                 char *  extra;
467 +               int     extra_size;
468 +               int     user_length = 0;
469                 int     err;
470  
471 +               /* Calculate space needed by arguments. Always allocate
472 +                * for max space. Easier, and won't last long... */
473 +               extra_size = descr->max_tokens * descr->token_size;
474 +
475                 /* Check what user space is giving us */
476                 if(IW_IS_SET(cmd)) {
477                         /* Check NULL pointer */
478 @@ -554,18 +591,33 @@ static inline int ioctl_standard_call(st
479                         if(iwr->u.data.pointer == NULL)
480                                 return -EFAULT;
481                         /* Save user space buffer size for checking */
482 -                       user_size = iwr->u.data.length;
483 +                       user_length = iwr->u.data.length;
484 +
485 +                       /* Don't check if user_length > max to allow forward
486 +                        * compatibility. The test user_length < min is
487 +                        * implied by the test at the end. */
488 +
489 +                       /* Support for very large requests */
490 +                       if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
491 +                          (user_length > descr->max_tokens)) {
492 +                               /* Allow userspace to GET more than max so
493 +                                * we can support any size GET requests.
494 +                                * There is still a limit : -ENOMEM. */
495 +                               extra_size = user_length * descr->token_size;
496 +                               /* Note : user_length is originally a __u16,
497 +                                * and token_size is controlled by us,
498 +                                * so extra_size won't get negative and
499 +                                * won't overflow... */
500 +                       }
501                 }
502  
503  #ifdef WE_IOCTL_DEBUG
504                 printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
505 -                      dev->name, descr->max_tokens * descr->token_size);
506 +                      dev->name, extra_size);
507  #endif /* WE_IOCTL_DEBUG */
508  
509 -               /* Always allocate for max space. Easier, and won't last
510 -                * long... */
511 -               extra = kmalloc(descr->max_tokens * descr->token_size,
512 -                               GFP_KERNEL);
513 +               /* Create the kernel buffer */
514 +               extra = kmalloc(extra_size, GFP_KERNEL);
515                 if (extra == NULL) {
516                         return -ENOMEM;
517                 }
518 @@ -591,14 +643,11 @@ static inline int ioctl_standard_call(st
519  
520                 /* If we have something to return to the user */
521                 if (!ret && IW_IS_GET(cmd)) {
522 -#ifdef WE_STRICT_WRITE
523                         /* Check if there is enough buffer up there */
524 -                       if(user_size < iwr->u.data.length) {
525 -                               printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length);
526 +                       if(user_length < iwr->u.data.length) {
527                                 kfree(extra);
528                                 return -E2BIG;
529                         }
530 -#endif /* WE_STRICT_WRITE */
531  
532                         err = copy_to_user(iwr->u.data.pointer, extra,
533                                            iwr->u.data.length *
534 @@ -661,7 +710,7 @@ static inline int ioctl_private_call(str
535                                      iw_handler         handler)
536  {
537         struct iwreq *                  iwr = (struct iwreq *) ifr;
538 -       struct iw_priv_args *           descr = NULL;
539 +       const struct iw_priv_args *     descr = NULL;
540         struct iw_request_info          info;
541         int                             extra_size = 0;
542         int                             i;
543 @@ -701,7 +750,7 @@ static inline int ioctl_private_call(str
544                            ((extra_size + offset) <= IFNAMSIZ))
545                                 extra_size = 0;
546                 } else {
547 -                       /* Size of set arguments */
548 +                       /* Size of get arguments */
549                         extra_size = get_priv_size(descr->get_args);
550  
551                         /* Does it fits in iwr ? */
552 @@ -771,6 +820,14 @@ static inline int ioctl_private_call(str
553  
554                 /* If we have something to return to the user */
555                 if (!ret && IW_IS_GET(cmd)) {
556 +
557 +                       /* Adjust for the actual length if it's variable,
558 +                        * avoid leaking kernel bits outside. */
559 +                       if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) {
560 +                               extra_size = adjust_priv_size(descr->get_args,
561 +                                                             &(iwr->u));
562 +                       }
563 +
564                         err = copy_to_user(iwr->u.data.pointer, extra,
565                                            extra_size);
566                         if (err)
567 @@ -1042,9 +1099,25 @@ void wireless_send_event(struct net_devi
568   * One of the main advantage of centralising spy support here is that
569   * it becomes much easier to improve and extend it without having to touch
570   * the drivers. One example is the addition of the Spy-Threshold events.
571 - * Note : IW_WIRELESS_SPY is defined in iw_handler.h
572   */
573  
574 +/* ---------------------------------------------------------------- */
575 +/*
576 + * Return the pointer to the spy data in the driver.
577 + * Because this is called on the Rx path via wireless_spy_update(),
578 + * we want it to be efficient...
579 + */
580 +static inline struct iw_spy_data * get_spydata(struct net_device *dev)
581 +{
582 +       /* This is the new way */
583 +       if(dev->wireless_data)
584 +               return(dev->wireless_data->spy_data);
585 +
586 +       /* This is the old way. Doesn't work for multi-headed drivers.
587 +        * It will be removed in the next version of WE. */
588 +       return (dev->priv + dev->wireless_handlers->spy_offset);
589 +}
590 +
591  /*------------------------------------------------------------------*/
592  /*
593   * Standard Wireless Handler : set Spy List
594 @@ -1054,16 +1127,26 @@ int iw_handler_set_spy(struct net_device
595                        union iwreq_data *       wrqu,
596                        char *                   extra)
597  {
598 -#ifdef IW_WIRELESS_SPY
599 -       struct iw_spy_data *    spydata = (dev->priv +
600 -                                          dev->wireless_handlers->spy_offset);
601 +       struct iw_spy_data *    spydata = get_spydata(dev);
602         struct sockaddr *       address = (struct sockaddr *) extra;
603  
604 +       /* Make sure driver is not buggy or using the old API */
605 +       if(!spydata)
606 +               return -EOPNOTSUPP;
607 +
608         /* Disable spy collection while we copy the addresses.
609 -        * As we don't disable interrupts, we need to do this to avoid races.
610 -        * As we are the only writer, this is good enough. */
611 +        * While we copy addresses, any call to wireless_spy_update()
612 +        * will NOP. This is OK, as anyway the addresses are changing. */
613         spydata->spy_number = 0;
614  
615 +       /* We want to operate without locking, because wireless_spy_update()
616 +        * most likely will happen in the interrupt handler, and therefore
617 +        * have its own locking constraints and needs performance.
618 +        * The rtnl_lock() make sure we don't race with the other iw_handlers.
619 +        * This make sure wireless_spy_update() "see" that the spy list
620 +        * is temporarily disabled. */
621 +       wmb();
622 +
623         /* Are there are addresses to copy? */
624         if(wrqu->data.length > 0) {
625                 int i;
626 @@ -1089,13 +1172,14 @@ int iw_handler_set_spy(struct net_device
627                                spydata->spy_address[i][5]);
628  #endif /* WE_SPY_DEBUG */
629         }
630 +
631 +       /* Make sure above is updated before re-enabling */
632 +       wmb();
633 +
634         /* Enable addresses */
635         spydata->spy_number = wrqu->data.length;
636  
637         return 0;
638 -#else /* IW_WIRELESS_SPY */
639 -       return -EOPNOTSUPP;
640 -#endif /* IW_WIRELESS_SPY */
641  }
642  
643  /*------------------------------------------------------------------*/
644 @@ -1107,12 +1191,14 @@ int iw_handler_get_spy(struct net_device
645                        union iwreq_data *       wrqu,
646                        char *                   extra)
647  {
648 -#ifdef IW_WIRELESS_SPY
649 -       struct iw_spy_data *    spydata = (dev->priv +
650 -                                          dev->wireless_handlers->spy_offset);
651 +       struct iw_spy_data *    spydata = get_spydata(dev);
652         struct sockaddr *       address = (struct sockaddr *) extra;
653         int                     i;
654  
655 +       /* Make sure driver is not buggy or using the old API */
656 +       if(!spydata)
657 +               return -EOPNOTSUPP;
658 +
659         wrqu->data.length = spydata->spy_number;
660  
661         /* Copy addresses. */
662 @@ -1129,9 +1215,6 @@ int iw_handler_get_spy(struct net_device
663         for(i = 0; i < spydata->spy_number; i++)
664                 spydata->spy_stat[i].updated = 0;
665         return 0;
666 -#else /* IW_WIRELESS_SPY */
667 -       return -EOPNOTSUPP;
668 -#endif /* IW_WIRELESS_SPY */
669  }
670  
671  /*------------------------------------------------------------------*/
672 @@ -1143,11 +1226,13 @@ int iw_handler_set_thrspy(struct net_dev
673                           union iwreq_data *    wrqu,
674                           char *                extra)
675  {
676 -#ifdef IW_WIRELESS_THRSPY
677 -       struct iw_spy_data *    spydata = (dev->priv +
678 -                                          dev->wireless_handlers->spy_offset);
679 +       struct iw_spy_data *    spydata = get_spydata(dev);
680         struct iw_thrspy *      threshold = (struct iw_thrspy *) extra;
681  
682 +       /* Make sure driver is not buggy or using the old API */
683 +       if(!spydata)
684 +               return -EOPNOTSUPP;
685 +
686         /* Just do it */
687         memcpy(&(spydata->spy_thr_low), &(threshold->low),
688                2 * sizeof(struct iw_quality));
689 @@ -1160,9 +1245,6 @@ int iw_handler_set_thrspy(struct net_dev
690  #endif /* WE_SPY_DEBUG */
691  
692         return 0;
693 -#else /* IW_WIRELESS_THRSPY */
694 -       return -EOPNOTSUPP;
695 -#endif /* IW_WIRELESS_THRSPY */
696  }
697  
698  /*------------------------------------------------------------------*/
699 @@ -1174,22 +1256,20 @@ int iw_handler_get_thrspy(struct net_dev
700                           union iwreq_data *    wrqu,
701                           char *                extra)
702  {
703 -#ifdef IW_WIRELESS_THRSPY
704 -       struct iw_spy_data *    spydata = (dev->priv +
705 -                                          dev->wireless_handlers->spy_offset);
706 +       struct iw_spy_data *    spydata = get_spydata(dev);
707         struct iw_thrspy *      threshold = (struct iw_thrspy *) extra;
708  
709 +       /* Make sure driver is not buggy or using the old API */
710 +       if(!spydata)
711 +               return -EOPNOTSUPP;
712 +
713         /* Just do it */
714         memcpy(&(threshold->low), &(spydata->spy_thr_low),
715                2 * sizeof(struct iw_quality));
716  
717         return 0;
718 -#else /* IW_WIRELESS_THRSPY */
719 -       return -EOPNOTSUPP;
720 -#endif /* IW_WIRELESS_THRSPY */
721  }
722  
723 -#ifdef IW_WIRELESS_THRSPY
724  /*------------------------------------------------------------------*/
725  /*
726   * Prepare and send a Spy Threshold event
727 @@ -1227,7 +1307,6 @@ static void iw_send_thrspy_event(struct 
728         /* Send event to user space */
729         wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
730  }
731 -#endif /* IW_WIRELESS_THRSPY */
732  
733  /* ---------------------------------------------------------------- */
734  /*
735 @@ -1240,12 +1319,14 @@ void wireless_spy_update(struct net_devi
736                          unsigned char *        address,
737                          struct iw_quality *    wstats)
738  {
739 -#ifdef IW_WIRELESS_SPY
740 -       struct iw_spy_data *    spydata = (dev->priv +
741 -                                          dev->wireless_handlers->spy_offset);
742 +       struct iw_spy_data *    spydata = get_spydata(dev);
743         int                     i;
744         int                     match = -1;
745  
746 +       /* Make sure driver is not buggy or using the old API */
747 +       if(!spydata)
748 +               return;
749 +
750  #ifdef WE_SPY_DEBUG
751         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]);
752  #endif /* WE_SPY_DEBUG */
753 @@ -1257,7 +1338,7 @@ void wireless_spy_update(struct net_devi
754                                sizeof(struct iw_quality));
755                         match = i;
756                 }
757 -#ifdef IW_WIRELESS_THRSPY
758 +
759         /* Generate an event if we cross the spy threshold.
760          * To avoid event storms, we have a simple hysteresis : we generate
761          * event only when we go under the low threshold or above the
762 @@ -1277,6 +1358,4 @@ void wireless_spy_update(struct net_devi
763                         }
764                 }
765         }
766 -#endif /* IW_WIRELESS_THRSPY */
767 -#endif /* IW_WIRELESS_SPY */
768  }