Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[linux-2.6] / 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-2005 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
70 /***************************** INCLUDES *****************************/
71
72 #include <linux/config.h>               /* Not needed ??? */
73 #include <linux/module.h>
74 #include <linux/types.h>                /* off_t */
75 #include <linux/netdevice.h>            /* struct ifreq, dev_get_by_name() */
76 #include <linux/proc_fs.h>
77 #include <linux/rtnetlink.h>            /* rtnetlink stuff */
78 #include <linux/seq_file.h>
79 #include <linux/init.h>                 /* for __init */
80 #include <linux/if_arp.h>               /* ARPHRD_ETHER */
81 #include <linux/etherdevice.h>          /* compare_ether_addr */
82
83 #include <linux/wireless.h>             /* Pretty obvious */
84 #include <net/iw_handler.h>             /* New driver API */
85
86 #include <asm/uaccess.h>                /* copy_to_user() */
87
88 /**************************** CONSTANTS ****************************/
89
90 /* Debugging stuff */
91 #undef WE_IOCTL_DEBUG           /* Debug IOCTL API */
92 #undef WE_EVENT_DEBUG           /* Debug Event dispatcher */
93 #undef WE_SPY_DEBUG             /* Debug enhanced spy support */
94
95 /* Options */
96 #define WE_EVENT_NETLINK        /* Propagate events using rtnetlink */
97 #define WE_SET_EVENT            /* Generate an event on some set commands */
98
99 /************************* GLOBAL VARIABLES *************************/
100 /*
101  * You should not use global variables, because of re-entrancy.
102  * On our case, it's only const, so it's OK...
103  */
104 /*
105  * Meta-data about all the standard Wireless Extension request we
106  * know about.
107  */
108 static const struct iw_ioctl_description standard_ioctl[] = {
109         [SIOCSIWCOMMIT  - SIOCIWFIRST] = {
110                 .header_type    = IW_HEADER_TYPE_NULL,
111         },
112         [SIOCGIWNAME    - SIOCIWFIRST] = {
113                 .header_type    = IW_HEADER_TYPE_CHAR,
114                 .flags          = IW_DESCR_FLAG_DUMP,
115         },
116         [SIOCSIWNWID    - SIOCIWFIRST] = {
117                 .header_type    = IW_HEADER_TYPE_PARAM,
118                 .flags          = IW_DESCR_FLAG_EVENT,
119         },
120         [SIOCGIWNWID    - SIOCIWFIRST] = {
121                 .header_type    = IW_HEADER_TYPE_PARAM,
122                 .flags          = IW_DESCR_FLAG_DUMP,
123         },
124         [SIOCSIWFREQ    - SIOCIWFIRST] = {
125                 .header_type    = IW_HEADER_TYPE_FREQ,
126                 .flags          = IW_DESCR_FLAG_EVENT,
127         },
128         [SIOCGIWFREQ    - SIOCIWFIRST] = {
129                 .header_type    = IW_HEADER_TYPE_FREQ,
130                 .flags          = IW_DESCR_FLAG_DUMP,
131         },
132         [SIOCSIWMODE    - SIOCIWFIRST] = {
133                 .header_type    = IW_HEADER_TYPE_UINT,
134                 .flags          = IW_DESCR_FLAG_EVENT,
135         },
136         [SIOCGIWMODE    - SIOCIWFIRST] = {
137                 .header_type    = IW_HEADER_TYPE_UINT,
138                 .flags          = IW_DESCR_FLAG_DUMP,
139         },
140         [SIOCSIWSENS    - SIOCIWFIRST] = {
141                 .header_type    = IW_HEADER_TYPE_PARAM,
142         },
143         [SIOCGIWSENS    - SIOCIWFIRST] = {
144                 .header_type    = IW_HEADER_TYPE_PARAM,
145         },
146         [SIOCSIWRANGE   - SIOCIWFIRST] = {
147                 .header_type    = IW_HEADER_TYPE_NULL,
148         },
149         [SIOCGIWRANGE   - SIOCIWFIRST] = {
150                 .header_type    = IW_HEADER_TYPE_POINT,
151                 .token_size     = 1,
152                 .max_tokens     = sizeof(struct iw_range),
153                 .flags          = IW_DESCR_FLAG_DUMP,
154         },
155         [SIOCSIWPRIV    - SIOCIWFIRST] = {
156                 .header_type    = IW_HEADER_TYPE_NULL,
157         },
158         [SIOCGIWPRIV    - SIOCIWFIRST] = { /* (handled directly by us) */
159                 .header_type    = IW_HEADER_TYPE_NULL,
160         },
161         [SIOCSIWSTATS   - SIOCIWFIRST] = {
162                 .header_type    = IW_HEADER_TYPE_NULL,
163         },
164         [SIOCGIWSTATS   - SIOCIWFIRST] = { /* (handled directly by us) */
165                 .header_type    = IW_HEADER_TYPE_NULL,
166                 .flags          = IW_DESCR_FLAG_DUMP,
167         },
168         [SIOCSIWSPY     - SIOCIWFIRST] = {
169                 .header_type    = IW_HEADER_TYPE_POINT,
170                 .token_size     = sizeof(struct sockaddr),
171                 .max_tokens     = IW_MAX_SPY,
172         },
173         [SIOCGIWSPY     - SIOCIWFIRST] = {
174                 .header_type    = IW_HEADER_TYPE_POINT,
175                 .token_size     = sizeof(struct sockaddr) +
176                                   sizeof(struct iw_quality),
177                 .max_tokens     = IW_MAX_SPY,
178         },
179         [SIOCSIWTHRSPY  - SIOCIWFIRST] = {
180                 .header_type    = IW_HEADER_TYPE_POINT,
181                 .token_size     = sizeof(struct iw_thrspy),
182                 .min_tokens     = 1,
183                 .max_tokens     = 1,
184         },
185         [SIOCGIWTHRSPY  - SIOCIWFIRST] = {
186                 .header_type    = IW_HEADER_TYPE_POINT,
187                 .token_size     = sizeof(struct iw_thrspy),
188                 .min_tokens     = 1,
189                 .max_tokens     = 1,
190         },
191         [SIOCSIWAP      - SIOCIWFIRST] = {
192                 .header_type    = IW_HEADER_TYPE_ADDR,
193         },
194         [SIOCGIWAP      - SIOCIWFIRST] = {
195                 .header_type    = IW_HEADER_TYPE_ADDR,
196                 .flags          = IW_DESCR_FLAG_DUMP,
197         },
198         [SIOCSIWMLME    - SIOCIWFIRST] = {
199                 .header_type    = IW_HEADER_TYPE_POINT,
200                 .token_size     = 1,
201                 .min_tokens     = sizeof(struct iw_mlme),
202                 .max_tokens     = sizeof(struct iw_mlme),
203         },
204         [SIOCGIWAPLIST  - SIOCIWFIRST] = {
205                 .header_type    = IW_HEADER_TYPE_POINT,
206                 .token_size     = sizeof(struct sockaddr) +
207                                   sizeof(struct iw_quality),
208                 .max_tokens     = IW_MAX_AP,
209                 .flags          = IW_DESCR_FLAG_NOMAX,
210         },
211         [SIOCSIWSCAN    - SIOCIWFIRST] = {
212                 .header_type    = IW_HEADER_TYPE_POINT,
213                 .token_size     = 1,
214                 .min_tokens     = 0,
215                 .max_tokens     = sizeof(struct iw_scan_req),
216         },
217         [SIOCGIWSCAN    - SIOCIWFIRST] = {
218                 .header_type    = IW_HEADER_TYPE_POINT,
219                 .token_size     = 1,
220                 .max_tokens     = IW_SCAN_MAX_DATA,
221                 .flags          = IW_DESCR_FLAG_NOMAX,
222         },
223         [SIOCSIWESSID   - SIOCIWFIRST] = {
224                 .header_type    = IW_HEADER_TYPE_POINT,
225                 .token_size     = 1,
226                 .max_tokens     = IW_ESSID_MAX_SIZE + 1,
227                 .flags          = IW_DESCR_FLAG_EVENT,
228         },
229         [SIOCGIWESSID   - SIOCIWFIRST] = {
230                 .header_type    = IW_HEADER_TYPE_POINT,
231                 .token_size     = 1,
232                 .max_tokens     = IW_ESSID_MAX_SIZE + 1,
233                 .flags          = IW_DESCR_FLAG_DUMP,
234         },
235         [SIOCSIWNICKN   - SIOCIWFIRST] = {
236                 .header_type    = IW_HEADER_TYPE_POINT,
237                 .token_size     = 1,
238                 .max_tokens     = IW_ESSID_MAX_SIZE + 1,
239         },
240         [SIOCGIWNICKN   - SIOCIWFIRST] = {
241                 .header_type    = IW_HEADER_TYPE_POINT,
242                 .token_size     = 1,
243                 .max_tokens     = IW_ESSID_MAX_SIZE + 1,
244         },
245         [SIOCSIWRATE    - SIOCIWFIRST] = {
246                 .header_type    = IW_HEADER_TYPE_PARAM,
247         },
248         [SIOCGIWRATE    - SIOCIWFIRST] = {
249                 .header_type    = IW_HEADER_TYPE_PARAM,
250         },
251         [SIOCSIWRTS     - SIOCIWFIRST] = {
252                 .header_type    = IW_HEADER_TYPE_PARAM,
253         },
254         [SIOCGIWRTS     - SIOCIWFIRST] = {
255                 .header_type    = IW_HEADER_TYPE_PARAM,
256         },
257         [SIOCSIWFRAG    - SIOCIWFIRST] = {
258                 .header_type    = IW_HEADER_TYPE_PARAM,
259         },
260         [SIOCGIWFRAG    - SIOCIWFIRST] = {
261                 .header_type    = IW_HEADER_TYPE_PARAM,
262         },
263         [SIOCSIWTXPOW   - SIOCIWFIRST] = {
264                 .header_type    = IW_HEADER_TYPE_PARAM,
265         },
266         [SIOCGIWTXPOW   - SIOCIWFIRST] = {
267                 .header_type    = IW_HEADER_TYPE_PARAM,
268         },
269         [SIOCSIWRETRY   - SIOCIWFIRST] = {
270                 .header_type    = IW_HEADER_TYPE_PARAM,
271         },
272         [SIOCGIWRETRY   - SIOCIWFIRST] = {
273                 .header_type    = IW_HEADER_TYPE_PARAM,
274         },
275         [SIOCSIWENCODE  - SIOCIWFIRST] = {
276                 .header_type    = IW_HEADER_TYPE_POINT,
277                 .token_size     = 1,
278                 .max_tokens     = IW_ENCODING_TOKEN_MAX,
279                 .flags          = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
280         },
281         [SIOCGIWENCODE  - SIOCIWFIRST] = {
282                 .header_type    = IW_HEADER_TYPE_POINT,
283                 .token_size     = 1,
284                 .max_tokens     = IW_ENCODING_TOKEN_MAX,
285                 .flags          = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
286         },
287         [SIOCSIWPOWER   - SIOCIWFIRST] = {
288                 .header_type    = IW_HEADER_TYPE_PARAM,
289         },
290         [SIOCGIWPOWER   - SIOCIWFIRST] = {
291                 .header_type    = IW_HEADER_TYPE_PARAM,
292         },
293         [SIOCSIWGENIE   - SIOCIWFIRST] = {
294                 .header_type    = IW_HEADER_TYPE_POINT,
295                 .token_size     = 1,
296                 .max_tokens     = IW_GENERIC_IE_MAX,
297         },
298         [SIOCGIWGENIE   - SIOCIWFIRST] = {
299                 .header_type    = IW_HEADER_TYPE_POINT,
300                 .token_size     = 1,
301                 .max_tokens     = IW_GENERIC_IE_MAX,
302         },
303         [SIOCSIWAUTH    - SIOCIWFIRST] = {
304                 .header_type    = IW_HEADER_TYPE_PARAM,
305         },
306         [SIOCGIWAUTH    - SIOCIWFIRST] = {
307                 .header_type    = IW_HEADER_TYPE_PARAM,
308         },
309         [SIOCSIWENCODEEXT - SIOCIWFIRST] = {
310                 .header_type    = IW_HEADER_TYPE_POINT,
311                 .token_size     = 1,
312                 .min_tokens     = sizeof(struct iw_encode_ext),
313                 .max_tokens     = sizeof(struct iw_encode_ext) +
314                                   IW_ENCODING_TOKEN_MAX,
315         },
316         [SIOCGIWENCODEEXT - SIOCIWFIRST] = {
317                 .header_type    = IW_HEADER_TYPE_POINT,
318                 .token_size     = 1,
319                 .min_tokens     = sizeof(struct iw_encode_ext),
320                 .max_tokens     = sizeof(struct iw_encode_ext) +
321                                   IW_ENCODING_TOKEN_MAX,
322         },
323         [SIOCSIWPMKSA - SIOCIWFIRST] = {
324                 .header_type    = IW_HEADER_TYPE_POINT,
325                 .token_size     = 1,
326                 .min_tokens     = sizeof(struct iw_pmksa),
327                 .max_tokens     = sizeof(struct iw_pmksa),
328         },
329 };
330 static const int standard_ioctl_num = (sizeof(standard_ioctl) /
331                                        sizeof(struct iw_ioctl_description));
332
333 /*
334  * Meta-data about all the additional standard Wireless Extension events
335  * we know about.
336  */
337 static const struct iw_ioctl_description standard_event[] = {
338         [IWEVTXDROP     - IWEVFIRST] = {
339                 .header_type    = IW_HEADER_TYPE_ADDR,
340         },
341         [IWEVQUAL       - IWEVFIRST] = {
342                 .header_type    = IW_HEADER_TYPE_QUAL,
343         },
344         [IWEVCUSTOM     - IWEVFIRST] = {
345                 .header_type    = IW_HEADER_TYPE_POINT,
346                 .token_size     = 1,
347                 .max_tokens     = IW_CUSTOM_MAX,
348         },
349         [IWEVREGISTERED - IWEVFIRST] = {
350                 .header_type    = IW_HEADER_TYPE_ADDR,
351         },
352         [IWEVEXPIRED    - IWEVFIRST] = {
353                 .header_type    = IW_HEADER_TYPE_ADDR, 
354         },
355         [IWEVGENIE      - IWEVFIRST] = {
356                 .header_type    = IW_HEADER_TYPE_POINT,
357                 .token_size     = 1,
358                 .max_tokens     = IW_GENERIC_IE_MAX,
359         },
360         [IWEVMICHAELMICFAILURE  - IWEVFIRST] = {
361                 .header_type    = IW_HEADER_TYPE_POINT, 
362                 .token_size     = 1,
363                 .max_tokens     = sizeof(struct iw_michaelmicfailure),
364         },
365         [IWEVASSOCREQIE - IWEVFIRST] = {
366                 .header_type    = IW_HEADER_TYPE_POINT,
367                 .token_size     = 1,
368                 .max_tokens     = IW_GENERIC_IE_MAX,
369         },
370         [IWEVASSOCRESPIE        - IWEVFIRST] = {
371                 .header_type    = IW_HEADER_TYPE_POINT,
372                 .token_size     = 1,
373                 .max_tokens     = IW_GENERIC_IE_MAX,
374         },
375         [IWEVPMKIDCAND  - IWEVFIRST] = {
376                 .header_type    = IW_HEADER_TYPE_POINT,
377                 .token_size     = 1,
378                 .max_tokens     = sizeof(struct iw_pmkid_cand),
379         },
380 };
381 static const int standard_event_num = (sizeof(standard_event) /
382                                        sizeof(struct iw_ioctl_description));
383
384 /* Size (in bytes) of the various private data types */
385 static const char iw_priv_type_size[] = {
386         0,                              /* IW_PRIV_TYPE_NONE */
387         1,                              /* IW_PRIV_TYPE_BYTE */
388         1,                              /* IW_PRIV_TYPE_CHAR */
389         0,                              /* Not defined */
390         sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
391         sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
392         sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
393         0,                              /* Not defined */
394 };
395
396 /* Size (in bytes) of various events */
397 static const int event_type_size[] = {
398         IW_EV_LCP_LEN,                  /* IW_HEADER_TYPE_NULL */
399         0,
400         IW_EV_CHAR_LEN,                 /* IW_HEADER_TYPE_CHAR */
401         0,
402         IW_EV_UINT_LEN,                 /* IW_HEADER_TYPE_UINT */
403         IW_EV_FREQ_LEN,                 /* IW_HEADER_TYPE_FREQ */
404         IW_EV_ADDR_LEN,                 /* IW_HEADER_TYPE_ADDR */
405         0,
406         IW_EV_POINT_LEN,                /* Without variable payload */
407         IW_EV_PARAM_LEN,                /* IW_HEADER_TYPE_PARAM */
408         IW_EV_QUAL_LEN,                 /* IW_HEADER_TYPE_QUAL */
409 };
410
411 /************************ COMMON SUBROUTINES ************************/
412 /*
413  * Stuff that may be used in various place or doesn't fit in one
414  * of the section below.
415  */
416
417 /* ---------------------------------------------------------------- */
418 /*
419  * Return the driver handler associated with a specific Wireless Extension.
420  * Called from various place, so make sure it remains efficient.
421  */
422 static inline iw_handler get_handler(struct net_device *dev,
423                                      unsigned int cmd)
424 {
425         /* Don't "optimise" the following variable, it will crash */
426         unsigned int    index;          /* *MUST* be unsigned */
427
428         /* Check if we have some wireless handlers defined */
429         if(dev->wireless_handlers == NULL)
430                 return NULL;
431
432         /* Try as a standard command */
433         index = cmd - SIOCIWFIRST;
434         if(index < dev->wireless_handlers->num_standard)
435                 return dev->wireless_handlers->standard[index];
436
437         /* Try as a private command */
438         index = cmd - SIOCIWFIRSTPRIV;
439         if(index < dev->wireless_handlers->num_private)
440                 return dev->wireless_handlers->private[index];
441
442         /* Not found */
443         return NULL;
444 }
445
446 /* ---------------------------------------------------------------- */
447 /*
448  * Get statistics out of the driver
449  */
450 static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
451 {
452         /* New location */
453         if((dev->wireless_handlers != NULL) &&
454            (dev->wireless_handlers->get_wireless_stats != NULL))
455                 return dev->wireless_handlers->get_wireless_stats(dev);
456
457         /* Old location, field to be removed in next WE */
458         if(dev->get_wireless_stats) {
459                 static int printed_message;
460
461                 if (!printed_message++)
462                         printk(KERN_DEBUG "%s (WE) : Driver using old /proc/net/wireless support, please fix driver !\n",
463                                 dev->name);
464
465                 return dev->get_wireless_stats(dev);
466         }
467
468         /* Not found */
469         return (struct iw_statistics *) NULL;
470 }
471
472 /* ---------------------------------------------------------------- */
473 /*
474  * Call the commit handler in the driver
475  * (if exist and if conditions are right)
476  *
477  * Note : our current commit strategy is currently pretty dumb,
478  * but we will be able to improve on that...
479  * The goal is to try to agreagate as many changes as possible
480  * before doing the commit. Drivers that will define a commit handler
481  * are usually those that need a reset after changing parameters, so
482  * we want to minimise the number of reset.
483  * A cool idea is to use a timer : at each "set" command, we re-set the
484  * timer, when the timer eventually fires, we call the driver.
485  * Hopefully, more on that later.
486  *
487  * Also, I'm waiting to see how many people will complain about the
488  * netif_running(dev) test. I'm open on that one...
489  * Hopefully, the driver will remember to do a commit in "open()" ;-)
490  */
491 static inline int call_commit_handler(struct net_device *       dev)
492 {
493         if((netif_running(dev)) &&
494            (dev->wireless_handlers->standard[0] != NULL)) {
495                 /* Call the commit handler on the driver */
496                 return dev->wireless_handlers->standard[0](dev, NULL,
497                                                            NULL, NULL);
498         } else
499                 return 0;               /* Command completed successfully */
500 }
501
502 /* ---------------------------------------------------------------- */
503 /*
504  * Calculate size of private arguments
505  */
506 static inline int get_priv_size(__u16   args)
507 {
508         int     num = args & IW_PRIV_SIZE_MASK;
509         int     type = (args & IW_PRIV_TYPE_MASK) >> 12;
510
511         return num * iw_priv_type_size[type];
512 }
513
514 /* ---------------------------------------------------------------- */
515 /*
516  * Re-calculate the size of private arguments
517  */
518 static inline int adjust_priv_size(__u16                args,
519                                    union iwreq_data *   wrqu)
520 {
521         int     num = wrqu->data.length;
522         int     max = args & IW_PRIV_SIZE_MASK;
523         int     type = (args & IW_PRIV_TYPE_MASK) >> 12;
524
525         /* Make sure the driver doesn't goof up */
526         if (max < num)
527                 num = max;
528
529         return num * iw_priv_type_size[type];
530 }
531
532
533 /******************** /proc/net/wireless SUPPORT ********************/
534 /*
535  * The /proc/net/wireless file is a human readable user-space interface
536  * exporting various wireless specific statistics from the wireless devices.
537  * This is the most popular part of the Wireless Extensions ;-)
538  *
539  * This interface is a pure clone of /proc/net/dev (in net/core/dev.c).
540  * The content of the file is basically the content of "struct iw_statistics".
541  */
542
543 #ifdef CONFIG_PROC_FS
544
545 /* ---------------------------------------------------------------- */
546 /*
547  * Print one entry (line) of /proc/net/wireless
548  */
549 static __inline__ void wireless_seq_printf_stats(struct seq_file *seq,
550                                                  struct net_device *dev)
551 {
552         /* Get stats from the driver */
553         struct iw_statistics *stats = get_wireless_stats(dev);
554
555         if (stats) {
556                 seq_printf(seq, "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d "
557                                 "%6d %6d   %6d\n",
558                            dev->name, stats->status, stats->qual.qual,
559                            stats->qual.updated & IW_QUAL_QUAL_UPDATED
560                            ? '.' : ' ',
561                            ((__s32) stats->qual.level) - 
562                            ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
563                            stats->qual.updated & IW_QUAL_LEVEL_UPDATED
564                            ? '.' : ' ',
565                            ((__s32) stats->qual.noise) - 
566                            ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
567                            stats->qual.updated & IW_QUAL_NOISE_UPDATED
568                            ? '.' : ' ',
569                            stats->discard.nwid, stats->discard.code,
570                            stats->discard.fragment, stats->discard.retries,
571                            stats->discard.misc, stats->miss.beacon);
572                 stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
573         }
574 }
575
576 /* ---------------------------------------------------------------- */
577 /*
578  * Print info for /proc/net/wireless (print all entries)
579  */
580 static int wireless_seq_show(struct seq_file *seq, void *v)
581 {
582         if (v == SEQ_START_TOKEN)
583                 seq_printf(seq, "Inter-| sta-|   Quality        |   Discarded "
584                                 "packets               | Missed | WE\n"
585                                 " face | tus | link level noise |  nwid  "
586                                 "crypt   frag  retry   misc | beacon | %d\n",
587                            WIRELESS_EXT);
588         else
589                 wireless_seq_printf_stats(seq, v);
590         return 0;
591 }
592
593 static struct seq_operations wireless_seq_ops = {
594         .start = dev_seq_start,
595         .next  = dev_seq_next,
596         .stop  = dev_seq_stop,
597         .show  = wireless_seq_show,
598 };
599
600 static int wireless_seq_open(struct inode *inode, struct file *file)
601 {
602         return seq_open(file, &wireless_seq_ops);
603 }
604
605 static struct file_operations wireless_seq_fops = {
606         .owner   = THIS_MODULE,
607         .open    = wireless_seq_open,
608         .read    = seq_read,
609         .llseek  = seq_lseek,
610         .release = seq_release,
611 };
612
613 int __init wireless_proc_init(void)
614 {
615         /* Create /proc/net/wireless entry */
616         if (!proc_net_fops_create("wireless", S_IRUGO, &wireless_seq_fops))
617                 return -ENOMEM;
618
619         return 0;
620 }
621 #endif  /* CONFIG_PROC_FS */
622
623 /************************** IOCTL SUPPORT **************************/
624 /*
625  * The original user space API to configure all those Wireless Extensions
626  * is through IOCTLs.
627  * In there, we check if we need to call the new driver API (iw_handler)
628  * or just call the driver ioctl handler.
629  */
630
631 /* ---------------------------------------------------------------- */
632 /*
633  *      Allow programatic access to /proc/net/wireless even if /proc
634  *      doesn't exist... Also more efficient...
635  */
636 static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
637 {
638         /* Get stats from the driver */
639         struct iw_statistics *stats;
640
641         stats = get_wireless_stats(dev);
642         if (stats != (struct iw_statistics *) NULL) {
643                 struct iwreq *  wrq = (struct iwreq *)ifr;
644
645                 /* Copy statistics to the user buffer */
646                 if(copy_to_user(wrq->u.data.pointer, stats,
647                                 sizeof(struct iw_statistics)))
648                         return -EFAULT;
649
650                 /* Check if we need to clear the updated flag */
651                 if(wrq->u.data.flags != 0)
652                         stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
653                 return 0;
654         } else
655                 return -EOPNOTSUPP;
656 }
657
658 /* ---------------------------------------------------------------- */
659 /*
660  * Export the driver private handler definition
661  * They will be picked up by tools like iwpriv...
662  */
663 static inline int ioctl_export_private(struct net_device *      dev,
664                                        struct ifreq *           ifr)
665 {
666         struct iwreq *                          iwr = (struct iwreq *) ifr;
667
668         /* Check if the driver has something to export */
669         if((dev->wireless_handlers->num_private_args == 0) ||
670            (dev->wireless_handlers->private_args == NULL))
671                 return -EOPNOTSUPP;
672
673         /* Check NULL pointer */
674         if(iwr->u.data.pointer == NULL)
675                 return -EFAULT;
676
677         /* Check if there is enough buffer up there */
678         if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
679                 /* User space can't know in advance how large the buffer
680                  * needs to be. Give it a hint, so that we can support
681                  * any size buffer we want somewhat efficiently... */
682                 iwr->u.data.length = dev->wireless_handlers->num_private_args;
683                 return -E2BIG;
684         }
685
686         /* Set the number of available ioctls. */
687         iwr->u.data.length = dev->wireless_handlers->num_private_args;
688
689         /* Copy structure to the user buffer. */
690         if (copy_to_user(iwr->u.data.pointer,
691                          dev->wireless_handlers->private_args,
692                          sizeof(struct iw_priv_args) * iwr->u.data.length))
693                 return -EFAULT;
694
695         return 0;
696 }
697
698 /* ---------------------------------------------------------------- */
699 /*
700  * Wrapper to call a standard Wireless Extension handler.
701  * We do various checks and also take care of moving data between
702  * user space and kernel space.
703  */
704 static inline int ioctl_standard_call(struct net_device *       dev,
705                                       struct ifreq *            ifr,
706                                       unsigned int              cmd,
707                                       iw_handler                handler)
708 {
709         struct iwreq *                          iwr = (struct iwreq *) ifr;
710         const struct iw_ioctl_description *     descr;
711         struct iw_request_info                  info;
712         int                                     ret = -EINVAL;
713
714         /* Get the description of the IOCTL */
715         if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
716                 return -EOPNOTSUPP;
717         descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
718
719 #ifdef WE_IOCTL_DEBUG
720         printk(KERN_DEBUG "%s (WE) : Found standard handler for 0x%04X\n",
721                ifr->ifr_name, cmd);
722         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);
723 #endif  /* WE_IOCTL_DEBUG */
724
725         /* Prepare the call */
726         info.cmd = cmd;
727         info.flags = 0;
728
729         /* Check if we have a pointer to user space data or not */
730         if(descr->header_type != IW_HEADER_TYPE_POINT) {
731
732                 /* No extra arguments. Trivial to handle */
733                 ret = handler(dev, &info, &(iwr->u), NULL);
734
735 #ifdef WE_SET_EVENT
736                 /* Generate an event to notify listeners of the change */
737                 if((descr->flags & IW_DESCR_FLAG_EVENT) &&
738                    ((ret == 0) || (ret == -EIWCOMMIT)))
739                         wireless_send_event(dev, cmd, &(iwr->u), NULL);
740 #endif  /* WE_SET_EVENT */
741         } else {
742                 char *  extra;
743                 int     extra_size;
744                 int     user_length = 0;
745                 int     err;
746
747                 /* Calculate space needed by arguments. Always allocate
748                  * for max space. Easier, and won't last long... */
749                 extra_size = descr->max_tokens * descr->token_size;
750
751                 /* Check what user space is giving us */
752                 if(IW_IS_SET(cmd)) {
753                         /* Check NULL pointer */
754                         if((iwr->u.data.pointer == NULL) &&
755                            (iwr->u.data.length != 0))
756                                 return -EFAULT;
757                         /* Check if number of token fits within bounds */
758                         if(iwr->u.data.length > descr->max_tokens)
759                                 return -E2BIG;
760                         if(iwr->u.data.length < descr->min_tokens)
761                                 return -EINVAL;
762                 } else {
763                         /* Check NULL pointer */
764                         if(iwr->u.data.pointer == NULL)
765                                 return -EFAULT;
766                         /* Save user space buffer size for checking */
767                         user_length = iwr->u.data.length;
768
769                         /* Don't check if user_length > max to allow forward
770                          * compatibility. The test user_length < min is
771                          * implied by the test at the end. */
772
773                         /* Support for very large requests */
774                         if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
775                            (user_length > descr->max_tokens)) {
776                                 /* Allow userspace to GET more than max so
777                                  * we can support any size GET requests.
778                                  * There is still a limit : -ENOMEM. */
779                                 extra_size = user_length * descr->token_size;
780                                 /* Note : user_length is originally a __u16,
781                                  * and token_size is controlled by us,
782                                  * so extra_size won't get negative and
783                                  * won't overflow... */
784                         }
785                 }
786
787 #ifdef WE_IOCTL_DEBUG
788                 printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
789                        dev->name, extra_size);
790 #endif  /* WE_IOCTL_DEBUG */
791
792                 /* Create the kernel buffer */
793                 extra = kmalloc(extra_size, GFP_KERNEL);
794                 if (extra == NULL) {
795                         return -ENOMEM;
796                 }
797
798                 /* If it is a SET, get all the extra data in here */
799                 if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
800                         err = copy_from_user(extra, iwr->u.data.pointer,
801                                              iwr->u.data.length *
802                                              descr->token_size);
803                         if (err) {
804                                 kfree(extra);
805                                 return -EFAULT;
806                         }
807 #ifdef WE_IOCTL_DEBUG
808                         printk(KERN_DEBUG "%s (WE) : Got %d bytes\n",
809                                dev->name,
810                                iwr->u.data.length * descr->token_size);
811 #endif  /* WE_IOCTL_DEBUG */
812                 }
813
814                 /* Call the handler */
815                 ret = handler(dev, &info, &(iwr->u), extra);
816
817                 /* If we have something to return to the user */
818                 if (!ret && IW_IS_GET(cmd)) {
819                         /* Check if there is enough buffer up there */
820                         if(user_length < iwr->u.data.length) {
821                                 kfree(extra);
822                                 return -E2BIG;
823                         }
824
825                         err = copy_to_user(iwr->u.data.pointer, extra,
826                                            iwr->u.data.length *
827                                            descr->token_size);
828                         if (err)
829                                 ret =  -EFAULT;                            
830 #ifdef WE_IOCTL_DEBUG
831                         printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n",
832                                dev->name,
833                                iwr->u.data.length * descr->token_size);
834 #endif  /* WE_IOCTL_DEBUG */
835                 }
836
837 #ifdef WE_SET_EVENT
838                 /* Generate an event to notify listeners of the change */
839                 if((descr->flags & IW_DESCR_FLAG_EVENT) &&
840                    ((ret == 0) || (ret == -EIWCOMMIT))) {
841                         if(descr->flags & IW_DESCR_FLAG_RESTRICT)
842                                 /* If the event is restricted, don't
843                                  * export the payload */
844                                 wireless_send_event(dev, cmd, &(iwr->u), NULL);
845                         else
846                                 wireless_send_event(dev, cmd, &(iwr->u),
847                                                     extra);
848                 }
849 #endif  /* WE_SET_EVENT */
850
851                 /* Cleanup - I told you it wasn't that long ;-) */
852                 kfree(extra);
853         }
854
855         /* Call commit handler if needed and defined */
856         if(ret == -EIWCOMMIT)
857                 ret = call_commit_handler(dev);
858
859         /* Here, we will generate the appropriate event if needed */
860
861         return ret;
862 }
863
864 /* ---------------------------------------------------------------- */
865 /*
866  * Wrapper to call a private Wireless Extension handler.
867  * We do various checks and also take care of moving data between
868  * user space and kernel space.
869  * It's not as nice and slimline as the standard wrapper. The cause
870  * is struct iw_priv_args, which was not really designed for the
871  * job we are going here.
872  *
873  * IMPORTANT : This function prevent to set and get data on the same
874  * IOCTL and enforce the SET/GET convention. Not doing it would be
875  * far too hairy...
876  * If you need to set and get data at the same time, please don't use
877  * a iw_handler but process it in your ioctl handler (i.e. use the
878  * old driver API).
879  */
880 static inline int ioctl_private_call(struct net_device *        dev,
881                                      struct ifreq *             ifr,
882                                      unsigned int               cmd,
883                                      iw_handler         handler)
884 {
885         struct iwreq *                  iwr = (struct iwreq *) ifr;
886         const struct iw_priv_args *     descr = NULL;
887         struct iw_request_info          info;
888         int                             extra_size = 0;
889         int                             i;
890         int                             ret = -EINVAL;
891
892         /* Get the description of the IOCTL */
893         for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
894                 if(cmd == dev->wireless_handlers->private_args[i].cmd) {
895                         descr = &(dev->wireless_handlers->private_args[i]);
896                         break;
897                 }
898
899 #ifdef WE_IOCTL_DEBUG
900         printk(KERN_DEBUG "%s (WE) : Found private handler for 0x%04X\n",
901                ifr->ifr_name, cmd);
902         if(descr) {
903                 printk(KERN_DEBUG "%s (WE) : Name %s, set %X, get %X\n",
904                        dev->name, descr->name,
905                        descr->set_args, descr->get_args);
906         }
907 #endif  /* WE_IOCTL_DEBUG */
908
909         /* Compute the size of the set/get arguments */
910         if(descr != NULL) {
911                 if(IW_IS_SET(cmd)) {
912                         int     offset = 0;     /* For sub-ioctls */
913                         /* Check for sub-ioctl handler */
914                         if(descr->name[0] == '\0')
915                                 /* Reserve one int for sub-ioctl index */
916                                 offset = sizeof(__u32);
917
918                         /* Size of set arguments */
919                         extra_size = get_priv_size(descr->set_args);
920
921                         /* Does it fits in iwr ? */
922                         if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
923                            ((extra_size + offset) <= IFNAMSIZ))
924                                 extra_size = 0;
925                 } else {
926                         /* Size of get arguments */
927                         extra_size = get_priv_size(descr->get_args);
928
929                         /* Does it fits in iwr ? */
930                         if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
931                            (extra_size <= IFNAMSIZ))
932                                 extra_size = 0;
933                 }
934         }
935
936         /* Prepare the call */
937         info.cmd = cmd;
938         info.flags = 0;
939
940         /* Check if we have a pointer to user space data or not. */
941         if(extra_size == 0) {
942                 /* No extra arguments. Trivial to handle */
943                 ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u));
944         } else {
945                 char *  extra;
946                 int     err;
947
948                 /* Check what user space is giving us */
949                 if(IW_IS_SET(cmd)) {
950                         /* Check NULL pointer */
951                         if((iwr->u.data.pointer == NULL) &&
952                            (iwr->u.data.length != 0))
953                                 return -EFAULT;
954
955                         /* Does it fits within bounds ? */
956                         if(iwr->u.data.length > (descr->set_args &
957                                                  IW_PRIV_SIZE_MASK))
958                                 return -E2BIG;
959                 } else {
960                         /* Check NULL pointer */
961                         if(iwr->u.data.pointer == NULL)
962                                 return -EFAULT;
963                 }
964
965 #ifdef WE_IOCTL_DEBUG
966                 printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
967                        dev->name, extra_size);
968 #endif  /* WE_IOCTL_DEBUG */
969
970                 /* Always allocate for max space. Easier, and won't last
971                  * long... */
972                 extra = kmalloc(extra_size, GFP_KERNEL);
973                 if (extra == NULL) {
974                         return -ENOMEM;
975                 }
976
977                 /* If it is a SET, get all the extra data in here */
978                 if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
979                         err = copy_from_user(extra, iwr->u.data.pointer,
980                                              extra_size);
981                         if (err) {
982                                 kfree(extra);
983                                 return -EFAULT;
984                         }
985 #ifdef WE_IOCTL_DEBUG
986                         printk(KERN_DEBUG "%s (WE) : Got %d elem\n",
987                                dev->name, iwr->u.data.length);
988 #endif  /* WE_IOCTL_DEBUG */
989                 }
990
991                 /* Call the handler */
992                 ret = handler(dev, &info, &(iwr->u), extra);
993
994                 /* If we have something to return to the user */
995                 if (!ret && IW_IS_GET(cmd)) {
996
997                         /* Adjust for the actual length if it's variable,
998                          * avoid leaking kernel bits outside. */
999                         if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) {
1000                                 extra_size = adjust_priv_size(descr->get_args,
1001                                                               &(iwr->u));
1002                         }
1003
1004                         err = copy_to_user(iwr->u.data.pointer, extra,
1005                                            extra_size);
1006                         if (err)
1007                                 ret =  -EFAULT;                            
1008 #ifdef WE_IOCTL_DEBUG
1009                         printk(KERN_DEBUG "%s (WE) : Wrote %d elem\n",
1010                                dev->name, iwr->u.data.length);
1011 #endif  /* WE_IOCTL_DEBUG */
1012                 }
1013
1014                 /* Cleanup - I told you it wasn't that long ;-) */
1015                 kfree(extra);
1016         }
1017
1018
1019         /* Call commit handler if needed and defined */
1020         if(ret == -EIWCOMMIT)
1021                 ret = call_commit_handler(dev);
1022
1023         return ret;
1024 }
1025
1026 /* ---------------------------------------------------------------- */
1027 /*
1028  * Main IOCTl dispatcher. Called from the main networking code
1029  * (dev_ioctl() in net/core/dev.c).
1030  * Check the type of IOCTL and call the appropriate wrapper...
1031  */
1032 int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
1033 {
1034         struct net_device *dev;
1035         iw_handler      handler;
1036
1037         /* Permissions are already checked in dev_ioctl() before calling us.
1038          * The copy_to/from_user() of ifr is also dealt with in there */
1039
1040         /* Make sure the device exist */
1041         if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
1042                 return -ENODEV;
1043
1044         /* A bunch of special cases, then the generic case...
1045          * Note that 'cmd' is already filtered in dev_ioctl() with
1046          * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
1047         switch(cmd) 
1048         {
1049                 case SIOCGIWSTATS:
1050                         /* Get Wireless Stats */
1051                         return dev_iwstats(dev, ifr);
1052
1053                 case SIOCGIWPRIV:
1054                         /* Check if we have some wireless handlers defined */
1055                         if(dev->wireless_handlers != NULL) {
1056                                 /* We export to user space the definition of
1057                                  * the private handler ourselves */
1058                                 return ioctl_export_private(dev, ifr);
1059                         }
1060                         // ## Fall-through for old API ##
1061                 default:
1062                         /* Generic IOCTL */
1063                         /* Basic check */
1064                         if (!netif_device_present(dev))
1065                                 return -ENODEV;
1066                         /* New driver API : try to find the handler */
1067                         handler = get_handler(dev, cmd);
1068                         if(handler != NULL) {
1069                                 /* Standard and private are not the same */
1070                                 if(cmd < SIOCIWFIRSTPRIV)
1071                                         return ioctl_standard_call(dev,
1072                                                                    ifr,
1073                                                                    cmd,
1074                                                                    handler);
1075                                 else
1076                                         return ioctl_private_call(dev,
1077                                                                   ifr,
1078                                                                   cmd,
1079                                                                   handler);
1080                         }
1081                         /* Old driver API : call driver ioctl handler */
1082                         if (dev->do_ioctl) {
1083                                 return dev->do_ioctl(dev, ifr, cmd);
1084                         }
1085                         return -EOPNOTSUPP;
1086         }
1087         /* Not reached */
1088         return -EINVAL;
1089 }
1090
1091 /************************* EVENT PROCESSING *************************/
1092 /*
1093  * Process events generated by the wireless layer or the driver.
1094  * Most often, the event will be propagated through rtnetlink
1095  */
1096
1097 #ifdef WE_EVENT_NETLINK
1098 /* "rtnl" is defined in net/core/rtnetlink.c, but we need it here.
1099  * It is declared in <linux/rtnetlink.h> */
1100
1101 /* ---------------------------------------------------------------- */
1102 /*
1103  * Fill a rtnetlink message with our event data.
1104  * Note that we propage only the specified event and don't dump the
1105  * current wireless config. Dumping the wireless config is far too
1106  * expensive (for each parameter, the driver need to query the hardware).
1107  */
1108 static inline int rtnetlink_fill_iwinfo(struct sk_buff *        skb,
1109                                         struct net_device *     dev,
1110                                         int                     type,
1111                                         char *                  event,
1112                                         int                     event_len)
1113 {
1114         struct ifinfomsg *r;
1115         struct nlmsghdr  *nlh;
1116         unsigned char    *b = skb->tail;
1117
1118         nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(*r));
1119         r = NLMSG_DATA(nlh);
1120         r->ifi_family = AF_UNSPEC;
1121         r->__ifi_pad = 0;
1122         r->ifi_type = dev->type;
1123         r->ifi_index = dev->ifindex;
1124         r->ifi_flags = dev->flags;
1125         r->ifi_change = 0;      /* Wireless changes don't affect those flags */
1126
1127         /* Add the wireless events in the netlink packet */
1128         RTA_PUT(skb, IFLA_WIRELESS,
1129                 event_len, event);
1130
1131         nlh->nlmsg_len = skb->tail - b;
1132         return skb->len;
1133
1134 nlmsg_failure:
1135 rtattr_failure:
1136         skb_trim(skb, b - skb->data);
1137         return -1;
1138 }
1139
1140 /* ---------------------------------------------------------------- */
1141 /*
1142  * Create and broadcast and send it on the standard rtnetlink socket
1143  * This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c
1144  * Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field
1145  * within a RTM_NEWLINK event.
1146  */
1147 static inline void rtmsg_iwinfo(struct net_device *     dev,
1148                                 char *                  event,
1149                                 int                     event_len)
1150 {
1151         struct sk_buff *skb;
1152         int size = NLMSG_GOODSIZE;
1153
1154         skb = alloc_skb(size, GFP_ATOMIC);
1155         if (!skb)
1156                 return;
1157
1158         if (rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK,
1159                                   event, event_len) < 0) {
1160                 kfree_skb(skb);
1161                 return;
1162         }
1163         NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
1164         netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
1165 }
1166 #endif  /* WE_EVENT_NETLINK */
1167
1168 /* ---------------------------------------------------------------- */
1169 /*
1170  * Main event dispatcher. Called from other parts and drivers.
1171  * Send the event on the appropriate channels.
1172  * May be called from interrupt context.
1173  */
1174 void wireless_send_event(struct net_device *    dev,
1175                          unsigned int           cmd,
1176                          union iwreq_data *     wrqu,
1177                          char *                 extra)
1178 {
1179         const struct iw_ioctl_description *     descr = NULL;
1180         int extra_len = 0;
1181         struct iw_event  *event;                /* Mallocated whole event */
1182         int event_len;                          /* Its size */
1183         int hdr_len;                            /* Size of the event header */
1184         int wrqu_off = 0;                       /* Offset in wrqu */
1185         /* Don't "optimise" the following variable, it will crash */
1186         unsigned        cmd_index;              /* *MUST* be unsigned */
1187
1188         /* Get the description of the Event */
1189         if(cmd <= SIOCIWLAST) {
1190                 cmd_index = cmd - SIOCIWFIRST;
1191                 if(cmd_index < standard_ioctl_num)
1192                         descr = &(standard_ioctl[cmd_index]);
1193         } else {
1194                 cmd_index = cmd - IWEVFIRST;
1195                 if(cmd_index < standard_event_num)
1196                         descr = &(standard_event[cmd_index]);
1197         }
1198         /* Don't accept unknown events */
1199         if(descr == NULL) {
1200                 /* Note : we don't return an error to the driver, because
1201                  * the driver would not know what to do about it. It can't
1202                  * return an error to the user, because the event is not
1203                  * initiated by a user request.
1204                  * The best the driver could do is to log an error message.
1205                  * We will do it ourselves instead...
1206                  */
1207                 printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
1208                        dev->name, cmd);
1209                 return;
1210         }
1211 #ifdef WE_EVENT_DEBUG
1212         printk(KERN_DEBUG "%s (WE) : Got event 0x%04X\n",
1213                dev->name, cmd);
1214         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);
1215 #endif  /* WE_EVENT_DEBUG */
1216
1217         /* Check extra parameters and set extra_len */
1218         if(descr->header_type == IW_HEADER_TYPE_POINT) {
1219                 /* Check if number of token fits within bounds */
1220                 if(wrqu->data.length > descr->max_tokens) {
1221                         printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length);
1222                         return;
1223                 }
1224                 if(wrqu->data.length < descr->min_tokens) {
1225                         printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length);
1226                         return;
1227                 }
1228                 /* Calculate extra_len - extra is NULL for restricted events */
1229                 if(extra != NULL)
1230                         extra_len = wrqu->data.length * descr->token_size;
1231                 /* Always at an offset in wrqu */
1232                 wrqu_off = IW_EV_POINT_OFF;
1233 #ifdef WE_EVENT_DEBUG
1234                 printk(KERN_DEBUG "%s (WE) : Event 0x%04X, tokens %d, extra_len %d\n", dev->name, cmd, wrqu->data.length, extra_len);
1235 #endif  /* WE_EVENT_DEBUG */
1236         }
1237
1238         /* Total length of the event */
1239         hdr_len = event_type_size[descr->header_type];
1240         event_len = hdr_len + extra_len;
1241
1242 #ifdef WE_EVENT_DEBUG
1243         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);
1244 #endif  /* WE_EVENT_DEBUG */
1245
1246         /* Create temporary buffer to hold the event */
1247         event = kmalloc(event_len, GFP_ATOMIC);
1248         if(event == NULL)
1249                 return;
1250
1251         /* Fill event */
1252         event->len = event_len;
1253         event->cmd = cmd;
1254         memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
1255         if(extra != NULL)
1256                 memcpy(((char *) event) + hdr_len, extra, extra_len);
1257
1258 #ifdef WE_EVENT_NETLINK
1259         /* rtnetlink event channel */
1260         rtmsg_iwinfo(dev, (char *) event, event_len);
1261 #endif  /* WE_EVENT_NETLINK */
1262
1263         /* Cleanup */
1264         kfree(event);
1265
1266         return;         /* Always success, I guess ;-) */
1267 }
1268
1269 /********************** ENHANCED IWSPY SUPPORT **********************/
1270 /*
1271  * In the old days, the driver was handling spy support all by itself.
1272  * Now, the driver can delegate this task to Wireless Extensions.
1273  * It needs to use those standard spy iw_handler in struct iw_handler_def,
1274  * push data to us via wireless_spy_update() and include struct iw_spy_data
1275  * in its private part (and export it in net_device->wireless_data->spy_data).
1276  * One of the main advantage of centralising spy support here is that
1277  * it becomes much easier to improve and extend it without having to touch
1278  * the drivers. One example is the addition of the Spy-Threshold events.
1279  */
1280
1281 /* ---------------------------------------------------------------- */
1282 /*
1283  * Return the pointer to the spy data in the driver.
1284  * Because this is called on the Rx path via wireless_spy_update(),
1285  * we want it to be efficient...
1286  */
1287 static inline struct iw_spy_data * get_spydata(struct net_device *dev)
1288 {
1289         /* This is the new way */
1290         if(dev->wireless_data)
1291                 return(dev->wireless_data->spy_data);
1292         return NULL;
1293 }
1294
1295 /*------------------------------------------------------------------*/
1296 /*
1297  * Standard Wireless Handler : set Spy List
1298  */
1299 int iw_handler_set_spy(struct net_device *      dev,
1300                        struct iw_request_info * info,
1301                        union iwreq_data *       wrqu,
1302                        char *                   extra)
1303 {
1304         struct iw_spy_data *    spydata = get_spydata(dev);
1305         struct sockaddr *       address = (struct sockaddr *) extra;
1306
1307         /* Make sure driver is not buggy or using the old API */
1308         if(!spydata)
1309                 return -EOPNOTSUPP;
1310
1311         /* Disable spy collection while we copy the addresses.
1312          * While we copy addresses, any call to wireless_spy_update()
1313          * will NOP. This is OK, as anyway the addresses are changing. */
1314         spydata->spy_number = 0;
1315
1316         /* We want to operate without locking, because wireless_spy_update()
1317          * most likely will happen in the interrupt handler, and therefore
1318          * have its own locking constraints and needs performance.
1319          * The rtnl_lock() make sure we don't race with the other iw_handlers.
1320          * This make sure wireless_spy_update() "see" that the spy list
1321          * is temporarily disabled. */
1322         wmb();
1323
1324         /* Are there are addresses to copy? */
1325         if(wrqu->data.length > 0) {
1326                 int i;
1327
1328                 /* Copy addresses */
1329                 for(i = 0; i < wrqu->data.length; i++)
1330                         memcpy(spydata->spy_address[i], address[i].sa_data,
1331                                ETH_ALEN);
1332                 /* Reset stats */
1333                 memset(spydata->spy_stat, 0,
1334                        sizeof(struct iw_quality) * IW_MAX_SPY);
1335
1336 #ifdef WE_SPY_DEBUG
1337                 printk(KERN_DEBUG "iw_handler_set_spy() :  wireless_data %p, spydata %p, num %d\n", dev->wireless_data, spydata, wrqu->data.length);
1338                 for (i = 0; i < wrqu->data.length; i++)
1339                         printk(KERN_DEBUG
1340                                "%02X:%02X:%02X:%02X:%02X:%02X \n",
1341                                spydata->spy_address[i][0],
1342                                spydata->spy_address[i][1],
1343                                spydata->spy_address[i][2],
1344                                spydata->spy_address[i][3],
1345                                spydata->spy_address[i][4],
1346                                spydata->spy_address[i][5]);
1347 #endif  /* WE_SPY_DEBUG */
1348         }
1349
1350         /* Make sure above is updated before re-enabling */
1351         wmb();
1352
1353         /* Enable addresses */
1354         spydata->spy_number = wrqu->data.length;
1355
1356         return 0;
1357 }
1358
1359 /*------------------------------------------------------------------*/
1360 /*
1361  * Standard Wireless Handler : get Spy List
1362  */
1363 int iw_handler_get_spy(struct net_device *      dev,
1364                        struct iw_request_info * info,
1365                        union iwreq_data *       wrqu,
1366                        char *                   extra)
1367 {
1368         struct iw_spy_data *    spydata = get_spydata(dev);
1369         struct sockaddr *       address = (struct sockaddr *) extra;
1370         int                     i;
1371
1372         /* Make sure driver is not buggy or using the old API */
1373         if(!spydata)
1374                 return -EOPNOTSUPP;
1375
1376         wrqu->data.length = spydata->spy_number;
1377
1378         /* Copy addresses. */
1379         for(i = 0; i < spydata->spy_number; i++)        {
1380                 memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
1381                 address[i].sa_family = AF_UNIX;
1382         }
1383         /* Copy stats to the user buffer (just after). */
1384         if(spydata->spy_number > 0)
1385                 memcpy(extra  + (sizeof(struct sockaddr) *spydata->spy_number),
1386                        spydata->spy_stat,
1387                        sizeof(struct iw_quality) * spydata->spy_number);
1388         /* Reset updated flags. */
1389         for(i = 0; i < spydata->spy_number; i++)
1390                 spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED;
1391         return 0;
1392 }
1393
1394 /*------------------------------------------------------------------*/
1395 /*
1396  * Standard Wireless Handler : set spy threshold
1397  */
1398 int iw_handler_set_thrspy(struct net_device *   dev,
1399                           struct iw_request_info *info,
1400                           union iwreq_data *    wrqu,
1401                           char *                extra)
1402 {
1403         struct iw_spy_data *    spydata = get_spydata(dev);
1404         struct iw_thrspy *      threshold = (struct iw_thrspy *) extra;
1405
1406         /* Make sure driver is not buggy or using the old API */
1407         if(!spydata)
1408                 return -EOPNOTSUPP;
1409
1410         /* Just do it */
1411         memcpy(&(spydata->spy_thr_low), &(threshold->low),
1412                2 * sizeof(struct iw_quality));
1413
1414         /* Clear flag */
1415         memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
1416
1417 #ifdef WE_SPY_DEBUG
1418         printk(KERN_DEBUG "iw_handler_set_thrspy() :  low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level);
1419 #endif  /* WE_SPY_DEBUG */
1420
1421         return 0;
1422 }
1423
1424 /*------------------------------------------------------------------*/
1425 /*
1426  * Standard Wireless Handler : get spy threshold
1427  */
1428 int iw_handler_get_thrspy(struct net_device *   dev,
1429                           struct iw_request_info *info,
1430                           union iwreq_data *    wrqu,
1431                           char *                extra)
1432 {
1433         struct iw_spy_data *    spydata = get_spydata(dev);
1434         struct iw_thrspy *      threshold = (struct iw_thrspy *) extra;
1435
1436         /* Make sure driver is not buggy or using the old API */
1437         if(!spydata)
1438                 return -EOPNOTSUPP;
1439
1440         /* Just do it */
1441         memcpy(&(threshold->low), &(spydata->spy_thr_low),
1442                2 * sizeof(struct iw_quality));
1443
1444         return 0;
1445 }
1446
1447 /*------------------------------------------------------------------*/
1448 /*
1449  * Prepare and send a Spy Threshold event
1450  */
1451 static void iw_send_thrspy_event(struct net_device *    dev,
1452                                  struct iw_spy_data *   spydata,
1453                                  unsigned char *        address,
1454                                  struct iw_quality *    wstats)
1455 {
1456         union iwreq_data        wrqu;
1457         struct iw_thrspy        threshold;
1458
1459         /* Init */
1460         wrqu.data.length = 1;
1461         wrqu.data.flags = 0;
1462         /* Copy address */
1463         memcpy(threshold.addr.sa_data, address, ETH_ALEN);
1464         threshold.addr.sa_family = ARPHRD_ETHER;
1465         /* Copy stats */
1466         memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
1467         /* Copy also thresholds */
1468         memcpy(&(threshold.low), &(spydata->spy_thr_low),
1469                2 * sizeof(struct iw_quality));
1470
1471 #ifdef WE_SPY_DEBUG
1472         printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n",
1473                threshold.addr.sa_data[0],
1474                threshold.addr.sa_data[1],
1475                threshold.addr.sa_data[2],
1476                threshold.addr.sa_data[3],
1477                threshold.addr.sa_data[4],
1478                threshold.addr.sa_data[5], threshold.qual.level);
1479 #endif  /* WE_SPY_DEBUG */
1480
1481         /* Send event to user space */
1482         wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
1483 }
1484
1485 /* ---------------------------------------------------------------- */
1486 /*
1487  * Call for the driver to update the spy data.
1488  * For now, the spy data is a simple array. As the size of the array is
1489  * small, this is good enough. If we wanted to support larger number of
1490  * spy addresses, we should use something more efficient...
1491  */
1492 void wireless_spy_update(struct net_device *    dev,
1493                          unsigned char *        address,
1494                          struct iw_quality *    wstats)
1495 {
1496         struct iw_spy_data *    spydata = get_spydata(dev);
1497         int                     i;
1498         int                     match = -1;
1499
1500         /* Make sure driver is not buggy or using the old API */
1501         if(!spydata)
1502                 return;
1503
1504 #ifdef WE_SPY_DEBUG
1505         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]);
1506 #endif  /* WE_SPY_DEBUG */
1507
1508         /* Update all records that match */
1509         for(i = 0; i < spydata->spy_number; i++)
1510                 if(!compare_ether_addr(address, spydata->spy_address[i])) {
1511                         memcpy(&(spydata->spy_stat[i]), wstats,
1512                                sizeof(struct iw_quality));
1513                         match = i;
1514                 }
1515
1516         /* Generate an event if we cross the spy threshold.
1517          * To avoid event storms, we have a simple hysteresis : we generate
1518          * event only when we go under the low threshold or above the
1519          * high threshold. */
1520         if(match >= 0) {
1521                 if(spydata->spy_thr_under[match]) {
1522                         if(wstats->level > spydata->spy_thr_high.level) {
1523                                 spydata->spy_thr_under[match] = 0;
1524                                 iw_send_thrspy_event(dev, spydata,
1525                                                      address, wstats);
1526                         }
1527                 } else {
1528                         if(wstats->level < spydata->spy_thr_low.level) {
1529                                 spydata->spy_thr_under[match] = 1;
1530                                 iw_send_thrspy_event(dev, spydata,
1531                                                      address, wstats);
1532                         }
1533                 }
1534         }
1535 }
1536
1537 EXPORT_SYMBOL(iw_handler_get_spy);
1538 EXPORT_SYMBOL(iw_handler_get_thrspy);
1539 EXPORT_SYMBOL(iw_handler_set_spy);
1540 EXPORT_SYMBOL(iw_handler_set_thrspy);
1541 EXPORT_SYMBOL(wireless_send_event);
1542 EXPORT_SYMBOL(wireless_spy_update);