Merge git://git.infradead.org/~dwmw2/cafe-2.6
[powerpc.git] / net / core / wireless.c
1 /*
2  * This file implement the Wireless Extensions APIs.
3  *
4  * Authors :    Jean Tourrilhes - HPL - <jt@hpl.hp.com>
5  * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
6  *
7  * (As all part of the Linux kernel, this file is GPL)
8  */
9
10 /************************** DOCUMENTATION **************************/
11 /*
12  * API definition :
13  * --------------
14  * See <linux/wireless.h> for details of the APIs and the rest.
15  *
16  * History :
17  * -------
18  *
19  * v1 - 5.12.01 - Jean II
20  *      o Created this file.
21  *
22  * v2 - 13.12.01 - Jean II
23  *      o Move /proc/net/wireless stuff from net/core/dev.c to here
24  *      o Make Wireless Extension IOCTLs go through here
25  *      o Added iw_handler handling ;-)
26  *      o Added standard ioctl description
27  *      o Initial dumb commit strategy based on orinoco.c
28  *
29  * v3 - 19.12.01 - Jean II
30  *      o Make sure we don't go out of standard_ioctl[] in ioctl_standard_call
31  *      o Add event dispatcher function
32  *      o Add event description
33  *      o Propagate events as rtnetlink IFLA_WIRELESS option
34  *      o Generate event on selected SET requests
35  *
36  * v4 - 18.04.02 - Jean II
37  *      o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1
38  *
39  * v5 - 21.06.02 - Jean II
40  *      o Add IW_PRIV_TYPE_ADDR in priv_type_size (+cleanup)
41  *      o Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
42  *      o Add IWEVCUSTOM for driver specific event/scanning token
43  *      o Turn on WE_STRICT_WRITE by default + kernel warning
44  *      o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
45  *      o Fix off-by-one in test (extra_size <= IFNAMSIZ)
46  *
47  * v6 - 9.01.03 - Jean II
48  *      o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
49  *      o Add enhanced spy support : iw_handler_set_thrspy() and event.
50  *      o Add WIRELESS_EXT version display in /proc/net/wireless
51  *
52  * v6 - 18.06.04 - Jean II
53  *      o Change get_spydata() method for added safety
54  *      o Remove spy #ifdef, they are always on -> cleaner code
55  *      o Allow any size GET request if user specifies length > max
56  *              and if request has IW_DESCR_FLAG_NOMAX flag or is SIOCGIWPRIV
57  *      o Start migrating get_wireless_stats to struct iw_handler_def
58  *      o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus
59  * Based on patch from Pavel Roskin <proski@gnu.org> :
60  *      o Fix kernel data leak to user space in private handler handling
61  *
62  * v7 - 18.3.05 - Jean II
63  *      o Remove (struct iw_point *)->pointer from events and streams
64  *      o Remove spy_offset from struct iw_handler_def
65  *      o Start deprecating dev->get_wireless_stats, output a warning
66  *      o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless
67  *      o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats)
68  *
69  * v8 - 17.02.06 - Jean II
70  *      o RtNetlink requests support (SET/GET)
71  *
72  * v8b - 03.08.06 - Herbert Xu
73  *      o Fix Wireless Event locking issues.
74  *
75  * v9 - 14.3.06 - Jean II
76  *      o Change length in ESSID and NICK to strlen() instead of strlen()+1
77  *      o Make standard_ioctl_num and standard_event_num unsigned
78  *      o Remove (struct net_device *)->get_wireless_stats()
79  */
80
81 /***************************** INCLUDES *****************************/
82
83 #include <linux/module.h>
84 #include <linux/types.h>                /* off_t */
85 #include <linux/netdevice.h>            /* struct ifreq, dev_get_by_name() */
86 #include <linux/proc_fs.h>
87 #include <linux/rtnetlink.h>            /* rtnetlink stuff */
88 #include <linux/seq_file.h>
89 #include <linux/init.h>                 /* for __init */
90 #include <linux/if_arp.h>               /* ARPHRD_ETHER */
91 #include <linux/etherdevice.h>          /* compare_ether_addr */
92 #include <linux/interrupt.h>
93
94 #include <linux/wireless.h>             /* Pretty obvious */
95 #include <net/iw_handler.h>             /* New driver API */
96 #include <net/netlink.h>
97
98 #include <asm/uaccess.h>                /* copy_to_user() */
99
100 /**************************** CONSTANTS ****************************/
101
102 /* Debugging stuff */
103 #undef WE_IOCTL_DEBUG           /* Debug IOCTL API */
104 #undef WE_RTNETLINK_DEBUG       /* Debug RtNetlink API */
105 #undef WE_EVENT_DEBUG           /* Debug Event dispatcher */
106 #undef WE_SPY_DEBUG             /* Debug enhanced spy support */
107
108 /* Options */
109 //CONFIG_NET_WIRELESS_RTNETLINK /* Wireless requests over RtNetlink */
110 #define WE_EVENT_RTNETLINK      /* Propagate events using RtNetlink */
111 #define WE_SET_EVENT            /* Generate an event on some set commands */
112
113 /************************* GLOBAL VARIABLES *************************/
114 /*
115  * You should not use global variables, because of re-entrancy.
116  * On our case, it's only const, so it's OK...
117  */
118 /*
119  * Meta-data about all the standard Wireless Extension request we
120  * know about.
121  */
122 static const struct iw_ioctl_description standard_ioctl[] = {
123         [SIOCSIWCOMMIT  - SIOCIWFIRST] = {
124                 .header_type    = IW_HEADER_TYPE_NULL,
125         },
126         [SIOCGIWNAME    - SIOCIWFIRST] = {
127                 .header_type    = IW_HEADER_TYPE_CHAR,
128                 .flags          = IW_DESCR_FLAG_DUMP,
129         },
130         [SIOCSIWNWID    - SIOCIWFIRST] = {
131                 .header_type    = IW_HEADER_TYPE_PARAM,
132                 .flags          = IW_DESCR_FLAG_EVENT,
133         },
134         [SIOCGIWNWID    - SIOCIWFIRST] = {
135                 .header_type    = IW_HEADER_TYPE_PARAM,
136                 .flags          = IW_DESCR_FLAG_DUMP,
137         },
138         [SIOCSIWFREQ    - SIOCIWFIRST] = {
139                 .header_type    = IW_HEADER_TYPE_FREQ,
140                 .flags          = IW_DESCR_FLAG_EVENT,
141         },
142         [SIOCGIWFREQ    - SIOCIWFIRST] = {
143                 .header_type    = IW_HEADER_TYPE_FREQ,
144                 .flags          = IW_DESCR_FLAG_DUMP,
145         },
146         [SIOCSIWMODE    - SIOCIWFIRST] = {
147                 .header_type    = IW_HEADER_TYPE_UINT,
148                 .flags          = IW_DESCR_FLAG_EVENT,
149         },
150         [SIOCGIWMODE    - SIOCIWFIRST] = {
151                 .header_type    = IW_HEADER_TYPE_UINT,
152                 .flags          = IW_DESCR_FLAG_DUMP,
153         },
154         [SIOCSIWSENS    - SIOCIWFIRST] = {
155                 .header_type    = IW_HEADER_TYPE_PARAM,
156         },
157         [SIOCGIWSENS    - SIOCIWFIRST] = {
158                 .header_type    = IW_HEADER_TYPE_PARAM,
159         },
160         [SIOCSIWRANGE   - SIOCIWFIRST] = {
161                 .header_type    = IW_HEADER_TYPE_NULL,
162         },
163         [SIOCGIWRANGE   - SIOCIWFIRST] = {
164                 .header_type    = IW_HEADER_TYPE_POINT,
165                 .token_size     = 1,
166                 .max_tokens     = sizeof(struct iw_range),
167                 .flags          = IW_DESCR_FLAG_DUMP,
168         },
169         [SIOCSIWPRIV    - SIOCIWFIRST] = {
170                 .header_type    = IW_HEADER_TYPE_NULL,
171         },
172         [SIOCGIWPRIV    - SIOCIWFIRST] = { /* (handled directly by us) */
173                 .header_type    = IW_HEADER_TYPE_POINT,
174                 .token_size     = sizeof(struct iw_priv_args),
175                 .max_tokens     = 16,
176                 .flags          = IW_DESCR_FLAG_NOMAX,
177         },
178         [SIOCSIWSTATS   - SIOCIWFIRST] = {
179                 .header_type    = IW_HEADER_TYPE_NULL,
180         },
181         [SIOCGIWSTATS   - SIOCIWFIRST] = { /* (handled directly by us) */
182                 .header_type    = IW_HEADER_TYPE_POINT,
183                 .token_size     = 1,
184                 .max_tokens     = sizeof(struct iw_statistics),
185                 .flags          = IW_DESCR_FLAG_DUMP,
186         },
187         [SIOCSIWSPY     - SIOCIWFIRST] = {
188                 .header_type    = IW_HEADER_TYPE_POINT,
189                 .token_size     = sizeof(struct sockaddr),
190                 .max_tokens     = IW_MAX_SPY,
191         },
192         [SIOCGIWSPY     - SIOCIWFIRST] = {
193                 .header_type    = IW_HEADER_TYPE_POINT,
194                 .token_size     = sizeof(struct sockaddr) +
195                                   sizeof(struct iw_quality),
196                 .max_tokens     = IW_MAX_SPY,
197         },
198         [SIOCSIWTHRSPY  - SIOCIWFIRST] = {
199                 .header_type    = IW_HEADER_TYPE_POINT,
200                 .token_size     = sizeof(struct iw_thrspy),
201                 .min_tokens     = 1,
202                 .max_tokens     = 1,
203         },
204         [SIOCGIWTHRSPY  - SIOCIWFIRST] = {
205                 .header_type    = IW_HEADER_TYPE_POINT,
206                 .token_size     = sizeof(struct iw_thrspy),
207                 .min_tokens     = 1,
208                 .max_tokens     = 1,
209         },
210         [SIOCSIWAP      - SIOCIWFIRST] = {
211                 .header_type    = IW_HEADER_TYPE_ADDR,
212         },
213         [SIOCGIWAP      - SIOCIWFIRST] = {
214                 .header_type    = IW_HEADER_TYPE_ADDR,
215                 .flags          = IW_DESCR_FLAG_DUMP,
216         },
217         [SIOCSIWMLME    - SIOCIWFIRST] = {
218                 .header_type    = IW_HEADER_TYPE_POINT,
219                 .token_size     = 1,
220                 .min_tokens     = sizeof(struct iw_mlme),
221                 .max_tokens     = sizeof(struct iw_mlme),
222         },
223         [SIOCGIWAPLIST  - SIOCIWFIRST] = {
224                 .header_type    = IW_HEADER_TYPE_POINT,
225                 .token_size     = sizeof(struct sockaddr) +
226                                   sizeof(struct iw_quality),
227                 .max_tokens     = IW_MAX_AP,
228                 .flags          = IW_DESCR_FLAG_NOMAX,
229         },
230         [SIOCSIWSCAN    - SIOCIWFIRST] = {
231                 .header_type    = IW_HEADER_TYPE_POINT,
232                 .token_size     = 1,
233                 .min_tokens     = 0,
234                 .max_tokens     = sizeof(struct iw_scan_req),
235         },
236         [SIOCGIWSCAN    - SIOCIWFIRST] = {
237                 .header_type    = IW_HEADER_TYPE_POINT,
238                 .token_size     = 1,
239                 .max_tokens     = IW_SCAN_MAX_DATA,
240                 .flags          = IW_DESCR_FLAG_NOMAX,
241         },
242         [SIOCSIWESSID   - SIOCIWFIRST] = {
243                 .header_type    = IW_HEADER_TYPE_POINT,
244                 .token_size     = 1,
245                 .max_tokens     = IW_ESSID_MAX_SIZE,
246                 .flags          = IW_DESCR_FLAG_EVENT,
247         },
248         [SIOCGIWESSID   - SIOCIWFIRST] = {
249                 .header_type    = IW_HEADER_TYPE_POINT,
250                 .token_size     = 1,
251                 .max_tokens     = IW_ESSID_MAX_SIZE,
252                 .flags          = IW_DESCR_FLAG_DUMP,
253         },
254         [SIOCSIWNICKN   - SIOCIWFIRST] = {
255                 .header_type    = IW_HEADER_TYPE_POINT,
256                 .token_size     = 1,
257                 .max_tokens     = IW_ESSID_MAX_SIZE,
258         },
259         [SIOCGIWNICKN   - SIOCIWFIRST] = {
260                 .header_type    = IW_HEADER_TYPE_POINT,
261                 .token_size     = 1,
262                 .max_tokens     = IW_ESSID_MAX_SIZE,
263         },
264         [SIOCSIWRATE    - SIOCIWFIRST] = {
265                 .header_type    = IW_HEADER_TYPE_PARAM,
266         },
267         [SIOCGIWRATE    - SIOCIWFIRST] = {
268                 .header_type    = IW_HEADER_TYPE_PARAM,
269         },
270         [SIOCSIWRTS     - SIOCIWFIRST] = {
271                 .header_type    = IW_HEADER_TYPE_PARAM,
272         },
273         [SIOCGIWRTS     - SIOCIWFIRST] = {
274                 .header_type    = IW_HEADER_TYPE_PARAM,
275         },
276         [SIOCSIWFRAG    - SIOCIWFIRST] = {
277                 .header_type    = IW_HEADER_TYPE_PARAM,
278         },
279         [SIOCGIWFRAG    - SIOCIWFIRST] = {
280                 .header_type    = IW_HEADER_TYPE_PARAM,
281         },
282         [SIOCSIWTXPOW   - SIOCIWFIRST] = {
283                 .header_type    = IW_HEADER_TYPE_PARAM,
284         },
285         [SIOCGIWTXPOW   - SIOCIWFIRST] = {
286                 .header_type    = IW_HEADER_TYPE_PARAM,
287         },
288         [SIOCSIWRETRY   - SIOCIWFIRST] = {
289                 .header_type    = IW_HEADER_TYPE_PARAM,
290         },
291         [SIOCGIWRETRY   - SIOCIWFIRST] = {
292                 .header_type    = IW_HEADER_TYPE_PARAM,
293         },
294         [SIOCSIWENCODE  - SIOCIWFIRST] = {
295                 .header_type    = IW_HEADER_TYPE_POINT,
296                 .token_size     = 1,
297                 .max_tokens     = IW_ENCODING_TOKEN_MAX,
298                 .flags          = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
299         },
300         [SIOCGIWENCODE  - SIOCIWFIRST] = {
301                 .header_type    = IW_HEADER_TYPE_POINT,
302                 .token_size     = 1,
303                 .max_tokens     = IW_ENCODING_TOKEN_MAX,
304                 .flags          = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
305         },
306         [SIOCSIWPOWER   - SIOCIWFIRST] = {
307                 .header_type    = IW_HEADER_TYPE_PARAM,
308         },
309         [SIOCGIWPOWER   - SIOCIWFIRST] = {
310                 .header_type    = IW_HEADER_TYPE_PARAM,
311         },
312         [SIOCSIWGENIE   - SIOCIWFIRST] = {
313                 .header_type    = IW_HEADER_TYPE_POINT,
314                 .token_size     = 1,
315                 .max_tokens     = IW_GENERIC_IE_MAX,
316         },
317         [SIOCGIWGENIE   - SIOCIWFIRST] = {
318                 .header_type    = IW_HEADER_TYPE_POINT,
319                 .token_size     = 1,
320                 .max_tokens     = IW_GENERIC_IE_MAX,
321         },
322         [SIOCSIWAUTH    - SIOCIWFIRST] = {
323                 .header_type    = IW_HEADER_TYPE_PARAM,
324         },
325         [SIOCGIWAUTH    - SIOCIWFIRST] = {
326                 .header_type    = IW_HEADER_TYPE_PARAM,
327         },
328         [SIOCSIWENCODEEXT - SIOCIWFIRST] = {
329                 .header_type    = IW_HEADER_TYPE_POINT,
330                 .token_size     = 1,
331                 .min_tokens     = sizeof(struct iw_encode_ext),
332                 .max_tokens     = sizeof(struct iw_encode_ext) +
333                                   IW_ENCODING_TOKEN_MAX,
334         },
335         [SIOCGIWENCODEEXT - SIOCIWFIRST] = {
336                 .header_type    = IW_HEADER_TYPE_POINT,
337                 .token_size     = 1,
338                 .min_tokens     = sizeof(struct iw_encode_ext),
339                 .max_tokens     = sizeof(struct iw_encode_ext) +
340                                   IW_ENCODING_TOKEN_MAX,
341         },
342         [SIOCSIWPMKSA - SIOCIWFIRST] = {
343                 .header_type    = IW_HEADER_TYPE_POINT,
344                 .token_size     = 1,
345                 .min_tokens     = sizeof(struct iw_pmksa),
346                 .max_tokens     = sizeof(struct iw_pmksa),
347         },
348 };
349 static const unsigned standard_ioctl_num = (sizeof(standard_ioctl) /
350                                             sizeof(struct iw_ioctl_description));
351
352 /*
353  * Meta-data about all the additional standard Wireless Extension events
354  * we know about.
355  */
356 static const struct iw_ioctl_description standard_event[] = {
357         [IWEVTXDROP     - IWEVFIRST] = {
358                 .header_type    = IW_HEADER_TYPE_ADDR,
359         },
360         [IWEVQUAL       - IWEVFIRST] = {
361                 .header_type    = IW_HEADER_TYPE_QUAL,
362         },
363         [IWEVCUSTOM     - IWEVFIRST] = {
364                 .header_type    = IW_HEADER_TYPE_POINT,
365                 .token_size     = 1,
366                 .max_tokens     = IW_CUSTOM_MAX,
367         },
368         [IWEVREGISTERED - IWEVFIRST] = {
369                 .header_type    = IW_HEADER_TYPE_ADDR,
370         },
371         [IWEVEXPIRED    - IWEVFIRST] = {
372                 .header_type    = IW_HEADER_TYPE_ADDR, 
373         },
374         [IWEVGENIE      - IWEVFIRST] = {
375                 .header_type    = IW_HEADER_TYPE_POINT,
376                 .token_size     = 1,
377                 .max_tokens     = IW_GENERIC_IE_MAX,
378         },
379         [IWEVMICHAELMICFAILURE  - IWEVFIRST] = {
380                 .header_type    = IW_HEADER_TYPE_POINT, 
381                 .token_size     = 1,
382                 .max_tokens     = sizeof(struct iw_michaelmicfailure),
383         },
384         [IWEVASSOCREQIE - IWEVFIRST] = {
385                 .header_type    = IW_HEADER_TYPE_POINT,
386                 .token_size     = 1,
387                 .max_tokens     = IW_GENERIC_IE_MAX,
388         },
389         [IWEVASSOCRESPIE        - IWEVFIRST] = {
390                 .header_type    = IW_HEADER_TYPE_POINT,
391                 .token_size     = 1,
392                 .max_tokens     = IW_GENERIC_IE_MAX,
393         },
394         [IWEVPMKIDCAND  - IWEVFIRST] = {
395                 .header_type    = IW_HEADER_TYPE_POINT,
396                 .token_size     = 1,
397                 .max_tokens     = sizeof(struct iw_pmkid_cand),
398         },
399 };
400 static const unsigned standard_event_num = (sizeof(standard_event) /
401                                             sizeof(struct iw_ioctl_description));
402
403 /* Size (in bytes) of the various private data types */
404 static const char iw_priv_type_size[] = {
405         0,                              /* IW_PRIV_TYPE_NONE */
406         1,                              /* IW_PRIV_TYPE_BYTE */
407         1,                              /* IW_PRIV_TYPE_CHAR */
408         0,                              /* Not defined */
409         sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
410         sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
411         sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
412         0,                              /* Not defined */
413 };
414
415 /* Size (in bytes) of various events */
416 static const int event_type_size[] = {
417         IW_EV_LCP_LEN,                  /* IW_HEADER_TYPE_NULL */
418         0,
419         IW_EV_CHAR_LEN,                 /* IW_HEADER_TYPE_CHAR */
420         0,
421         IW_EV_UINT_LEN,                 /* IW_HEADER_TYPE_UINT */
422         IW_EV_FREQ_LEN,                 /* IW_HEADER_TYPE_FREQ */
423         IW_EV_ADDR_LEN,                 /* IW_HEADER_TYPE_ADDR */
424         0,
425         IW_EV_POINT_LEN,                /* Without variable payload */
426         IW_EV_PARAM_LEN,                /* IW_HEADER_TYPE_PARAM */
427         IW_EV_QUAL_LEN,                 /* IW_HEADER_TYPE_QUAL */
428 };
429
430 /************************ COMMON SUBROUTINES ************************/
431 /*
432  * Stuff that may be used in various place or doesn't fit in one
433  * of the section below.
434  */
435
436 /* ---------------------------------------------------------------- */
437 /*
438  * Return the driver handler associated with a specific Wireless Extension.
439  * Called from various place, so make sure it remains efficient.
440  */
441 static inline iw_handler get_handler(struct net_device *dev,
442                                      unsigned int cmd)
443 {
444         /* Don't "optimise" the following variable, it will crash */
445         unsigned int    index;          /* *MUST* be unsigned */
446
447         /* Check if we have some wireless handlers defined */
448         if(dev->wireless_handlers == NULL)
449                 return NULL;
450
451         /* Try as a standard command */
452         index = cmd - SIOCIWFIRST;
453         if(index < dev->wireless_handlers->num_standard)
454                 return dev->wireless_handlers->standard[index];
455
456         /* Try as a private command */
457         index = cmd - SIOCIWFIRSTPRIV;
458         if(index < dev->wireless_handlers->num_private)
459                 return dev->wireless_handlers->private[index];
460
461         /* Not found */
462         return NULL;
463 }
464
465 /* ---------------------------------------------------------------- */
466 /*
467  * Get statistics out of the driver
468  */
469 static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
470 {
471         /* New location */
472         if((dev->wireless_handlers != NULL) &&
473            (dev->wireless_handlers->get_wireless_stats != NULL))
474                 return dev->wireless_handlers->get_wireless_stats(dev);
475
476         /* Not found */
477         return (struct iw_statistics *) NULL;
478 }
479
480 /* ---------------------------------------------------------------- */
481 /*
482  * Call the commit handler in the driver
483  * (if exist and if conditions are right)
484  *
485  * Note : our current commit strategy is currently pretty dumb,
486  * but we will be able to improve on that...
487  * The goal is to try to agreagate as many changes as possible
488  * before doing the commit. Drivers that will define a commit handler
489  * are usually those that need a reset after changing parameters, so
490  * we want to minimise the number of reset.
491  * A cool idea is to use a timer : at each "set" command, we re-set the
492  * timer, when the timer eventually fires, we call the driver.
493  * Hopefully, more on that later.
494  *
495  * Also, I'm waiting to see how many people will complain about the
496  * netif_running(dev) test. I'm open on that one...
497  * Hopefully, the driver will remember to do a commit in "open()" ;-)
498  */
499 static inline int call_commit_handler(struct net_device *       dev)
500 {
501         if((netif_running(dev)) &&
502            (dev->wireless_handlers->standard[0] != NULL)) {
503                 /* Call the commit handler on the driver */
504                 return dev->wireless_handlers->standard[0](dev, NULL,
505                                                            NULL, NULL);
506         } else
507                 return 0;               /* Command completed successfully */
508 }
509
510 /* ---------------------------------------------------------------- */
511 /*
512  * Calculate size of private arguments
513  */
514 static inline int get_priv_size(__u16   args)
515 {
516         int     num = args & IW_PRIV_SIZE_MASK;
517         int     type = (args & IW_PRIV_TYPE_MASK) >> 12;
518
519         return num * iw_priv_type_size[type];
520 }
521
522 /* ---------------------------------------------------------------- */
523 /*
524  * Re-calculate the size of private arguments
525  */
526 static inline int adjust_priv_size(__u16                args,
527                                    union iwreq_data *   wrqu)
528 {
529         int     num = wrqu->data.length;
530         int     max = args & IW_PRIV_SIZE_MASK;
531         int     type = (args & IW_PRIV_TYPE_MASK) >> 12;
532
533         /* Make sure the driver doesn't goof up */
534         if (max < num)
535                 num = max;
536
537         return num * iw_priv_type_size[type];
538 }
539
540 /* ---------------------------------------------------------------- */
541 /*
542  * Standard Wireless Handler : get wireless stats
543  *      Allow programatic access to /proc/net/wireless even if /proc
544  *      doesn't exist... Also more efficient...
545  */
546 static int iw_handler_get_iwstats(struct net_device *           dev,
547                                   struct iw_request_info *      info,
548                                   union iwreq_data *            wrqu,
549                                   char *                        extra)
550 {
551         /* Get stats from the driver */
552         struct iw_statistics *stats;
553
554         stats = get_wireless_stats(dev);
555         if (stats != (struct iw_statistics *) NULL) {
556
557                 /* Copy statistics to extra */
558                 memcpy(extra, stats, sizeof(struct iw_statistics));
559                 wrqu->data.length = sizeof(struct iw_statistics);
560
561                 /* Check if we need to clear the updated flag */
562                 if(wrqu->data.flags != 0)
563                         stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
564                 return 0;
565         } else
566                 return -EOPNOTSUPP;
567 }
568
569 /* ---------------------------------------------------------------- */
570 /*
571  * Standard Wireless Handler : get iwpriv definitions
572  * Export the driver private handler definition
573  * They will be picked up by tools like iwpriv...
574  */
575 static int iw_handler_get_private(struct net_device *           dev,
576                                   struct iw_request_info *      info,
577                                   union iwreq_data *            wrqu,
578                                   char *                        extra)
579 {
580         /* Check if the driver has something to export */
581         if((dev->wireless_handlers->num_private_args == 0) ||
582            (dev->wireless_handlers->private_args == NULL))
583                 return -EOPNOTSUPP;
584
585         /* Check if there is enough buffer up there */
586         if(wrqu->data.length < dev->wireless_handlers->num_private_args) {
587                 /* User space can't know in advance how large the buffer
588                  * needs to be. Give it a hint, so that we can support
589                  * any size buffer we want somewhat efficiently... */
590                 wrqu->data.length = dev->wireless_handlers->num_private_args;
591                 return -E2BIG;
592         }
593
594         /* Set the number of available ioctls. */
595         wrqu->data.length = dev->wireless_handlers->num_private_args;
596
597         /* Copy structure to the user buffer. */
598         memcpy(extra, dev->wireless_handlers->private_args,
599                sizeof(struct iw_priv_args) * wrqu->data.length);
600
601         return 0;
602 }
603
604
605 /******************** /proc/net/wireless SUPPORT ********************/
606 /*
607  * The /proc/net/wireless file is a human readable user-space interface
608  * exporting various wireless specific statistics from the wireless devices.
609  * This is the most popular part of the Wireless Extensions ;-)
610  *
611  * This interface is a pure clone of /proc/net/dev (in net/core/dev.c).
612  * The content of the file is basically the content of "struct iw_statistics".
613  */
614
615 #ifdef CONFIG_PROC_FS
616
617 /* ---------------------------------------------------------------- */
618 /*
619  * Print one entry (line) of /proc/net/wireless
620  */
621 static __inline__ void wireless_seq_printf_stats(struct seq_file *seq,
622                                                  struct net_device *dev)
623 {
624         /* Get stats from the driver */
625         struct iw_statistics *stats = get_wireless_stats(dev);
626
627         if (stats) {
628                 seq_printf(seq, "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d "
629                                 "%6d %6d   %6d\n",
630                            dev->name, stats->status, stats->qual.qual,
631                            stats->qual.updated & IW_QUAL_QUAL_UPDATED
632                            ? '.' : ' ',
633                            ((__s32) stats->qual.level) - 
634                            ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
635                            stats->qual.updated & IW_QUAL_LEVEL_UPDATED
636                            ? '.' : ' ',
637                            ((__s32) stats->qual.noise) - 
638                            ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
639                            stats->qual.updated & IW_QUAL_NOISE_UPDATED
640                            ? '.' : ' ',
641                            stats->discard.nwid, stats->discard.code,
642                            stats->discard.fragment, stats->discard.retries,
643                            stats->discard.misc, stats->miss.beacon);
644                 stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
645         }
646 }
647
648 /* ---------------------------------------------------------------- */
649 /*
650  * Print info for /proc/net/wireless (print all entries)
651  */
652 static int wireless_seq_show(struct seq_file *seq, void *v)
653 {
654         if (v == SEQ_START_TOKEN)
655                 seq_printf(seq, "Inter-| sta-|   Quality        |   Discarded "
656                                 "packets               | Missed | WE\n"
657                                 " face | tus | link level noise |  nwid  "
658                                 "crypt   frag  retry   misc | beacon | %d\n",
659                            WIRELESS_EXT);
660         else
661                 wireless_seq_printf_stats(seq, v);
662         return 0;
663 }
664
665 static struct seq_operations wireless_seq_ops = {
666         .start = dev_seq_start,
667         .next  = dev_seq_next,
668         .stop  = dev_seq_stop,
669         .show  = wireless_seq_show,
670 };
671
672 static int wireless_seq_open(struct inode *inode, struct file *file)
673 {
674         return seq_open(file, &wireless_seq_ops);
675 }
676
677 static struct file_operations wireless_seq_fops = {
678         .owner   = THIS_MODULE,
679         .open    = wireless_seq_open,
680         .read    = seq_read,
681         .llseek  = seq_lseek,
682         .release = seq_release,
683 };
684
685 int __init wireless_proc_init(void)
686 {
687         /* Create /proc/net/wireless entry */
688         if (!proc_net_fops_create("wireless", S_IRUGO, &wireless_seq_fops))
689                 return -ENOMEM;
690
691         return 0;
692 }
693 #endif  /* CONFIG_PROC_FS */
694
695 /************************** IOCTL SUPPORT **************************/
696 /*
697  * The original user space API to configure all those Wireless Extensions
698  * is through IOCTLs.
699  * In there, we check if we need to call the new driver API (iw_handler)
700  * or just call the driver ioctl handler.
701  */
702
703 /* ---------------------------------------------------------------- */
704 /*
705  * Wrapper to call a standard Wireless Extension handler.
706  * We do various checks and also take care of moving data between
707  * user space and kernel space.
708  */
709 static int ioctl_standard_call(struct net_device *      dev,
710                                struct ifreq *           ifr,
711                                unsigned int             cmd,
712                                iw_handler               handler)
713 {
714         struct iwreq *                          iwr = (struct iwreq *) ifr;
715         const struct iw_ioctl_description *     descr;
716         struct iw_request_info                  info;
717         int                                     ret = -EINVAL;
718
719         /* Get the description of the IOCTL */
720         if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
721                 return -EOPNOTSUPP;
722         descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
723
724 #ifdef WE_IOCTL_DEBUG
725         printk(KERN_DEBUG "%s (WE) : Found standard handler for 0x%04X\n",
726                ifr->ifr_name, cmd);
727         printk(KERN_DEBUG "%s (WE) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
728 #endif  /* WE_IOCTL_DEBUG */
729
730         /* Prepare the call */
731         info.cmd = cmd;
732         info.flags = 0;
733
734         /* Check if we have a pointer to user space data or not */
735         if(descr->header_type != IW_HEADER_TYPE_POINT) {
736
737                 /* No extra arguments. Trivial to handle */
738                 ret = handler(dev, &info, &(iwr->u), NULL);
739
740 #ifdef WE_SET_EVENT
741                 /* Generate an event to notify listeners of the change */
742                 if((descr->flags & IW_DESCR_FLAG_EVENT) &&
743                    ((ret == 0) || (ret == -EIWCOMMIT)))
744                         wireless_send_event(dev, cmd, &(iwr->u), NULL);
745 #endif  /* WE_SET_EVENT */
746         } else {
747                 char *  extra;
748                 int     extra_size;
749                 int     user_length = 0;
750                 int     err;
751
752                 /* Calculate space needed by arguments. Always allocate
753                  * for max space. Easier, and won't last long... */
754                 extra_size = descr->max_tokens * descr->token_size;
755
756                 /* Check what user space is giving us */
757                 if(IW_IS_SET(cmd)) {
758                         /* Check NULL pointer */
759                         if((iwr->u.data.pointer == NULL) &&
760                            (iwr->u.data.length != 0))
761                                 return -EFAULT;
762                         /* Check if number of token fits within bounds */
763                         if(iwr->u.data.length > descr->max_tokens)
764                                 return -E2BIG;
765                         if(iwr->u.data.length < descr->min_tokens)
766                                 return -EINVAL;
767                 } else {
768                         /* Check NULL pointer */
769                         if(iwr->u.data.pointer == NULL)
770                                 return -EFAULT;
771                         /* Save user space buffer size for checking */
772                         user_length = iwr->u.data.length;
773
774                         /* Don't check if user_length > max to allow forward
775                          * compatibility. The test user_length < min is
776                          * implied by the test at the end. */
777
778                         /* Support for very large requests */
779                         if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
780                            (user_length > descr->max_tokens)) {
781                                 /* Allow userspace to GET more than max so
782                                  * we can support any size GET requests.
783                                  * There is still a limit : -ENOMEM. */
784                                 extra_size = user_length * descr->token_size;
785                                 /* Note : user_length is originally a __u16,
786                                  * and token_size is controlled by us,
787                                  * so extra_size won't get negative and
788                                  * won't overflow... */
789                         }
790                 }
791
792 #ifdef WE_IOCTL_DEBUG
793                 printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
794                        dev->name, extra_size);
795 #endif  /* WE_IOCTL_DEBUG */
796
797                 /* Create the kernel buffer */
798                 extra = kmalloc(extra_size, GFP_KERNEL);
799                 if (extra == NULL) {
800                         return -ENOMEM;
801                 }
802
803                 /* If it is a SET, get all the extra data in here */
804                 if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
805                         err = copy_from_user(extra, iwr->u.data.pointer,
806                                              iwr->u.data.length *
807                                              descr->token_size);
808                         if (err) {
809                                 kfree(extra);
810                                 return -EFAULT;
811                         }
812 #ifdef WE_IOCTL_DEBUG
813                         printk(KERN_DEBUG "%s (WE) : Got %d bytes\n",
814                                dev->name,
815                                iwr->u.data.length * descr->token_size);
816 #endif  /* WE_IOCTL_DEBUG */
817                 }
818
819                 /* Call the handler */
820                 ret = handler(dev, &info, &(iwr->u), extra);
821
822                 /* If we have something to return to the user */
823                 if (!ret && IW_IS_GET(cmd)) {
824                         /* Check if there is enough buffer up there */
825                         if(user_length < iwr->u.data.length) {
826                                 kfree(extra);
827                                 return -E2BIG;
828                         }
829
830                         err = copy_to_user(iwr->u.data.pointer, extra,
831                                            iwr->u.data.length *
832                                            descr->token_size);
833                         if (err)
834                                 ret =  -EFAULT;                            
835 #ifdef WE_IOCTL_DEBUG
836                         printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n",
837                                dev->name,
838                                iwr->u.data.length * descr->token_size);
839 #endif  /* WE_IOCTL_DEBUG */
840                 }
841
842 #ifdef WE_SET_EVENT
843                 /* Generate an event to notify listeners of the change */
844                 if((descr->flags & IW_DESCR_FLAG_EVENT) &&
845                    ((ret == 0) || (ret == -EIWCOMMIT))) {
846                         if(descr->flags & IW_DESCR_FLAG_RESTRICT)
847                                 /* If the event is restricted, don't
848                                  * export the payload */
849                                 wireless_send_event(dev, cmd, &(iwr->u), NULL);
850                         else
851                                 wireless_send_event(dev, cmd, &(iwr->u),
852                                                     extra);
853                 }
854 #endif  /* WE_SET_EVENT */
855
856                 /* Cleanup - I told you it wasn't that long ;-) */
857                 kfree(extra);
858         }
859
860         /* Call commit handler if needed and defined */
861         if(ret == -EIWCOMMIT)
862                 ret = call_commit_handler(dev);
863
864         /* Here, we will generate the appropriate event if needed */
865
866         return ret;
867 }
868
869 /* ---------------------------------------------------------------- */
870 /*
871  * Wrapper to call a private Wireless Extension handler.
872  * We do various checks and also take care of moving data between
873  * user space and kernel space.
874  * It's not as nice and slimline as the standard wrapper. The cause
875  * is struct iw_priv_args, which was not really designed for the
876  * job we are going here.
877  *
878  * IMPORTANT : This function prevent to set and get data on the same
879  * IOCTL and enforce the SET/GET convention. Not doing it would be
880  * far too hairy...
881  * If you need to set and get data at the same time, please don't use
882  * a iw_handler but process it in your ioctl handler (i.e. use the
883  * old driver API).
884  */
885 static inline int ioctl_private_call(struct net_device *        dev,
886                                      struct ifreq *             ifr,
887                                      unsigned int               cmd,
888                                      iw_handler         handler)
889 {
890         struct iwreq *                  iwr = (struct iwreq *) ifr;
891         const struct iw_priv_args *     descr = NULL;
892         struct iw_request_info          info;
893         int                             extra_size = 0;
894         int                             i;
895         int                             ret = -EINVAL;
896
897         /* Get the description of the IOCTL */
898         for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
899                 if(cmd == dev->wireless_handlers->private_args[i].cmd) {
900                         descr = &(dev->wireless_handlers->private_args[i]);
901                         break;
902                 }
903
904 #ifdef WE_IOCTL_DEBUG
905         printk(KERN_DEBUG "%s (WE) : Found private handler for 0x%04X\n",
906                ifr->ifr_name, cmd);
907         if(descr) {
908                 printk(KERN_DEBUG "%s (WE) : Name %s, set %X, get %X\n",
909                        dev->name, descr->name,
910                        descr->set_args, descr->get_args);
911         }
912 #endif  /* WE_IOCTL_DEBUG */
913
914         /* Compute the size of the set/get arguments */
915         if(descr != NULL) {
916                 if(IW_IS_SET(cmd)) {
917                         int     offset = 0;     /* For sub-ioctls */
918                         /* Check for sub-ioctl handler */
919                         if(descr->name[0] == '\0')
920                                 /* Reserve one int for sub-ioctl index */
921                                 offset = sizeof(__u32);
922
923                         /* Size of set arguments */
924                         extra_size = get_priv_size(descr->set_args);
925
926                         /* Does it fits in iwr ? */
927                         if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
928                            ((extra_size + offset) <= IFNAMSIZ))
929                                 extra_size = 0;
930                 } else {
931                         /* Size of get arguments */
932                         extra_size = get_priv_size(descr->get_args);
933
934                         /* Does it fits in iwr ? */
935                         if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
936                            (extra_size <= IFNAMSIZ))
937                                 extra_size = 0;
938                 }
939         }
940
941         /* Prepare the call */
942         info.cmd = cmd;
943         info.flags = 0;
944
945         /* Check if we have a pointer to user space data or not. */
946         if(extra_size == 0) {
947                 /* No extra arguments. Trivial to handle */
948                 ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u));
949         } else {
950                 char *  extra;
951                 int     err;
952
953                 /* Check what user space is giving us */
954                 if(IW_IS_SET(cmd)) {
955                         /* Check NULL pointer */
956                         if((iwr->u.data.pointer == NULL) &&
957                            (iwr->u.data.length != 0))
958                                 return -EFAULT;
959
960                         /* Does it fits within bounds ? */
961                         if(iwr->u.data.length > (descr->set_args &
962                                                  IW_PRIV_SIZE_MASK))
963                                 return -E2BIG;
964                 } else {
965                         /* Check NULL pointer */
966                         if(iwr->u.data.pointer == NULL)
967                                 return -EFAULT;
968                 }
969
970 #ifdef WE_IOCTL_DEBUG
971                 printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
972                        dev->name, extra_size);
973 #endif  /* WE_IOCTL_DEBUG */
974
975                 /* Always allocate for max space. Easier, and won't last
976                  * long... */
977                 extra = kmalloc(extra_size, GFP_KERNEL);
978                 if (extra == NULL) {
979                         return -ENOMEM;
980                 }
981
982                 /* If it is a SET, get all the extra data in here */
983                 if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
984                         err = copy_from_user(extra, iwr->u.data.pointer,
985                                              extra_size);
986                         if (err) {
987                                 kfree(extra);
988                                 return -EFAULT;
989                         }
990 #ifdef WE_IOCTL_DEBUG
991                         printk(KERN_DEBUG "%s (WE) : Got %d elem\n",
992                                dev->name, iwr->u.data.length);
993 #endif  /* WE_IOCTL_DEBUG */
994                 }
995
996                 /* Call the handler */
997                 ret = handler(dev, &info, &(iwr->u), extra);
998
999                 /* If we have something to return to the user */
1000                 if (!ret && IW_IS_GET(cmd)) {
1001
1002                         /* Adjust for the actual length if it's variable,
1003                          * avoid leaking kernel bits outside. */
1004                         if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) {
1005                                 extra_size = adjust_priv_size(descr->get_args,
1006                                                               &(iwr->u));
1007                         }
1008
1009                         err = copy_to_user(iwr->u.data.pointer, extra,
1010                                            extra_size);
1011                         if (err)
1012                                 ret =  -EFAULT;                            
1013 #ifdef WE_IOCTL_DEBUG
1014                         printk(KERN_DEBUG "%s (WE) : Wrote %d elem\n",
1015                                dev->name, iwr->u.data.length);
1016 #endif  /* WE_IOCTL_DEBUG */
1017                 }
1018
1019                 /* Cleanup - I told you it wasn't that long ;-) */
1020                 kfree(extra);
1021         }
1022
1023
1024         /* Call commit handler if needed and defined */
1025         if(ret == -EIWCOMMIT)
1026                 ret = call_commit_handler(dev);
1027
1028         return ret;
1029 }
1030
1031 /* ---------------------------------------------------------------- */
1032 /*
1033  * Main IOCTl dispatcher. Called from the main networking code
1034  * (dev_ioctl() in net/core/dev.c).
1035  * Check the type of IOCTL and call the appropriate wrapper...
1036  */
1037 int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
1038 {
1039         struct net_device *dev;
1040         iw_handler      handler;
1041
1042         /* Permissions are already checked in dev_ioctl() before calling us.
1043          * The copy_to/from_user() of ifr is also dealt with in there */
1044
1045         /* Make sure the device exist */
1046         if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
1047                 return -ENODEV;
1048
1049         /* A bunch of special cases, then the generic case...
1050          * Note that 'cmd' is already filtered in dev_ioctl() with
1051          * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
1052         switch(cmd) 
1053         {
1054                 case SIOCGIWSTATS:
1055                         /* Get Wireless Stats */
1056                         return ioctl_standard_call(dev,
1057                                                    ifr,
1058                                                    cmd,
1059                                                    &iw_handler_get_iwstats);
1060
1061                 case SIOCGIWPRIV:
1062                         /* Check if we have some wireless handlers defined */
1063                         if(dev->wireless_handlers != NULL) {
1064                                 /* We export to user space the definition of
1065                                  * the private handler ourselves */
1066                                 return ioctl_standard_call(dev,
1067                                                            ifr,
1068                                                            cmd,
1069                                                            &iw_handler_get_private);
1070                         }
1071                         // ## Fall-through for old API ##
1072                 default:
1073                         /* Generic IOCTL */
1074                         /* Basic check */
1075                         if (!netif_device_present(dev))
1076                                 return -ENODEV;
1077                         /* New driver API : try to find the handler */
1078                         handler = get_handler(dev, cmd);
1079                         if(handler != NULL) {
1080                                 /* Standard and private are not the same */
1081                                 if(cmd < SIOCIWFIRSTPRIV)
1082                                         return ioctl_standard_call(dev,
1083                                                                    ifr,
1084                                                                    cmd,
1085                                                                    handler);
1086                                 else
1087                                         return ioctl_private_call(dev,
1088                                                                   ifr,
1089                                                                   cmd,
1090                                                                   handler);
1091                         }
1092                         /* Old driver API : call driver ioctl handler */
1093                         if (dev->do_ioctl) {
1094                                 return dev->do_ioctl(dev, ifr, cmd);
1095                         }
1096                         return -EOPNOTSUPP;
1097         }
1098         /* Not reached */
1099         return -EINVAL;
1100 }
1101
1102 /********************** RTNETLINK REQUEST API **********************/
1103 /*
1104  * The alternate user space API to configure all those Wireless Extensions
1105  * is through RtNetlink.
1106  * This API support only the new driver API (iw_handler).
1107  *
1108  * This RtNetlink API use the same query/reply model as the ioctl API.
1109  * Maximum effort has been done to fit in the RtNetlink model, and
1110  * we support both RtNetlink Set and RtNelink Get operations.
1111  * On the other hand, we don't offer Dump operations because of the
1112  * following reasons :
1113  *      o Large number of parameters, most optional
1114  *      o Large size of some parameters (> 100 bytes)
1115  *      o Each parameters need to be extracted from hardware
1116  *      o Scan requests can take seconds and disable network activity.
1117  * Because of this high cost/overhead, we want to return only the
1118  * parameters the user application is really interested in.
1119  * We could offer partial Dump using the IW_DESCR_FLAG_DUMP flag.
1120  *
1121  * The API uses the standard RtNetlink socket. When the RtNetlink code
1122  * find a IFLA_WIRELESS field in a RtNetlink SET_LINK request,
1123  * it calls here.
1124  */
1125
1126 #ifdef CONFIG_NET_WIRELESS_RTNETLINK
1127 /* ---------------------------------------------------------------- */
1128 /*
1129  * Wrapper to call a standard Wireless Extension GET handler.
1130  * We do various checks and call the handler with the proper args.
1131  */
1132 static int rtnetlink_standard_get(struct net_device *   dev,
1133                                   struct iw_event *     request,
1134                                   int                   request_len,
1135                                   iw_handler            handler,
1136                                   char **               p_buf,
1137                                   int *                 p_len)
1138 {
1139         const struct iw_ioctl_description *     descr = NULL;
1140         unsigned int                            cmd;
1141         union iwreq_data *                      wrqu;
1142         int                                     hdr_len;
1143         struct iw_request_info                  info;
1144         char *                                  buffer = NULL;
1145         int                                     buffer_size = 0;
1146         int                                     ret = -EINVAL;
1147
1148         /* Get the description of the Request */
1149         cmd = request->cmd;
1150         if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
1151                 return -EOPNOTSUPP;
1152         descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
1153
1154 #ifdef WE_RTNETLINK_DEBUG
1155         printk(KERN_DEBUG "%s (WE.r) : Found standard handler for 0x%04X\n",
1156                dev->name, cmd);
1157         printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
1158 #endif  /* WE_RTNETLINK_DEBUG */
1159
1160         /* Check if wrqu is complete */
1161         hdr_len = event_type_size[descr->header_type];
1162         if(request_len < hdr_len) {
1163 #ifdef WE_RTNETLINK_DEBUG
1164                 printk(KERN_DEBUG
1165                        "%s (WE.r) : Wireless request too short (%d)\n",
1166                        dev->name, request_len);
1167 #endif  /* WE_RTNETLINK_DEBUG */
1168                 return -EINVAL;
1169         }
1170
1171         /* Prepare the call */
1172         info.cmd = cmd;
1173         info.flags = 0;
1174
1175         /* Check if we have extra data in the reply or not */
1176         if(descr->header_type != IW_HEADER_TYPE_POINT) {
1177
1178                 /* Create the kernel buffer that we will return.
1179                  * It's at an offset to match the TYPE_POINT case... */
1180                 buffer_size = request_len + IW_EV_POINT_OFF;
1181                 buffer = kmalloc(buffer_size, GFP_KERNEL);
1182                 if (buffer == NULL) {
1183                         return -ENOMEM;
1184                 }
1185                 /* Copy event data */
1186                 memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
1187                 /* Use our own copy of wrqu */
1188                 wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
1189                                              + IW_EV_LCP_LEN);
1190
1191                 /* No extra arguments. Trivial to handle */
1192                 ret = handler(dev, &info, wrqu, NULL);
1193
1194         } else {
1195                 union iwreq_data        wrqu_point;
1196                 char *                  extra = NULL;
1197                 int                     extra_size = 0;
1198
1199                 /* Get a temp copy of wrqu (skip pointer) */
1200                 memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1201                        ((char *) request) + IW_EV_LCP_LEN,
1202                        IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1203
1204                 /* Calculate space needed by arguments. Always allocate
1205                  * for max space. Easier, and won't last long... */
1206                 extra_size = descr->max_tokens * descr->token_size;
1207                 /* Support for very large requests */
1208                 if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
1209                    (wrqu_point.data.length > descr->max_tokens))
1210                         extra_size = (wrqu_point.data.length
1211                                       * descr->token_size);
1212                 buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF;
1213 #ifdef WE_RTNETLINK_DEBUG
1214                 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
1215                        dev->name, extra_size, buffer_size);
1216 #endif  /* WE_RTNETLINK_DEBUG */
1217
1218                 /* Create the kernel buffer that we will return */
1219                 buffer = kmalloc(buffer_size, GFP_KERNEL);
1220                 if (buffer == NULL) {
1221                         return -ENOMEM;
1222                 }
1223
1224                 /* Put wrqu in the right place (just before extra).
1225                  * Leave space for IWE header and dummy pointer...
1226                  * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
1227                  */
1228                 memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
1229                        ((char *) &wrqu_point) + IW_EV_POINT_OFF,
1230                        IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1231                 wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN);
1232
1233                 /* Extra comes logically after that. Offset +12 bytes. */
1234                 extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN;
1235
1236                 /* Call the handler */
1237                 ret = handler(dev, &info, wrqu, extra);
1238
1239                 /* Calculate real returned length */
1240                 extra_size = (wrqu->data.length * descr->token_size);
1241                 /* Re-adjust reply size */
1242                 request->len = extra_size + IW_EV_POINT_LEN;
1243
1244                 /* Put the iwe header where it should, i.e. scrap the
1245                  * dummy pointer. */
1246                 memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN);
1247
1248 #ifdef WE_RTNETLINK_DEBUG
1249                 printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
1250 #endif  /* WE_RTNETLINK_DEBUG */
1251
1252                 /* Check if there is enough buffer up there */
1253                 if(wrqu_point.data.length < wrqu->data.length)
1254                         ret = -E2BIG;
1255         }
1256
1257         /* Return the buffer to the caller */
1258         if (!ret) {
1259                 *p_buf = buffer;
1260                 *p_len = request->len;
1261         } else {
1262                 /* Cleanup */
1263                 if(buffer)
1264                         kfree(buffer);
1265         }
1266
1267         return ret;
1268 }
1269
1270 /* ---------------------------------------------------------------- */
1271 /*
1272  * Wrapper to call a standard Wireless Extension SET handler.
1273  * We do various checks and call the handler with the proper args.
1274  */
1275 static inline int rtnetlink_standard_set(struct net_device *    dev,
1276                                          struct iw_event *      request,
1277                                          int                    request_len,
1278                                          iw_handler             handler)
1279 {
1280         const struct iw_ioctl_description *     descr = NULL;
1281         unsigned int                            cmd;
1282         union iwreq_data *                      wrqu;
1283         union iwreq_data                        wrqu_point;
1284         int                                     hdr_len;
1285         char *                                  extra = NULL;
1286         int                                     extra_size = 0;
1287         struct iw_request_info                  info;
1288         int                                     ret = -EINVAL;
1289
1290         /* Get the description of the Request */
1291         cmd = request->cmd;
1292         if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
1293                 return -EOPNOTSUPP;
1294         descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
1295
1296 #ifdef WE_RTNETLINK_DEBUG
1297         printk(KERN_DEBUG "%s (WE.r) : Found standard SET handler for 0x%04X\n",
1298                dev->name, cmd);
1299         printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
1300 #endif  /* WE_RTNETLINK_DEBUG */
1301
1302         /* Extract fixed header from request. This is properly aligned. */
1303         wrqu = &request->u;
1304
1305         /* Check if wrqu is complete */
1306         hdr_len = event_type_size[descr->header_type];
1307         if(request_len < hdr_len) {
1308 #ifdef WE_RTNETLINK_DEBUG
1309                 printk(KERN_DEBUG
1310                        "%s (WE.r) : Wireless request too short (%d)\n",
1311                        dev->name, request_len);
1312 #endif  /* WE_RTNETLINK_DEBUG */
1313                 return -EINVAL;
1314         }
1315
1316         /* Prepare the call */
1317         info.cmd = cmd;
1318         info.flags = 0;
1319
1320         /* Check if we have extra data in the request or not */
1321         if(descr->header_type != IW_HEADER_TYPE_POINT) {
1322
1323                 /* No extra arguments. Trivial to handle */
1324                 ret = handler(dev, &info, wrqu, NULL);
1325
1326         } else {
1327                 int     extra_len;
1328
1329                 /* Put wrqu in the right place (skip pointer) */
1330                 memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1331                        wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1332                 /* Don't forget about the event code... */
1333                 wrqu = &wrqu_point;
1334
1335                 /* Check if number of token fits within bounds */
1336                 if(wrqu_point.data.length > descr->max_tokens)
1337                         return -E2BIG;
1338                 if(wrqu_point.data.length < descr->min_tokens)
1339                         return -EINVAL;
1340
1341                 /* Real length of payload */
1342                 extra_len = wrqu_point.data.length * descr->token_size;
1343
1344                 /* Check if request is self consistent */
1345                 if((request_len - hdr_len) < extra_len) {
1346 #ifdef WE_RTNETLINK_DEBUG
1347                         printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n",
1348                                dev->name, extra_size);
1349 #endif  /* WE_RTNETLINK_DEBUG */
1350                         return -EINVAL;
1351                 }
1352
1353 #ifdef WE_RTNETLINK_DEBUG
1354                 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n",
1355                        dev->name, extra_size);
1356 #endif  /* WE_RTNETLINK_DEBUG */
1357
1358                 /* Always allocate for max space. Easier, and won't last
1359                  * long... */
1360                 extra_size = descr->max_tokens * descr->token_size;
1361                 extra = kmalloc(extra_size, GFP_KERNEL);
1362                 if (extra == NULL)
1363                         return -ENOMEM;
1364
1365                 /* Copy extra in aligned buffer */
1366                 memcpy(extra, ((char *) request) + hdr_len, extra_len);
1367
1368                 /* Call the handler */
1369                 ret = handler(dev, &info, &wrqu_point, extra);
1370         }
1371
1372 #ifdef WE_SET_EVENT
1373         /* Generate an event to notify listeners of the change */
1374         if((descr->flags & IW_DESCR_FLAG_EVENT) &&
1375            ((ret == 0) || (ret == -EIWCOMMIT))) {
1376                 if(descr->flags & IW_DESCR_FLAG_RESTRICT)
1377                         /* If the event is restricted, don't
1378                          * export the payload */
1379                         wireless_send_event(dev, cmd, wrqu, NULL);
1380                 else
1381                         wireless_send_event(dev, cmd, wrqu, extra);
1382         }
1383 #endif  /* WE_SET_EVENT */
1384
1385         /* Cleanup - I told you it wasn't that long ;-) */
1386         if(extra)
1387                 kfree(extra);
1388
1389         /* Call commit handler if needed and defined */
1390         if(ret == -EIWCOMMIT)
1391                 ret = call_commit_handler(dev);
1392
1393         return ret;
1394 }
1395
1396 /* ---------------------------------------------------------------- */
1397 /*
1398  * Wrapper to call a private Wireless Extension GET handler.
1399  * Same as above...
1400  * It's not as nice and slimline as the standard wrapper. The cause
1401  * is struct iw_priv_args, which was not really designed for the
1402  * job we are going here.
1403  *
1404  * IMPORTANT : This function prevent to set and get data on the same
1405  * IOCTL and enforce the SET/GET convention. Not doing it would be
1406  * far too hairy...
1407  * If you need to set and get data at the same time, please don't use
1408  * a iw_handler but process it in your ioctl handler (i.e. use the
1409  * old driver API).
1410  */
1411 static inline int rtnetlink_private_get(struct net_device *     dev,
1412                                         struct iw_event *       request,
1413                                         int                     request_len,
1414                                         iw_handler              handler,
1415                                         char **                 p_buf,
1416                                         int *                   p_len)
1417 {
1418         const struct iw_priv_args *     descr = NULL;
1419         unsigned int                    cmd;
1420         union iwreq_data *              wrqu;
1421         int                             hdr_len;
1422         struct iw_request_info          info;
1423         int                             extra_size = 0;
1424         int                             i;
1425         char *                          buffer = NULL;
1426         int                             buffer_size = 0;
1427         int                             ret = -EINVAL;
1428
1429         /* Get the description of the Request */
1430         cmd = request->cmd;
1431         for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
1432                 if(cmd == dev->wireless_handlers->private_args[i].cmd) {
1433                         descr = &(dev->wireless_handlers->private_args[i]);
1434                         break;
1435                 }
1436         if(descr == NULL)
1437                 return -EOPNOTSUPP;
1438
1439 #ifdef WE_RTNETLINK_DEBUG
1440         printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n",
1441                dev->name, cmd);
1442         printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n",
1443                dev->name, descr->name, descr->set_args, descr->get_args);
1444 #endif  /* WE_RTNETLINK_DEBUG */
1445
1446         /* Compute the max size of the get arguments */
1447         extra_size = get_priv_size(descr->get_args);
1448
1449         /* Does it fits in wrqu ? */
1450         if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
1451            (extra_size <= IFNAMSIZ)) {
1452                 hdr_len = extra_size;
1453                 extra_size = 0;
1454         } else {
1455                 hdr_len = IW_EV_POINT_LEN;
1456         }
1457
1458         /* Check if wrqu is complete */
1459         if(request_len < hdr_len) {
1460 #ifdef WE_RTNETLINK_DEBUG
1461                 printk(KERN_DEBUG
1462                        "%s (WE.r) : Wireless request too short (%d)\n",
1463                        dev->name, request_len);
1464 #endif  /* WE_RTNETLINK_DEBUG */
1465                 return -EINVAL;
1466         }
1467
1468         /* Prepare the call */
1469         info.cmd = cmd;
1470         info.flags = 0;
1471
1472         /* Check if we have a pointer to user space data or not. */
1473         if(extra_size == 0) {
1474
1475                 /* Create the kernel buffer that we will return.
1476                  * It's at an offset to match the TYPE_POINT case... */
1477                 buffer_size = request_len + IW_EV_POINT_OFF;
1478                 buffer = kmalloc(buffer_size, GFP_KERNEL);
1479                 if (buffer == NULL) {
1480                         return -ENOMEM;
1481                 }
1482                 /* Copy event data */
1483                 memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
1484                 /* Use our own copy of wrqu */
1485                 wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
1486                                              + IW_EV_LCP_LEN);
1487
1488                 /* No extra arguments. Trivial to handle */
1489                 ret = handler(dev, &info, wrqu, (char *) wrqu);
1490
1491         } else {
1492                 char *  extra;
1493
1494                 /* Buffer for full reply */
1495                 buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF;
1496
1497 #ifdef WE_RTNETLINK_DEBUG
1498                 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
1499                        dev->name, extra_size, buffer_size);
1500 #endif  /* WE_RTNETLINK_DEBUG */
1501
1502                 /* Create the kernel buffer that we will return */
1503                 buffer = kmalloc(buffer_size, GFP_KERNEL);
1504                 if (buffer == NULL) {
1505                         return -ENOMEM;
1506                 }
1507
1508                 /* Put wrqu in the right place (just before extra).
1509                  * Leave space for IWE header and dummy pointer...
1510                  * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
1511                  */
1512                 memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
1513                        ((char *) request) + IW_EV_LCP_LEN,
1514                        IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1515                 wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN);
1516
1517                 /* Extra comes logically after that. Offset +12 bytes. */
1518                 extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN;
1519
1520                 /* Call the handler */
1521                 ret = handler(dev, &info, wrqu, extra);
1522
1523                 /* Adjust for the actual length if it's variable,
1524                  * avoid leaking kernel bits outside. */
1525                 if (!(descr->get_args & IW_PRIV_SIZE_FIXED))
1526                         extra_size = adjust_priv_size(descr->get_args, wrqu);
1527                 /* Re-adjust reply size */
1528                 request->len = extra_size + IW_EV_POINT_LEN;
1529
1530                 /* Put the iwe header where it should, i.e. scrap the
1531                  * dummy pointer. */
1532                 memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN);
1533
1534 #ifdef WE_RTNETLINK_DEBUG
1535                 printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
1536 #endif  /* WE_RTNETLINK_DEBUG */
1537         }
1538
1539         /* Return the buffer to the caller */
1540         if (!ret) {
1541                 *p_buf = buffer;
1542                 *p_len = request->len;
1543         } else {
1544                 /* Cleanup */
1545                 if(buffer)
1546                         kfree(buffer);
1547         }
1548
1549         return ret;
1550 }
1551
1552 /* ---------------------------------------------------------------- */
1553 /*
1554  * Wrapper to call a private Wireless Extension SET handler.
1555  * Same as above...
1556  * It's not as nice and slimline as the standard wrapper. The cause
1557  * is struct iw_priv_args, which was not really designed for the
1558  * job we are going here.
1559  *
1560  * IMPORTANT : This function prevent to set and get data on the same
1561  * IOCTL and enforce the SET/GET convention. Not doing it would be
1562  * far too hairy...
1563  * If you need to set and get data at the same time, please don't use
1564  * a iw_handler but process it in your ioctl handler (i.e. use the
1565  * old driver API).
1566  */
1567 static inline int rtnetlink_private_set(struct net_device *     dev,
1568                                         struct iw_event *       request,
1569                                         int                     request_len,
1570                                         iw_handler              handler)
1571 {
1572         const struct iw_priv_args *     descr = NULL;
1573         unsigned int                    cmd;
1574         union iwreq_data *              wrqu;
1575         union iwreq_data                wrqu_point;
1576         int                             hdr_len;
1577         char *                          extra = NULL;
1578         int                             extra_size = 0;
1579         int                             offset = 0;     /* For sub-ioctls */
1580         struct iw_request_info          info;
1581         int                             i;
1582         int                             ret = -EINVAL;
1583
1584         /* Get the description of the Request */
1585         cmd = request->cmd;
1586         for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
1587                 if(cmd == dev->wireless_handlers->private_args[i].cmd) {
1588                         descr = &(dev->wireless_handlers->private_args[i]);
1589                         break;
1590                 }
1591         if(descr == NULL)
1592                 return -EOPNOTSUPP;
1593
1594 #ifdef WE_RTNETLINK_DEBUG
1595         printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n",
1596                ifr->ifr_name, cmd);
1597         printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n",
1598                dev->name, descr->name, descr->set_args, descr->get_args);
1599 #endif  /* WE_RTNETLINK_DEBUG */
1600
1601         /* Compute the size of the set arguments */
1602         /* Check for sub-ioctl handler */
1603         if(descr->name[0] == '\0')
1604                 /* Reserve one int for sub-ioctl index */
1605                 offset = sizeof(__u32);
1606
1607         /* Size of set arguments */
1608         extra_size = get_priv_size(descr->set_args);
1609
1610         /* Does it fits in wrqu ? */
1611         if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
1612            (extra_size <= IFNAMSIZ)) {
1613                 hdr_len = IW_EV_LCP_LEN + extra_size;
1614                 extra_size = 0;
1615         } else {
1616                 hdr_len = IW_EV_POINT_LEN;
1617         }
1618
1619         /* Extract fixed header from request. This is properly aligned. */
1620         wrqu = &request->u;
1621
1622         /* Check if wrqu is complete */
1623         if(request_len < hdr_len) {
1624 #ifdef WE_RTNETLINK_DEBUG
1625                 printk(KERN_DEBUG
1626                        "%s (WE.r) : Wireless request too short (%d)\n",
1627                        dev->name, request_len);
1628 #endif  /* WE_RTNETLINK_DEBUG */
1629                 return -EINVAL;
1630         }
1631
1632         /* Prepare the call */
1633         info.cmd = cmd;
1634         info.flags = 0;
1635
1636         /* Check if we have a pointer to user space data or not. */
1637         if(extra_size == 0) {
1638
1639                 /* No extra arguments. Trivial to handle */
1640                 ret = handler(dev, &info, wrqu, (char *) wrqu);
1641
1642         } else {
1643                 int     extra_len;
1644
1645                 /* Put wrqu in the right place (skip pointer) */
1646                 memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1647                        wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN);
1648
1649                 /* Does it fits within bounds ? */
1650                 if(wrqu_point.data.length > (descr->set_args &
1651                                              IW_PRIV_SIZE_MASK))
1652                         return -E2BIG;
1653
1654                 /* Real length of payload */
1655                 extra_len = adjust_priv_size(descr->set_args, &wrqu_point);
1656
1657                 /* Check if request is self consistent */
1658                 if((request_len - hdr_len) < extra_len) {
1659 #ifdef WE_RTNETLINK_DEBUG
1660                         printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n",
1661                                dev->name, extra_size);
1662 #endif  /* WE_RTNETLINK_DEBUG */
1663                         return -EINVAL;
1664                 }
1665
1666 #ifdef WE_RTNETLINK_DEBUG
1667                 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n",
1668                        dev->name, extra_size);
1669 #endif  /* WE_RTNETLINK_DEBUG */
1670
1671                 /* Always allocate for max space. Easier, and won't last
1672                  * long... */
1673                 extra = kmalloc(extra_size, GFP_KERNEL);
1674                 if (extra == NULL)
1675                         return -ENOMEM;
1676
1677                 /* Copy extra in aligned buffer */
1678                 memcpy(extra, ((char *) request) + hdr_len, extra_len);
1679
1680                 /* Call the handler */
1681                 ret = handler(dev, &info, &wrqu_point, extra);
1682
1683                 /* Cleanup - I told you it wasn't that long ;-) */
1684                 kfree(extra);
1685         }
1686
1687         /* Call commit handler if needed and defined */
1688         if(ret == -EIWCOMMIT)
1689                 ret = call_commit_handler(dev);
1690
1691         return ret;
1692 }
1693
1694 /* ---------------------------------------------------------------- */
1695 /*
1696  * Main RtNetlink dispatcher. Called from the main networking code
1697  * (do_getlink() in net/core/rtnetlink.c).
1698  * Check the type of Request and call the appropriate wrapper...
1699  */
1700 int wireless_rtnetlink_get(struct net_device *  dev,
1701                            char *               data,
1702                            int                  len,
1703                            char **              p_buf,
1704                            int *                p_len)
1705 {
1706         struct iw_event *       request = (struct iw_event *) data;
1707         iw_handler              handler;
1708
1709         /* Check length */
1710         if(len < IW_EV_LCP_LEN) {
1711                 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
1712                        dev->name, len);
1713                 return -EINVAL;
1714         }
1715
1716         /* ReCheck length (len may have padding) */
1717         if(request->len > len) {
1718                 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n",
1719                        dev->name, request->len, len);
1720                 return -EINVAL;
1721         }
1722
1723         /* Only accept GET requests in here */
1724         if(!IW_IS_GET(request->cmd))
1725                 return -EOPNOTSUPP;
1726
1727         /* If command is `get the encoding parameters', check if
1728          * the user has the right to do it */
1729         if (request->cmd == SIOCGIWENCODE ||
1730             request->cmd == SIOCGIWENCODEEXT) {
1731                 if (!capable(CAP_NET_ADMIN))
1732                         return -EPERM;
1733         }
1734
1735         /* Special cases */
1736         if(request->cmd == SIOCGIWSTATS)
1737                 /* Get Wireless Stats */
1738                 return rtnetlink_standard_get(dev,
1739                                               request,
1740                                               request->len,
1741                                               &iw_handler_get_iwstats,
1742                                               p_buf, p_len);
1743         if(request->cmd == SIOCGIWPRIV) {
1744                 /* Check if we have some wireless handlers defined */
1745                 if(dev->wireless_handlers == NULL)
1746                         return -EOPNOTSUPP;
1747                 /* Get Wireless Stats */
1748                 return rtnetlink_standard_get(dev,
1749                                               request,
1750                                               request->len,
1751                                               &iw_handler_get_private,
1752                                               p_buf, p_len);
1753         }
1754
1755         /* Basic check */
1756         if (!netif_device_present(dev))
1757                 return -ENODEV;
1758
1759         /* Try to find the handler */
1760         handler = get_handler(dev, request->cmd);
1761         if(handler != NULL) {
1762                 /* Standard and private are not the same */
1763                 if(request->cmd < SIOCIWFIRSTPRIV)
1764                         return rtnetlink_standard_get(dev,
1765                                                       request,
1766                                                       request->len,
1767                                                       handler,
1768                                                       p_buf, p_len);
1769                 else
1770                         return rtnetlink_private_get(dev,
1771                                                      request,
1772                                                      request->len,
1773                                                      handler,
1774                                                      p_buf, p_len);
1775         }
1776
1777         return -EOPNOTSUPP;
1778 }
1779
1780 /* ---------------------------------------------------------------- */
1781 /*
1782  * Main RtNetlink dispatcher. Called from the main networking code
1783  * (do_setlink() in net/core/rtnetlink.c).
1784  * Check the type of Request and call the appropriate wrapper...
1785  */
1786 int wireless_rtnetlink_set(struct net_device *  dev,
1787                            char *               data,
1788                            int                  len)
1789 {
1790         struct iw_event *       request = (struct iw_event *) data;
1791         iw_handler              handler;
1792
1793         /* Check length */
1794         if(len < IW_EV_LCP_LEN) {
1795                 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
1796                        dev->name, len);
1797                 return -EINVAL;
1798         }
1799
1800         /* ReCheck length (len may have padding) */
1801         if(request->len > len) {
1802                 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n",
1803                        dev->name, request->len, len);
1804                 return -EINVAL;
1805         }
1806
1807         /* Only accept SET requests in here */
1808         if(!IW_IS_SET(request->cmd))
1809                 return -EOPNOTSUPP;
1810
1811         /* Basic check */
1812         if (!netif_device_present(dev))
1813                 return -ENODEV;
1814
1815         /* New driver API : try to find the handler */
1816         handler = get_handler(dev, request->cmd);
1817         if(handler != NULL) {
1818                 /* Standard and private are not the same */
1819                 if(request->cmd < SIOCIWFIRSTPRIV)
1820                         return rtnetlink_standard_set(dev,
1821                                                       request,
1822                                                       request->len,
1823                                                       handler);
1824                 else
1825                         return rtnetlink_private_set(dev,
1826                                                      request,
1827                                                      request->len,
1828                                                      handler);
1829         }
1830
1831         return -EOPNOTSUPP;
1832 }
1833 #endif  /* CONFIG_NET_WIRELESS_RTNETLINK */
1834
1835
1836 /************************* EVENT PROCESSING *************************/
1837 /*
1838  * Process events generated by the wireless layer or the driver.
1839  * Most often, the event will be propagated through rtnetlink
1840  */
1841
1842 #ifdef WE_EVENT_RTNETLINK
1843 /* ---------------------------------------------------------------- */
1844 /*
1845  * Locking...
1846  * ----------
1847  *
1848  * Thanks to Herbert Xu <herbert@gondor.apana.org.au> for fixing
1849  * the locking issue in here and implementing this code !
1850  *
1851  * The issue : wireless_send_event() is often called in interrupt context,
1852  * while the Netlink layer can never be called in interrupt context.
1853  * The fully formed RtNetlink events are queued, and then a tasklet is run
1854  * to feed those to Netlink.
1855  * The skb_queue is interrupt safe, and its lock is not held while calling
1856  * Netlink, so there is no possibility of dealock.
1857  * Jean II
1858  */
1859
1860 static struct sk_buff_head wireless_nlevent_queue;
1861
1862 static int __init wireless_nlevent_init(void)
1863 {
1864         skb_queue_head_init(&wireless_nlevent_queue);
1865         return 0;
1866 }
1867
1868 subsys_initcall(wireless_nlevent_init);
1869
1870 static void wireless_nlevent_process(unsigned long data)
1871 {
1872         struct sk_buff *skb;
1873
1874         while ((skb = skb_dequeue(&wireless_nlevent_queue)))
1875                 rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
1876 }
1877
1878 static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
1879
1880 /* ---------------------------------------------------------------- */
1881 /*
1882  * Fill a rtnetlink message with our event data.
1883  * Note that we propage only the specified event and don't dump the
1884  * current wireless config. Dumping the wireless config is far too
1885  * expensive (for each parameter, the driver need to query the hardware).
1886  */
1887 static inline int rtnetlink_fill_iwinfo(struct sk_buff *        skb,
1888                                         struct net_device *     dev,
1889                                         int                     type,
1890                                         char *                  event,
1891                                         int                     event_len)
1892 {
1893         struct ifinfomsg *r;
1894         struct nlmsghdr  *nlh;
1895         unsigned char    *b = skb->tail;
1896
1897         nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(*r));
1898         r = NLMSG_DATA(nlh);
1899         r->ifi_family = AF_UNSPEC;
1900         r->__ifi_pad = 0;
1901         r->ifi_type = dev->type;
1902         r->ifi_index = dev->ifindex;
1903         r->ifi_flags = dev_get_flags(dev);
1904         r->ifi_change = 0;      /* Wireless changes don't affect those flags */
1905
1906         /* Add the wireless events in the netlink packet */
1907         RTA_PUT(skb, IFLA_WIRELESS, event_len, event);
1908
1909         nlh->nlmsg_len = skb->tail - b;
1910         return skb->len;
1911
1912 nlmsg_failure:
1913 rtattr_failure:
1914         skb_trim(skb, b - skb->data);
1915         return -1;
1916 }
1917
1918 /* ---------------------------------------------------------------- */
1919 /*
1920  * Create and broadcast and send it on the standard rtnetlink socket
1921  * This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c
1922  * Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field
1923  * within a RTM_NEWLINK event.
1924  */
1925 static inline void rtmsg_iwinfo(struct net_device *     dev,
1926                                 char *                  event,
1927                                 int                     event_len)
1928 {
1929         struct sk_buff *skb;
1930         int size = NLMSG_GOODSIZE;
1931
1932         skb = alloc_skb(size, GFP_ATOMIC);
1933         if (!skb)
1934                 return;
1935
1936         if (rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK,
1937                                   event, event_len) < 0) {
1938                 kfree_skb(skb);
1939                 return;
1940         }
1941         NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
1942         skb_queue_tail(&wireless_nlevent_queue, skb);
1943         tasklet_schedule(&wireless_nlevent_tasklet);
1944 }
1945
1946 #endif  /* WE_EVENT_RTNETLINK */
1947
1948 /* ---------------------------------------------------------------- */
1949 /*
1950  * Main event dispatcher. Called from other parts and drivers.
1951  * Send the event on the appropriate channels.
1952  * May be called from interrupt context.
1953  */
1954 void wireless_send_event(struct net_device *    dev,
1955                          unsigned int           cmd,
1956                          union iwreq_data *     wrqu,
1957                          char *                 extra)
1958 {
1959         const struct iw_ioctl_description *     descr = NULL;
1960         int extra_len = 0;
1961         struct iw_event  *event;                /* Mallocated whole event */
1962         int event_len;                          /* Its size */
1963         int hdr_len;                            /* Size of the event header */
1964         int wrqu_off = 0;                       /* Offset in wrqu */
1965         /* Don't "optimise" the following variable, it will crash */
1966         unsigned        cmd_index;              /* *MUST* be unsigned */
1967
1968         /* Get the description of the Event */
1969         if(cmd <= SIOCIWLAST) {
1970                 cmd_index = cmd - SIOCIWFIRST;
1971                 if(cmd_index < standard_ioctl_num)
1972                         descr = &(standard_ioctl[cmd_index]);
1973         } else {
1974                 cmd_index = cmd - IWEVFIRST;
1975                 if(cmd_index < standard_event_num)
1976                         descr = &(standard_event[cmd_index]);
1977         }
1978         /* Don't accept unknown events */
1979         if(descr == NULL) {
1980                 /* Note : we don't return an error to the driver, because
1981                  * the driver would not know what to do about it. It can't
1982                  * return an error to the user, because the event is not
1983                  * initiated by a user request.
1984                  * The best the driver could do is to log an error message.
1985                  * We will do it ourselves instead...
1986                  */
1987                 printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
1988                        dev->name, cmd);
1989                 return;
1990         }
1991 #ifdef WE_EVENT_DEBUG
1992         printk(KERN_DEBUG "%s (WE) : Got event 0x%04X\n",
1993                dev->name, cmd);
1994         printk(KERN_DEBUG "%s (WE) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
1995 #endif  /* WE_EVENT_DEBUG */
1996
1997         /* Check extra parameters and set extra_len */
1998         if(descr->header_type == IW_HEADER_TYPE_POINT) {
1999                 /* Check if number of token fits within bounds */
2000                 if(wrqu->data.length > descr->max_tokens) {
2001                         printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length);
2002                         return;
2003                 }
2004                 if(wrqu->data.length < descr->min_tokens) {
2005                         printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length);
2006                         return;
2007                 }
2008                 /* Calculate extra_len - extra is NULL for restricted events */
2009                 if(extra != NULL)
2010                         extra_len = wrqu->data.length * descr->token_size;
2011                 /* Always at an offset in wrqu */
2012                 wrqu_off = IW_EV_POINT_OFF;
2013 #ifdef WE_EVENT_DEBUG
2014                 printk(KERN_DEBUG "%s (WE) : Event 0x%04X, tokens %d, extra_len %d\n", dev->name, cmd, wrqu->data.length, extra_len);
2015 #endif  /* WE_EVENT_DEBUG */
2016         }
2017
2018         /* Total length of the event */
2019         hdr_len = event_type_size[descr->header_type];
2020         event_len = hdr_len + extra_len;
2021
2022 #ifdef WE_EVENT_DEBUG
2023         printk(KERN_DEBUG "%s (WE) : Event 0x%04X, hdr_len %d, wrqu_off %d, event_len %d\n", dev->name, cmd, hdr_len, wrqu_off, event_len);
2024 #endif  /* WE_EVENT_DEBUG */
2025
2026         /* Create temporary buffer to hold the event */
2027         event = kmalloc(event_len, GFP_ATOMIC);
2028         if(event == NULL)
2029                 return;
2030
2031         /* Fill event */
2032         event->len = event_len;
2033         event->cmd = cmd;
2034         memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
2035         if(extra != NULL)
2036                 memcpy(((char *) event) + hdr_len, extra, extra_len);
2037
2038 #ifdef WE_EVENT_RTNETLINK
2039         /* Send via the RtNetlink event channel */
2040         rtmsg_iwinfo(dev, (char *) event, event_len);
2041 #endif  /* WE_EVENT_RTNETLINK */
2042
2043         /* Cleanup */
2044         kfree(event);
2045
2046         return;         /* Always success, I guess ;-) */
2047 }
2048
2049 /********************** ENHANCED IWSPY SUPPORT **********************/
2050 /*
2051  * In the old days, the driver was handling spy support all by itself.
2052  * Now, the driver can delegate this task to Wireless Extensions.
2053  * It needs to use those standard spy iw_handler in struct iw_handler_def,
2054  * push data to us via wireless_spy_update() and include struct iw_spy_data
2055  * in its private part (and export it in net_device->wireless_data->spy_data).
2056  * One of the main advantage of centralising spy support here is that
2057  * it becomes much easier to improve and extend it without having to touch
2058  * the drivers. One example is the addition of the Spy-Threshold events.
2059  */
2060
2061 /* ---------------------------------------------------------------- */
2062 /*
2063  * Return the pointer to the spy data in the driver.
2064  * Because this is called on the Rx path via wireless_spy_update(),
2065  * we want it to be efficient...
2066  */
2067 static inline struct iw_spy_data * get_spydata(struct net_device *dev)
2068 {
2069         /* This is the new way */
2070         if(dev->wireless_data)
2071                 return(dev->wireless_data->spy_data);
2072         return NULL;
2073 }
2074
2075 /*------------------------------------------------------------------*/
2076 /*
2077  * Standard Wireless Handler : set Spy List
2078  */
2079 int iw_handler_set_spy(struct net_device *      dev,
2080                        struct iw_request_info * info,
2081                        union iwreq_data *       wrqu,
2082                        char *                   extra)
2083 {
2084         struct iw_spy_data *    spydata = get_spydata(dev);
2085         struct sockaddr *       address = (struct sockaddr *) extra;
2086
2087         /* Make sure driver is not buggy or using the old API */
2088         if(!spydata)
2089                 return -EOPNOTSUPP;
2090
2091         /* Disable spy collection while we copy the addresses.
2092          * While we copy addresses, any call to wireless_spy_update()
2093          * will NOP. This is OK, as anyway the addresses are changing. */
2094         spydata->spy_number = 0;
2095
2096         /* We want to operate without locking, because wireless_spy_update()
2097          * most likely will happen in the interrupt handler, and therefore
2098          * have its own locking constraints and needs performance.
2099          * The rtnl_lock() make sure we don't race with the other iw_handlers.
2100          * This make sure wireless_spy_update() "see" that the spy list
2101          * is temporarily disabled. */
2102         wmb();
2103
2104         /* Are there are addresses to copy? */
2105         if(wrqu->data.length > 0) {
2106                 int i;
2107
2108                 /* Copy addresses */
2109                 for(i = 0; i < wrqu->data.length; i++)
2110                         memcpy(spydata->spy_address[i], address[i].sa_data,
2111                                ETH_ALEN);
2112                 /* Reset stats */
2113                 memset(spydata->spy_stat, 0,
2114                        sizeof(struct iw_quality) * IW_MAX_SPY);
2115
2116 #ifdef WE_SPY_DEBUG
2117                 printk(KERN_DEBUG "iw_handler_set_spy() :  wireless_data %p, spydata %p, num %d\n", dev->wireless_data, spydata, wrqu->data.length);
2118                 for (i = 0; i < wrqu->data.length; i++)
2119                         printk(KERN_DEBUG
2120                                "%02X:%02X:%02X:%02X:%02X:%02X \n",
2121                                spydata->spy_address[i][0],
2122                                spydata->spy_address[i][1],
2123                                spydata->spy_address[i][2],
2124                                spydata->spy_address[i][3],
2125                                spydata->spy_address[i][4],
2126                                spydata->spy_address[i][5]);
2127 #endif  /* WE_SPY_DEBUG */
2128         }
2129
2130         /* Make sure above is updated before re-enabling */
2131         wmb();
2132
2133         /* Enable addresses */
2134         spydata->spy_number = wrqu->data.length;
2135
2136         return 0;
2137 }
2138
2139 /*------------------------------------------------------------------*/
2140 /*
2141  * Standard Wireless Handler : get Spy List
2142  */
2143 int iw_handler_get_spy(struct net_device *      dev,
2144                        struct iw_request_info * info,
2145                        union iwreq_data *       wrqu,
2146                        char *                   extra)
2147 {
2148         struct iw_spy_data *    spydata = get_spydata(dev);
2149         struct sockaddr *       address = (struct sockaddr *) extra;
2150         int                     i;
2151
2152         /* Make sure driver is not buggy or using the old API */
2153         if(!spydata)
2154                 return -EOPNOTSUPP;
2155
2156         wrqu->data.length = spydata->spy_number;
2157
2158         /* Copy addresses. */
2159         for(i = 0; i < spydata->spy_number; i++)        {
2160                 memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
2161                 address[i].sa_family = AF_UNIX;
2162         }
2163         /* Copy stats to the user buffer (just after). */
2164         if(spydata->spy_number > 0)
2165                 memcpy(extra  + (sizeof(struct sockaddr) *spydata->spy_number),
2166                        spydata->spy_stat,
2167                        sizeof(struct iw_quality) * spydata->spy_number);
2168         /* Reset updated flags. */
2169         for(i = 0; i < spydata->spy_number; i++)
2170                 spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED;
2171         return 0;
2172 }
2173
2174 /*------------------------------------------------------------------*/
2175 /*
2176  * Standard Wireless Handler : set spy threshold
2177  */
2178 int iw_handler_set_thrspy(struct net_device *   dev,
2179                           struct iw_request_info *info,
2180                           union iwreq_data *    wrqu,
2181                           char *                extra)
2182 {
2183         struct iw_spy_data *    spydata = get_spydata(dev);
2184         struct iw_thrspy *      threshold = (struct iw_thrspy *) extra;
2185
2186         /* Make sure driver is not buggy or using the old API */
2187         if(!spydata)
2188                 return -EOPNOTSUPP;
2189
2190         /* Just do it */
2191         memcpy(&(spydata->spy_thr_low), &(threshold->low),
2192                2 * sizeof(struct iw_quality));
2193
2194         /* Clear flag */
2195         memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
2196
2197 #ifdef WE_SPY_DEBUG
2198         printk(KERN_DEBUG "iw_handler_set_thrspy() :  low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level);
2199 #endif  /* WE_SPY_DEBUG */
2200
2201         return 0;
2202 }
2203
2204 /*------------------------------------------------------------------*/
2205 /*
2206  * Standard Wireless Handler : get spy threshold
2207  */
2208 int iw_handler_get_thrspy(struct net_device *   dev,
2209                           struct iw_request_info *info,
2210                           union iwreq_data *    wrqu,
2211                           char *                extra)
2212 {
2213         struct iw_spy_data *    spydata = get_spydata(dev);
2214         struct iw_thrspy *      threshold = (struct iw_thrspy *) extra;
2215
2216         /* Make sure driver is not buggy or using the old API */
2217         if(!spydata)
2218                 return -EOPNOTSUPP;
2219
2220         /* Just do it */
2221         memcpy(&(threshold->low), &(spydata->spy_thr_low),
2222                2 * sizeof(struct iw_quality));
2223
2224         return 0;
2225 }
2226
2227 /*------------------------------------------------------------------*/
2228 /*
2229  * Prepare and send a Spy Threshold event
2230  */
2231 static void iw_send_thrspy_event(struct net_device *    dev,
2232                                  struct iw_spy_data *   spydata,
2233                                  unsigned char *        address,
2234                                  struct iw_quality *    wstats)
2235 {
2236         union iwreq_data        wrqu;
2237         struct iw_thrspy        threshold;
2238
2239         /* Init */
2240         wrqu.data.length = 1;
2241         wrqu.data.flags = 0;
2242         /* Copy address */
2243         memcpy(threshold.addr.sa_data, address, ETH_ALEN);
2244         threshold.addr.sa_family = ARPHRD_ETHER;
2245         /* Copy stats */
2246         memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
2247         /* Copy also thresholds */
2248         memcpy(&(threshold.low), &(spydata->spy_thr_low),
2249                2 * sizeof(struct iw_quality));
2250
2251 #ifdef WE_SPY_DEBUG
2252         printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n",
2253                threshold.addr.sa_data[0],
2254                threshold.addr.sa_data[1],
2255                threshold.addr.sa_data[2],
2256                threshold.addr.sa_data[3],
2257                threshold.addr.sa_data[4],
2258                threshold.addr.sa_data[5], threshold.qual.level);
2259 #endif  /* WE_SPY_DEBUG */
2260
2261         /* Send event to user space */
2262         wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
2263 }
2264
2265 /* ---------------------------------------------------------------- */
2266 /*
2267  * Call for the driver to update the spy data.
2268  * For now, the spy data is a simple array. As the size of the array is
2269  * small, this is good enough. If we wanted to support larger number of
2270  * spy addresses, we should use something more efficient...
2271  */
2272 void wireless_spy_update(struct net_device *    dev,
2273                          unsigned char *        address,
2274                          struct iw_quality *    wstats)
2275 {
2276         struct iw_spy_data *    spydata = get_spydata(dev);
2277         int                     i;
2278         int                     match = -1;
2279
2280         /* Make sure driver is not buggy or using the old API */
2281         if(!spydata)
2282                 return;
2283
2284 #ifdef WE_SPY_DEBUG
2285         printk(KERN_DEBUG "wireless_spy_update() :  wireless_data %p, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_data, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
2286 #endif  /* WE_SPY_DEBUG */
2287
2288         /* Update all records that match */
2289         for(i = 0; i < spydata->spy_number; i++)
2290                 if(!compare_ether_addr(address, spydata->spy_address[i])) {
2291                         memcpy(&(spydata->spy_stat[i]), wstats,
2292                                sizeof(struct iw_quality));
2293                         match = i;
2294                 }
2295
2296         /* Generate an event if we cross the spy threshold.
2297          * To avoid event storms, we have a simple hysteresis : we generate
2298          * event only when we go under the low threshold or above the
2299          * high threshold. */
2300         if(match >= 0) {
2301                 if(spydata->spy_thr_under[match]) {
2302                         if(wstats->level > spydata->spy_thr_high.level) {
2303                                 spydata->spy_thr_under[match] = 0;
2304                                 iw_send_thrspy_event(dev, spydata,
2305                                                      address, wstats);
2306                         }
2307                 } else {
2308                         if(wstats->level < spydata->spy_thr_low.level) {
2309                                 spydata->spy_thr_under[match] = 1;
2310                                 iw_send_thrspy_event(dev, spydata,
2311                                                      address, wstats);
2312                         }
2313                 }
2314         }
2315 }
2316
2317 EXPORT_SYMBOL(iw_handler_get_spy);
2318 EXPORT_SYMBOL(iw_handler_get_thrspy);
2319 EXPORT_SYMBOL(iw_handler_set_spy);
2320 EXPORT_SYMBOL(iw_handler_set_thrspy);
2321 EXPORT_SYMBOL(wireless_send_event);
2322 EXPORT_SYMBOL(wireless_spy_update);