import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.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-2002 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
48 /***************************** INCLUDES *****************************/
49
50 #include <asm/uaccess.h>                /* copy_to_user() */
51 #include <linux/config.h>               /* Not needed ??? */
52 #include <linux/types.h>                /* off_t */
53 #include <linux/netdevice.h>            /* struct ifreq, dev_get_by_name() */
54 #include <linux/rtnetlink.h>            /* rtnetlink stuff */
55
56 #include <linux/wireless.h>             /* Pretty obvious */
57 #include <net/iw_handler.h>             /* New driver API */
58
59 /**************************** CONSTANTS ****************************/
60
61 /* Enough lenience, let's make sure things are proper... */
62 #define WE_STRICT_WRITE         /* Check write buffer size */
63 /* I'll probably drop both the define and kernel message in the next version */
64
65 /* Debuging stuff */
66 #undef WE_IOCTL_DEBUG           /* Debug IOCTL API */
67 #undef WE_EVENT_DEBUG           /* Debug Event dispatcher */
68
69 /* Options */
70 #define WE_EVENT_NETLINK        /* Propagate events using rtnetlink */
71 #define WE_SET_EVENT            /* Generate an event on some set commands */
72
73 /************************* GLOBAL VARIABLES *************************/
74 /*
75  * You should not use global variables, because or re-entrancy.
76  * On our case, it's only const, so it's OK...
77  */
78 /*
79  * Meta-data about all the standard Wireless Extension request we
80  * know about.
81  */
82 static const struct iw_ioctl_description        standard_ioctl[] = {
83         /* SIOCSIWCOMMIT */
84         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
85         /* SIOCGIWNAME */
86         { IW_HEADER_TYPE_CHAR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
87         /* SIOCSIWNWID */
88         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
89         /* SIOCGIWNWID */
90         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
91         /* SIOCSIWFREQ */
92         { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
93         /* SIOCGIWFREQ */
94         { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
95         /* SIOCSIWMODE */
96         { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
97         /* SIOCGIWMODE */
98         { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
99         /* SIOCSIWSENS */
100         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
101         /* SIOCGIWSENS */
102         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
103         /* SIOCSIWRANGE */
104         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
105         /* SIOCGIWRANGE */
106         { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_range), IW_DESCR_FLAG_DUMP},
107         /* SIOCSIWPRIV */
108         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
109         /* SIOCGIWPRIV (handled directly by us) */
110         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
111         /* SIOCSIWSTATS */
112         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
113         /* SIOCGIWSTATS (handled directly by us) */
114         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
115         /* SIOCSIWSPY */
116         { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
117         /* SIOCGIWSPY */
118         { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0},
119         /* -- hole -- */
120         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
121         /* -- hole -- */
122         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
123         /* SIOCSIWAP */
124         { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
125         /* SIOCGIWAP */
126         { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
127         /* -- hole -- */
128         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
129         /* SIOCGIWAPLIST */
130         { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
131         /* SIOCSIWSCAN */
132         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
133         /* SIOCGIWSCAN */
134         { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0},
135         /* SIOCSIWESSID */
136         { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT},
137         /* SIOCGIWESSID */
138         { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_DUMP},
139         /* SIOCSIWNICKN */
140         { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0},
141         /* SIOCGIWNICKN */
142         { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0},
143         /* -- hole -- */
144         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
145         /* -- hole -- */
146         { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
147         /* SIOCSIWRATE */
148         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
149         /* SIOCGIWRATE */
150         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
151         /* SIOCSIWRTS */
152         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
153         /* SIOCGIWRTS */
154         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
155         /* SIOCSIWFRAG */
156         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
157         /* SIOCGIWFRAG */
158         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
159         /* SIOCSIWTXPOW */
160         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
161         /* SIOCGIWTXPOW */
162         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
163         /* SIOCSIWRETRY */
164         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
165         /* SIOCGIWRETRY */
166         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
167         /* SIOCSIWENCODE */
168         { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT},
169         /* SIOCGIWENCODE */
170         { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT},
171         /* SIOCSIWPOWER */
172         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
173         /* SIOCGIWPOWER */
174         { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
175 };
176 static const int standard_ioctl_num = (sizeof(standard_ioctl) /
177                                        sizeof(struct iw_ioctl_description));
178
179 /*
180  * Meta-data about all the additional standard Wireless Extension events
181  * we know about.
182  */
183 static const struct iw_ioctl_description        standard_event[] = {
184         /* IWEVTXDROP */
185         { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
186         /* IWEVQUAL */
187         { IW_HEADER_TYPE_QUAL, 0, 0, 0, 0, 0},
188         /* IWEVCUSTOM */
189         { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_CUSTOM_MAX, 0},
190         /* IWEVREGISTERED */
191         { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
192         /* IWEVEXPIRED */
193         { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
194 };
195 static const int standard_event_num = (sizeof(standard_event) /
196                                        sizeof(struct iw_ioctl_description));
197
198 /* Size (in bytes) of the various private data types */
199 static const char priv_type_size[] = {
200         0,                              /* IW_PRIV_TYPE_NONE */
201         1,                              /* IW_PRIV_TYPE_BYTE */
202         1,                              /* IW_PRIV_TYPE_CHAR */
203         0,                              /* Not defined */
204         sizeof(__u32),                  /* IW_PRIV_TYPE_INT */
205         sizeof(struct iw_freq),         /* IW_PRIV_TYPE_FLOAT */
206         sizeof(struct sockaddr),        /* IW_PRIV_TYPE_ADDR */
207         0,                              /* Not defined */
208 };
209
210 /* Size (in bytes) of various events */
211 static const int event_type_size[] = {
212         IW_EV_LCP_LEN,                  /* IW_HEADER_TYPE_NULL */
213         0,
214         IW_EV_CHAR_LEN,                 /* IW_HEADER_TYPE_CHAR */
215         0,
216         IW_EV_UINT_LEN,                 /* IW_HEADER_TYPE_UINT */
217         IW_EV_FREQ_LEN,                 /* IW_HEADER_TYPE_FREQ */
218         IW_EV_ADDR_LEN,                 /* IW_HEADER_TYPE_ADDR */
219         0,
220         IW_EV_POINT_LEN,                /* Without variable payload */
221         IW_EV_PARAM_LEN,                /* IW_HEADER_TYPE_PARAM */
222         IW_EV_QUAL_LEN,                 /* IW_HEADER_TYPE_QUAL */
223 };
224
225 /************************ COMMON SUBROUTINES ************************/
226 /*
227  * Stuff that may be used in various place or doesn't fit in one
228  * of the section below.
229  */
230
231 /* ---------------------------------------------------------------- */
232 /*
233  * Return the driver handler associated with a specific Wireless Extension.
234  * Called from various place, so make sure it remains efficient.
235  */
236 static inline iw_handler get_handler(struct net_device *dev,
237                                      unsigned int cmd)
238 {
239         /* Don't "optimise" the following variable, it will crash */
240         unsigned int    index;          /* *MUST* be unsigned */
241
242         /* Check if we have some wireless handlers defined */
243         if(dev->wireless_handlers == NULL)
244                 return NULL;
245
246         /* Try as a standard command */
247         index = cmd - SIOCIWFIRST;
248         if(index < dev->wireless_handlers->num_standard)
249                 return dev->wireless_handlers->standard[index];
250
251         /* Try as a private command */
252         index = cmd - SIOCIWFIRSTPRIV;
253         if(index < dev->wireless_handlers->num_private)
254                 return dev->wireless_handlers->private[index];
255
256         /* Not found */
257         return NULL;
258 }
259
260 /* ---------------------------------------------------------------- */
261 /*
262  * Get statistics out of the driver
263  */
264 static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
265 {
266         return (dev->get_wireless_stats ?
267                 dev->get_wireless_stats(dev) :
268                 (struct iw_statistics *) NULL);
269         /* In the future, get_wireless_stats may move from 'struct net_device'
270          * to 'struct iw_handler_def', to de-bloat struct net_device.
271          * Definitely worse a thought... */
272 }
273
274 /* ---------------------------------------------------------------- */
275 /*
276  * Call the commit handler in the driver
277  * (if exist and if conditions are right)
278  *
279  * Note : our current commit strategy is currently pretty dumb,
280  * but we will be able to improve on that...
281  * The goal is to try to agreagate as many changes as possible
282  * before doing the commit. Drivers that will define a commit handler
283  * are usually those that need a reset after changing parameters, so
284  * we want to minimise the number of reset.
285  * A cool idea is to use a timer : at each "set" command, we re-set the
286  * timer, when the timer eventually fires, we call the driver.
287  * Hopefully, more on that later.
288  *
289  * Also, I'm waiting to see how many people will complain about the
290  * netif_running(dev) test. I'm open on that one...
291  * Hopefully, the driver will remember to do a commit in "open()" ;-)
292  */
293 static inline int call_commit_handler(struct net_device *       dev)
294 {
295         if((netif_running(dev)) &&
296            (dev->wireless_handlers->standard[0] != NULL)) {
297                 /* Call the commit handler on the driver */
298                 return dev->wireless_handlers->standard[0](dev, NULL,
299                                                            NULL, NULL);
300         } else
301                 return 0;               /* Command completed successfully */
302 }
303
304 /* ---------------------------------------------------------------- */
305 /*
306  * Number of private arguments
307  */
308 static inline int get_priv_size(__u16   args)
309 {
310         int     num = args & IW_PRIV_SIZE_MASK;
311         int     type = (args & IW_PRIV_TYPE_MASK) >> 12;
312
313         return num * priv_type_size[type];
314 }
315
316
317 /******************** /proc/net/wireless SUPPORT ********************/
318 /*
319  * The /proc/net/wireless file is a human readable user-space interface
320  * exporting various wireless specific statistics from the wireless devices.
321  * This is the most popular part of the Wireless Extensions ;-)
322  *
323  * This interface is a pure clone of /proc/net/dev (in net/core/dev.c).
324  * The content of the file is basically the content of "struct iw_statistics".
325  */
326
327 #ifdef CONFIG_PROC_FS
328
329 /* ---------------------------------------------------------------- */
330 /*
331  * Print one entry (line) of /proc/net/wireless
332  */
333 static inline int sprintf_wireless_stats(char *buffer, struct net_device *dev)
334 {
335         /* Get stats from the driver */
336         struct iw_statistics *stats;
337         int size;
338
339         stats = get_wireless_stats(dev);
340         if (stats != (struct iw_statistics *) NULL) {
341                 size = sprintf(buffer,
342                                "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d %6d %6d   %6d\n",
343                                dev->name,
344                                stats->status,
345                                stats->qual.qual,
346                                stats->qual.updated & 1 ? '.' : ' ',
347                                ((__u8) stats->qual.level),
348                                stats->qual.updated & 2 ? '.' : ' ',
349                                ((__u8) stats->qual.noise),
350                                stats->qual.updated & 4 ? '.' : ' ',
351                                stats->discard.nwid,
352                                stats->discard.code,
353                                stats->discard.fragment,
354                                stats->discard.retries,
355                                stats->discard.misc,
356                                stats->miss.beacon);
357                 stats->qual.updated = 0;
358         }
359         else
360                 size = 0;
361
362         return size;
363 }
364
365 /* ---------------------------------------------------------------- */
366 /*
367  * Print info for /proc/net/wireless (print all entries)
368  */
369 int dev_get_wireless_info(char * buffer, char **start, off_t offset,
370                           int length)
371 {
372         int             len = 0;
373         off_t           begin = 0;
374         off_t           pos = 0;
375         int             size;
376         
377         struct net_device *     dev;
378
379         size = sprintf(buffer,
380                        "Inter-| sta-|   Quality        |   Discarded packets               | Missed\n"
381                        " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon\n"
382                         );
383         
384         pos += size;
385         len += size;
386
387         read_lock(&dev_base_lock);
388         for (dev = dev_base; dev != NULL; dev = dev->next) {
389                 size = sprintf_wireless_stats(buffer + len, dev);
390                 len += size;
391                 pos = begin + len;
392
393                 if (pos < offset) {
394                         len = 0;
395                         begin = pos;
396                 }
397                 if (pos > offset + length)
398                         break;
399         }
400         read_unlock(&dev_base_lock);
401
402         *start = buffer + (offset - begin);     /* Start of wanted data */
403         len -= (offset - begin);                /* Start slop */
404         if (len > length)
405                 len = length;                   /* Ending slop */
406         if (len < 0)
407                 len = 0;
408
409         return len;
410 }
411 #endif  /* CONFIG_PROC_FS */
412
413 /************************** IOCTL SUPPORT **************************/
414 /*
415  * The original user space API to configure all those Wireless Extensions
416  * is through IOCTLs.
417  * In there, we check if we need to call the new driver API (iw_handler)
418  * or just call the driver ioctl handler.
419  */
420
421 /* ---------------------------------------------------------------- */
422 /*
423  *      Allow programatic access to /proc/net/wireless even if /proc
424  *      doesn't exist... Also more efficient...
425  */
426 static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
427 {
428         /* Get stats from the driver */
429         struct iw_statistics *stats;
430
431         stats = get_wireless_stats(dev);
432         if (stats != (struct iw_statistics *) NULL) {
433                 struct iwreq *  wrq = (struct iwreq *)ifr;
434
435                 /* Copy statistics to the user buffer */
436                 if(copy_to_user(wrq->u.data.pointer, stats,
437                                 sizeof(struct iw_statistics)))
438                         return -EFAULT;
439
440                 /* Check if we need to clear the update flag */
441                 if(wrq->u.data.flags != 0)
442                         stats->qual.updated = 0;
443                 return 0;
444         } else
445                 return -EOPNOTSUPP;
446 }
447
448 /* ---------------------------------------------------------------- */
449 /*
450  * Export the driver private handler definition
451  * They will be picked up by tools like iwpriv...
452  */
453 static inline int ioctl_export_private(struct net_device *      dev,
454                                        struct ifreq *           ifr)
455 {
456         struct iwreq *                          iwr = (struct iwreq *) ifr;
457
458         /* Check if the driver has something to export */
459         if((dev->wireless_handlers->num_private_args == 0) ||
460            (dev->wireless_handlers->private_args == NULL))
461                 return -EOPNOTSUPP;
462
463         /* Check NULL pointer */
464         if(iwr->u.data.pointer == NULL)
465                 return -EFAULT;
466 #ifdef WE_STRICT_WRITE
467         /* Check if there is enough buffer up there */
468         if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
469                 printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.data.length, dev->wireless_handlers->num_private_args);
470                 return -E2BIG;
471         }
472 #endif  /* WE_STRICT_WRITE */
473
474         /* Set the number of available ioctls. */
475         iwr->u.data.length = dev->wireless_handlers->num_private_args;
476
477         /* Copy structure to the user buffer. */
478         if (copy_to_user(iwr->u.data.pointer,
479                          dev->wireless_handlers->private_args,
480                          sizeof(struct iw_priv_args) * iwr->u.data.length))
481                 return -EFAULT;
482
483         return 0;
484 }
485
486 /* ---------------------------------------------------------------- */
487 /*
488  * Wrapper to call a standard Wireless Extension handler.
489  * We do various checks and also take care of moving data between
490  * user space and kernel space.
491  */
492 static inline int ioctl_standard_call(struct net_device *       dev,
493                                       struct ifreq *            ifr,
494                                       unsigned int              cmd,
495                                       iw_handler                handler)
496 {
497         struct iwreq *                          iwr = (struct iwreq *) ifr;
498         const struct iw_ioctl_description *     descr;
499         struct iw_request_info                  info;
500         int                                     ret = -EINVAL;
501         int                                     user_size = 0;
502
503         /* Get the description of the IOCTL */
504         if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
505                 return -EOPNOTSUPP;
506         descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
507
508 #ifdef WE_IOCTL_DEBUG
509         printk(KERN_DEBUG "%s (WE) : Found standard handler for 0x%04X\n",
510                ifr->ifr_name, cmd);
511         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);
512 #endif  /* WE_IOCTL_DEBUG */
513
514         /* Prepare the call */
515         info.cmd = cmd;
516         info.flags = 0;
517
518         /* Check if we have a pointer to user space data or not */
519         if(descr->header_type != IW_HEADER_TYPE_POINT) {
520
521                 /* No extra arguments. Trivial to handle */
522                 ret = handler(dev, &info, &(iwr->u), NULL);
523
524 #ifdef WE_SET_EVENT
525                 /* Generate an event to notify listeners of the change */
526                 if((descr->flags & IW_DESCR_FLAG_EVENT) &&
527                    ((ret == 0) || (ret == -EIWCOMMIT)))
528                         wireless_send_event(dev, cmd, &(iwr->u), NULL);
529 #endif  /* WE_SET_EVENT */
530         } else {
531                 char *  extra;
532                 int     err;
533
534                 /* Check what user space is giving us */
535                 if(IW_IS_SET(cmd)) {
536                         /* Check NULL pointer */
537                         if((iwr->u.data.pointer == NULL) &&
538                            (iwr->u.data.length != 0))
539                                 return -EFAULT;
540                         /* Check if number of token fits within bounds */
541                         if(iwr->u.data.length > descr->max_tokens)
542                                 return -E2BIG;
543                         if(iwr->u.data.length < descr->min_tokens)
544                                 return -EINVAL;
545                 } else {
546                         /* Check NULL pointer */
547                         if(iwr->u.data.pointer == NULL)
548                                 return -EFAULT;
549                         /* Save user space buffer size for checking */
550                         user_size = iwr->u.data.length;
551                 }
552
553 #ifdef WE_IOCTL_DEBUG
554                 printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
555                        dev->name, descr->max_tokens * descr->token_size);
556 #endif  /* WE_IOCTL_DEBUG */
557
558                 /* Always allocate for max space. Easier, and won't last
559                  * long... */
560                 extra = kmalloc(descr->max_tokens * descr->token_size,
561                                 GFP_KERNEL);
562                 if (extra == NULL) {
563                         return -ENOMEM;
564                 }
565
566                 /* If it is a SET, get all the extra data in here */
567                 if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
568                         err = copy_from_user(extra, iwr->u.data.pointer,
569                                              iwr->u.data.length *
570                                              descr->token_size);
571                         if (err) {
572                                 kfree(extra);
573                                 return -EFAULT;
574                         }
575 #ifdef WE_IOCTL_DEBUG
576                         printk(KERN_DEBUG "%s (WE) : Got %d bytes\n",
577                                dev->name,
578                                iwr->u.data.length * descr->token_size);
579 #endif  /* WE_IOCTL_DEBUG */
580                 }
581
582                 /* Call the handler */
583                 ret = handler(dev, &info, &(iwr->u), extra);
584
585                 /* If we have something to return to the user */
586                 if (!ret && IW_IS_GET(cmd)) {
587 #ifdef WE_STRICT_WRITE
588                         /* Check if there is enough buffer up there */
589                         if(user_size < iwr->u.data.length) {
590                                 printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length);
591                                 kfree(extra);
592                                 return -E2BIG;
593                         }
594 #endif  /* WE_STRICT_WRITE */
595
596                         err = copy_to_user(iwr->u.data.pointer, extra,
597                                            iwr->u.data.length *
598                                            descr->token_size);
599                         if (err)
600                                 ret =  -EFAULT;                            
601 #ifdef WE_IOCTL_DEBUG
602                         printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n",
603                                dev->name,
604                                iwr->u.data.length * descr->token_size);
605 #endif  /* WE_IOCTL_DEBUG */
606                 }
607
608 #ifdef WE_SET_EVENT
609                 /* Generate an event to notify listeners of the change */
610                 if((descr->flags & IW_DESCR_FLAG_EVENT) &&
611                    ((ret == 0) || (ret == -EIWCOMMIT))) {
612                         if(descr->flags & IW_DESCR_FLAG_RESTRICT)
613                                 /* If the event is restricted, don't
614                                  * export the payload */
615                                 wireless_send_event(dev, cmd, &(iwr->u), NULL);
616                         else
617                                 wireless_send_event(dev, cmd, &(iwr->u),
618                                                     extra);
619                 }
620 #endif  /* WE_SET_EVENT */
621
622                 /* Cleanup - I told you it wasn't that long ;-) */
623                 kfree(extra);
624         }
625
626         /* Call commit handler if needed and defined */
627         if(ret == -EIWCOMMIT)
628                 ret = call_commit_handler(dev);
629
630         /* Here, we will generate the appropriate event if needed */
631
632         return ret;
633 }
634
635 /* ---------------------------------------------------------------- */
636 /*
637  * Wrapper to call a private Wireless Extension handler.
638  * We do various checks and also take care of moving data between
639  * user space and kernel space.
640  * It's not as nice and slimline as the standard wrapper. The cause
641  * is struct iw_priv_args, which was not really designed for the
642  * job we are going here.
643  *
644  * IMPORTANT : This function prevent to set and get data on the same
645  * IOCTL and enforce the SET/GET convention. Not doing it would be
646  * far too hairy...
647  * If you need to set and get data at the same time, please don't use
648  * a iw_handler but process it in your ioctl handler (i.e. use the
649  * old driver API).
650  */
651 static inline int ioctl_private_call(struct net_device *        dev,
652                                      struct ifreq *             ifr,
653                                      unsigned int               cmd,
654                                      iw_handler         handler)
655 {
656         struct iwreq *                  iwr = (struct iwreq *) ifr;
657         struct iw_priv_args *           descr = NULL;
658         struct iw_request_info          info;
659         int                             extra_size = 0;
660         int                             i;
661         int                             ret = -EINVAL;
662
663         /* Get the description of the IOCTL */
664         for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
665                 if(cmd == dev->wireless_handlers->private_args[i].cmd) {
666                         descr = &(dev->wireless_handlers->private_args[i]);
667                         break;
668                 }
669
670 #ifdef WE_IOCTL_DEBUG
671         printk(KERN_DEBUG "%s (WE) : Found private handler for 0x%04X\n",
672                ifr->ifr_name, cmd);
673         if(descr) {
674                 printk(KERN_DEBUG "%s (WE) : Name %s, set %X, get %X\n",
675                        dev->name, descr->name,
676                        descr->set_args, descr->get_args);
677         }
678 #endif  /* WE_IOCTL_DEBUG */
679
680         /* Compute the size of the set/get arguments */
681         if(descr != NULL) {
682                 if(IW_IS_SET(cmd)) {
683                         int     offset = 0;     /* For sub-ioctls */
684                         /* Check for sub-ioctl handler */
685                         if(descr->name[0] == '\0')
686                                 /* Reserve one int for sub-ioctl index */
687                                 offset = sizeof(__u32);
688
689                         /* Size of set arguments */
690                         extra_size = get_priv_size(descr->set_args);
691
692                         /* Does it fits in iwr ? */
693                         if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
694                            ((extra_size + offset) <= IFNAMSIZ))
695                                 extra_size = 0;
696                 } else {
697                         /* Size of set arguments */
698                         extra_size = get_priv_size(descr->get_args);
699
700                         /* Does it fits in iwr ? */
701                         if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
702                            (extra_size <= IFNAMSIZ))
703                                 extra_size = 0;
704                 }
705         }
706
707         /* Prepare the call */
708         info.cmd = cmd;
709         info.flags = 0;
710
711         /* Check if we have a pointer to user space data or not. */
712         if(extra_size == 0) {
713                 /* No extra arguments. Trivial to handle */
714                 ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u));
715         } else {
716                 char *  extra;
717                 int     err;
718
719                 /* Check what user space is giving us */
720                 if(IW_IS_SET(cmd)) {
721                         /* Check NULL pointer */
722                         if((iwr->u.data.pointer == NULL) &&
723                            (iwr->u.data.length != 0))
724                                 return -EFAULT;
725
726                         /* Does it fits within bounds ? */
727                         if(iwr->u.data.length > (descr->set_args &
728                                                  IW_PRIV_SIZE_MASK))
729                                 return -E2BIG;
730                 } else {
731                         /* Check NULL pointer */
732                         if(iwr->u.data.pointer == NULL)
733                                 return -EFAULT;
734                 }
735
736 #ifdef WE_IOCTL_DEBUG
737                 printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
738                        dev->name, extra_size);
739 #endif  /* WE_IOCTL_DEBUG */
740
741                 /* Always allocate for max space. Easier, and won't last
742                  * long... */
743                 extra = kmalloc(extra_size, GFP_KERNEL);
744                 if (extra == NULL) {
745                         return -ENOMEM;
746                 }
747
748                 /* If it is a SET, get all the extra data in here */
749                 if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
750                         err = copy_from_user(extra, iwr->u.data.pointer,
751                                              extra_size);
752                         if (err) {
753                                 kfree(extra);
754                                 return -EFAULT;
755                         }
756 #ifdef WE_IOCTL_DEBUG
757                         printk(KERN_DEBUG "%s (WE) : Got %d elem\n",
758                                dev->name, iwr->u.data.length);
759 #endif  /* WE_IOCTL_DEBUG */
760                 }
761
762                 /* Call the handler */
763                 ret = handler(dev, &info, &(iwr->u), extra);
764
765                 /* If we have something to return to the user */
766                 if (!ret && IW_IS_GET(cmd)) {
767                         err = copy_to_user(iwr->u.data.pointer, extra,
768                                            extra_size);
769                         if (err)
770                                 ret =  -EFAULT;                            
771 #ifdef WE_IOCTL_DEBUG
772                         printk(KERN_DEBUG "%s (WE) : Wrote %d elem\n",
773                                dev->name, iwr->u.data.length);
774 #endif  /* WE_IOCTL_DEBUG */
775                 }
776
777                 /* Cleanup - I told you it wasn't that long ;-) */
778                 kfree(extra);
779         }
780
781
782         /* Call commit handler if needed and defined */
783         if(ret == -EIWCOMMIT)
784                 ret = call_commit_handler(dev);
785
786         return ret;
787 }
788
789 /* ---------------------------------------------------------------- */
790 /*
791  * Main IOCTl dispatcher. Called from the main networking code
792  * (dev_ioctl() in net/core/dev.c).
793  * Check the type of IOCTL and call the appropriate wrapper...
794  */
795 int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
796 {
797         struct net_device *dev;
798         iw_handler      handler;
799
800         /* Permissions are already checked in dev_ioctl() before calling us.
801          * The copy_to/from_user() of ifr is also dealt with in there */
802
803         /* Make sure the device exist */
804         if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
805                 return -ENODEV;
806
807         /* A bunch of special cases, then the generic case...
808          * Note that 'cmd' is already filtered in dev_ioctl() with
809          * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
810         switch(cmd) 
811         {
812                 case SIOCGIWSTATS:
813                         /* Get Wireless Stats */
814                         return dev_iwstats(dev, ifr);
815
816                 case SIOCGIWPRIV:
817                         /* Check if we have some wireless handlers defined */
818                         if(dev->wireless_handlers != NULL) {
819                                 /* We export to user space the definition of
820                                  * the private handler ourselves */
821                                 return ioctl_export_private(dev, ifr);
822                         }
823                         // ## Fall-through for old API ##
824                 default:
825                         /* Generic IOCTL */
826                         /* Basic check */
827                         if (!netif_device_present(dev))
828                                 return -ENODEV;
829                         /* New driver API : try to find the handler */
830                         handler = get_handler(dev, cmd);
831                         if(handler != NULL) {
832                                 /* Standard and private are not the same */
833                                 if(cmd < SIOCIWFIRSTPRIV)
834                                         return ioctl_standard_call(dev,
835                                                                    ifr,
836                                                                    cmd,
837                                                                    handler);
838                                 else
839                                         return ioctl_private_call(dev,
840                                                                   ifr,
841                                                                   cmd,
842                                                                   handler);
843                         }
844                         /* Old driver API : call driver ioctl handler */
845                         if (dev->do_ioctl) {
846                                 return dev->do_ioctl(dev, ifr, cmd);
847                         }
848                         return -EOPNOTSUPP;
849         }
850         /* Not reached */
851         return -EINVAL;
852 }
853
854 /************************* EVENT PROCESSING *************************/
855 /*
856  * Process events generated by the wireless layer or the driver.
857  * Most often, the event will be propagated through rtnetlink
858  */
859
860 #ifdef WE_EVENT_NETLINK
861 /* "rtnl" is defined in net/core/rtnetlink.c, but we need it here.
862  * It is declared in <linux/rtnetlink.h> */
863
864 /* ---------------------------------------------------------------- */
865 /*
866  * Fill a rtnetlink message with our event data.
867  * Note that we propage only the specified event and don't dump the
868  * current wireless config. Dumping the wireless config is far too
869  * expensive (for each parameter, the driver need to query the hardware).
870  */
871 static inline int rtnetlink_fill_iwinfo(struct sk_buff *        skb,
872                                         struct net_device *     dev,
873                                         int                     type,
874                                         char *                  event,
875                                         int                     event_len)
876 {
877         struct ifinfomsg *r;
878         struct nlmsghdr  *nlh;
879         unsigned char    *b = skb->tail;
880
881         nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(*r));
882         r = NLMSG_DATA(nlh);
883         r->ifi_family = AF_UNSPEC;
884         r->ifi_type = dev->type;
885         r->ifi_index = dev->ifindex;
886         r->ifi_flags = dev->flags;
887         r->ifi_change = 0;      /* Wireless changes don't affect those flags */
888
889         /* Add the wireless events in the netlink packet */
890         RTA_PUT(skb, IFLA_WIRELESS,
891                 event_len, event);
892
893         nlh->nlmsg_len = skb->tail - b;
894         return skb->len;
895
896 nlmsg_failure:
897 rtattr_failure:
898         skb_trim(skb, b - skb->data);
899         return -1;
900 }
901
902 /* ---------------------------------------------------------------- */
903 /*
904  * Create and broadcast and send it on the standard rtnetlink socket
905  * This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c
906  * Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field
907  * within a RTM_NEWLINK event.
908  */
909 static inline void rtmsg_iwinfo(struct net_device *     dev,
910                                 char *                  event,
911                                 int                     event_len)
912 {
913         struct sk_buff *skb;
914         int size = NLMSG_GOODSIZE;
915
916         skb = alloc_skb(size, GFP_ATOMIC);
917         if (!skb)
918                 return;
919
920         if (rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK,
921                                   event, event_len) < 0) {
922                 kfree_skb(skb);
923                 return;
924         }
925         NETLINK_CB(skb).dst_groups = RTMGRP_LINK;
926         netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_ATOMIC);
927 }
928 #endif  /* WE_EVENT_NETLINK */
929
930 /* ---------------------------------------------------------------- */
931 /*
932  * Main event dispatcher. Called from other parts and drivers.
933  * Send the event on the apropriate channels.
934  * May be called from interrupt context.
935  */
936 void wireless_send_event(struct net_device *    dev,
937                          unsigned int           cmd,
938                          union iwreq_data *     wrqu,
939                          char *                 extra)
940 {
941         const struct iw_ioctl_description *     descr = NULL;
942         int extra_len = 0;
943         struct iw_event  *event;                /* Mallocated whole event */
944         int event_len;                          /* Its size */
945         int hdr_len;                            /* Size of the event header */
946         /* Don't "optimise" the following variable, it will crash */
947         unsigned        cmd_index;              /* *MUST* be unsigned */
948
949         /* Get the description of the IOCTL */
950         if(cmd <= SIOCIWLAST) {
951                 cmd_index = cmd - SIOCIWFIRST;
952                 if(cmd_index < standard_ioctl_num)
953                         descr = &(standard_ioctl[cmd_index]);
954         } else {
955                 cmd_index = cmd - IWEVFIRST;
956                 if(cmd_index < standard_event_num)
957                         descr = &(standard_event[cmd_index]);
958         }
959         /* Don't accept unknown events */
960         if(descr == NULL) {
961                 /* Note : we don't return an error to the driver, because
962                  * the driver would not know what to do about it. It can't
963                  * return an error to the user, because the event is not
964                  * initiated by a user request.
965                  * The best the driver could do is to log an error message.
966                  * We will do it ourselves instead...
967                  */
968                 printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
969                        dev->name, cmd);
970                 return;
971         }
972 #ifdef WE_EVENT_DEBUG
973         printk(KERN_DEBUG "%s (WE) : Got event 0x%04X\n",
974                dev->name, cmd);
975         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);
976 #endif  /* WE_EVENT_DEBUG */
977
978         /* Check extra parameters and set extra_len */
979         if(descr->header_type == IW_HEADER_TYPE_POINT) {
980                 /* Check if number of token fits within bounds */
981                 if(wrqu->data.length > descr->max_tokens) {
982                         printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length);
983                         return;
984                 }
985                 if(wrqu->data.length < descr->min_tokens) {
986                         printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length);
987                         return;
988                 }
989                 /* Calculate extra_len - extra is NULL for restricted events */
990                 if(extra != NULL)
991                         extra_len = wrqu->data.length * descr->token_size;
992 #ifdef WE_EVENT_DEBUG
993                 printk(KERN_DEBUG "%s (WE) : Event 0x%04X, tokens %d, extra_len %d\n", dev->name, cmd, wrqu->data.length, extra_len);
994 #endif  /* WE_EVENT_DEBUG */
995         }
996
997         /* Total length of the event */
998         hdr_len = event_type_size[descr->header_type];
999         event_len = hdr_len + extra_len;
1000
1001 #ifdef WE_EVENT_DEBUG
1002         printk(KERN_DEBUG "%s (WE) : Event 0x%04X, hdr_len %d, event_len %d\n", dev->name, cmd, hdr_len, event_len);
1003 #endif  /* WE_EVENT_DEBUG */
1004
1005         /* Create temporary buffer to hold the event */
1006         event = kmalloc(event_len, GFP_ATOMIC);
1007         if(event == NULL)
1008                 return;
1009
1010         /* Fill event */
1011         event->len = event_len;
1012         event->cmd = cmd;
1013         memcpy(&event->u, wrqu, hdr_len - IW_EV_LCP_LEN);
1014         if(extra != NULL)
1015                 memcpy(((char *) event) + hdr_len, extra, extra_len);
1016
1017 #ifdef WE_EVENT_NETLINK
1018         /* rtnetlink event channel */
1019         rtmsg_iwinfo(dev, (char *) event, event_len);
1020 #endif  /* WE_EVENT_NETLINK */
1021
1022         /* Cleanup */
1023         kfree(event);
1024
1025         return;         /* Always success, I guess ;-) */
1026 }