1 diff -u -p -r --new-file linux/include/linux-w12/netdevice.h linux/include/linux/netdevice.h
2 --- linux/include/linux-w12/netdevice.h Thu Nov 22 11:47:09 2001
3 +++ linux/include/linux/netdevice.h Thu Jan 17 12:00:39 2002
4 @@ -278,6 +278,10 @@ struct net_device
5 struct net_device_stats* (*get_stats)(struct net_device *dev);
6 struct iw_statistics* (*get_wireless_stats)(struct net_device *dev);
8 + /* List of functions to handle Wireless Extensions (instead of ioctl).
9 + * See <net/iw_handler.h> for details. Jean II */
10 + struct iw_handler_def * wireless_handlers;
13 * This marks the end of the "visible" part of the structure. All
14 * fields hereafter are internal to the system, and may change at
15 diff -u -p -r --new-file linux/include/linux-w12/wireless.h linux/include/linux/wireless.h
16 --- linux/include/linux-w12/wireless.h Thu Nov 22 11:47:12 2001
17 +++ linux/include/linux/wireless.h Thu Jan 17 12:04:08 2002
20 * This file define a set of standard wireless extensions
22 - * Version : 12 5.10.01
23 + * Version : 13 6.12.01
25 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
26 + * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
29 #ifndef _LINUX_WIRELESS_H
32 /************************** DOCUMENTATION **************************/
34 + * Initial APIs (1996 -> onward) :
35 + * -----------------------------
36 * Basically, the wireless extensions are for now a set of standard ioctl
37 * call + /proc/net/wireless
40 * We have the list of command plus a structure descibing the
42 * Note that to add these ioctl, I was obliged to modify :
43 - * net/core/dev.c (two place + add include)
44 - * net/ipv4/af_inet.c (one place + add include)
45 + * # net/core/dev.c (two place + add include)
46 + * # net/ipv4/af_inet.c (one place + add include)
48 * /proc/net/wireless is a copy of /proc/net/dev.
49 * We have a structure for data passed from the driver to /proc/net/wireless
50 * Too add this, I've modified :
51 - * net/core/dev.c (two other places)
52 - * include/linux/netdevice.h (one place)
53 - * include/linux/proc_fs.h (one place)
54 + * # net/core/dev.c (two other places)
55 + * # include/linux/netdevice.h (one place)
56 + * # include/linux/proc_fs.h (one place)
58 + * New driver API (2001 -> onward) :
59 + * -------------------------------
60 + * This file is only concerned with the user space API and common definitions.
61 + * The new driver API is defined and documented in :
62 + * # include/net/iw_handler.h
64 + * Note as well that /proc/net/wireless implementation has now moved in :
65 + * # include/linux/wireless.c
69 * Do not add here things that are redundant with other mechanisms
70 * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
73 #include <linux/socket.h> /* for "struct sockaddr" et al */
74 #include <linux/if.h> /* for IFNAMSIZ and co... */
76 -/**************************** CONSTANTS ****************************/
78 -/* --------------------------- VERSION --------------------------- */
79 +/***************************** VERSION *****************************/
81 * This constant is used to know the availability of the wireless
82 * extensions and to know which version of wireless extensions it is
83 * (there is some stuff that will be added in the future...)
84 * I just plan to increment with each new version.
86 -#define WIRELESS_EXT 12
87 +#define WIRELESS_EXT 13
92 * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
93 * - Add new statistics (frag, retry, beacon)
94 * - Add average quality (for user space calibration)
98 + * - Document creation of new driver API.
99 + * - Extract union iwreq_data from struct iwreq (for new driver API).
100 + * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
103 +/**************************** CONSTANTS ****************************/
105 /* -------------------------- IOCTL LIST -------------------------- */
107 /* Basic operations */
108 -#define SIOCSIWNAME 0x8B00 /* Unused */
109 +#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
110 #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
111 #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */
112 #define SIOCGIWNWID 0x8B03 /* get network id */
113 @@ -414,13 +434,49 @@ struct iw_statistics
115 /* ------------------------ IOCTL REQUEST ------------------------ */
117 + * This structure defines the payload of an ioctl, and is used
120 + * Note that this structure should fit on the memory footprint
121 + * of iwreq (which is the same as ifreq), which mean a max size of
122 + * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
123 + * You should check this when increasing the structures defined
124 + * above in this file...
128 + /* Config - generic */
129 + char name[IFNAMSIZ];
130 + /* Name : used to verify the presence of wireless extensions.
131 + * Name of the protocol/provider... */
133 + struct iw_point essid; /* Extended network name */
134 + struct iw_param nwid; /* network id (or domain - the cell) */
135 + struct iw_freq freq; /* frequency or channel :
137 + * > 1000 = frequency in Hz */
139 + struct iw_param sens; /* signal level threshold */
140 + struct iw_param bitrate; /* default bit rate */
141 + struct iw_param txpower; /* default transmit power */
142 + struct iw_param rts; /* RTS threshold threshold */
143 + struct iw_param frag; /* Fragmentation threshold */
144 + __u32 mode; /* Operation mode */
145 + struct iw_param retry; /* Retry limits & lifetime */
147 + struct iw_point encoding; /* Encoding stuff : tokens */
148 + struct iw_param power; /* PM duration/timeout */
150 + struct sockaddr ap_addr; /* Access point address */
152 + struct iw_point data; /* Other large parameters */
156 * The structure to exchange data for ioctl.
157 * This structure is the same as 'struct ifreq', but (re)defined for
160 - * Note that it should fit on the same memory footprint !
161 - * You should check this when increasing the above structures (16 octets)
162 - * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
163 + * Do I need to remind you about structure size (32 octets) ?
167 @@ -429,35 +485,8 @@ struct iwreq
168 char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
174 - /* Config - generic */
175 - char name[IFNAMSIZ];
176 - /* Name : used to verify the presence of wireless extensions.
177 - * Name of the protocol/provider... */
179 - struct iw_point essid; /* Extended network name */
180 - struct iw_param nwid; /* network id (or domain - the cell) */
181 - struct iw_freq freq; /* frequency or channel :
183 - * > 1000 = frequency in Hz */
185 - struct iw_param sens; /* signal level threshold */
186 - struct iw_param bitrate; /* default bit rate */
187 - struct iw_param txpower; /* default transmit power */
188 - struct iw_param rts; /* RTS threshold threshold */
189 - struct iw_param frag; /* Fragmentation threshold */
190 - __u32 mode; /* Operation mode */
191 - struct iw_param retry; /* Retry limits & lifetime */
193 - struct iw_point encoding; /* Encoding stuff : tokens */
194 - struct iw_param power; /* PM duration/timeout */
196 - struct sockaddr ap_addr; /* Access point address */
198 - struct iw_point data; /* Other large parameters */
200 + /* Data part (defined just above) */
201 + union iwreq_data u;
204 /* -------------------------- IOCTL DATA -------------------------- */
205 diff -u -p -r --new-file linux/include/net-w12/iw_handler.h linux/include/net/iw_handler.h
206 --- linux/include/net-w12/iw_handler.h Wed Dec 31 16:00:00 1969
207 +++ linux/include/net/iw_handler.h Thu Jan 17 12:16:46 2002
210 + * This file define the new driver API for Wireless Extensions
212 + * Version : 2 6.12.01
214 + * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
215 + * Copyright (c) 2001 Jean Tourrilhes, All Rights Reserved.
218 +#ifndef _IW_HANDLER_H
219 +#define _IW_HANDLER_H
221 +/************************** DOCUMENTATION **************************/
223 + * Initial driver API (1996 -> onward) :
224 + * -----------------------------------
225 + * The initial API just sends the IOCTL request received from user space
226 + * to the driver (via the driver ioctl handler). The driver has to
227 + * handle all the rest...
229 + * The initial API also defines a specific handler in struct net_device
230 + * to handle wireless statistics.
232 + * The initial APIs served us well and has proven a reasonably good design.
233 + * However, there is a few shortcommings :
234 + * o No events, everything is a request to the driver.
235 + * o Large ioctl function in driver with gigantic switch statement
236 + * (i.e. spaghetti code).
237 + * o Driver has to mess up with copy_to/from_user, and in many cases
238 + * does it unproperly. Common mistakes are :
239 + * * buffer overflows (no checks or off by one checks)
240 + * * call copy_to/from_user with irq disabled
241 + * o The user space interface is tied to ioctl because of the use
242 + * copy_to/from_user.
244 + * New driver API (2001 -> onward) :
245 + * -------------------------------
246 + * The new driver API is just a bunch of standard functions (handlers),
247 + * each handling a specific Wireless Extension. The driver just export
248 + * the list of handler it supports, and those will be called apropriately.
250 + * I tried to keep the main advantage of the previous API (simplicity,
251 + * efficiency and light weight), and also I provide a good dose of backward
252 + * compatibility (most structures are the same, driver can use both API
253 + * simultaneously, ...).
254 + * Hopefully, I've also addressed the shortcomming of the initial API.
256 + * The advantage of the new API are :
257 + * o Handling of Extensions in driver broken in small contained functions
258 + * o Tighter checks of ioctl before calling the driver
259 + * o Flexible commit strategy (at least, the start of it)
260 + * o Backward compatibility (can be mixed with old API)
261 + * o Driver doesn't have to worry about memory and user-space issues
262 + * The last point is important for the following reasons :
263 + * o You are now able to call the new driver API from any API you
264 + * want (including from within other parts of the kernel).
265 + * o Common mistakes are avoided (buffer overflow, user space copy
266 + * with irq disabled and so on).
268 + * The Drawback of the new API are :
269 + * o bloat (especially kernel)
270 + * o need to migrate existing drivers to new API
271 + * My initial testing shows that the new API adds around 3kB to the kernel
272 + * and save between 0 and 5kB from a typical driver.
273 + * Also, as all structures and data types are unchanged, the migration is
274 + * quite straightforward (but tedious).
278 + * The new driver API is defined below in this file. User space should
279 + * not be aware of what's happening down there...
281 + * A new kernel wrapper is in charge of validating the IOCTLs and calling
282 + * the appropriate driver handler. This is implemented in :
283 + * # net/core/wireless.c
285 + * The driver export the list of handlers in :
286 + * # include/linux/netdevice.h (one place)
288 + * The new driver API is available for WIRELESS_EXT >= 13.
289 + * Good luck with migration to the new API ;-)
292 +/* ---------------------- THE IMPLEMENTATION ---------------------- */
294 + * Some of the choice I've made are pretty controversials. Defining an
295 + * API is very much weighting compromises. This goes into some of the
296 + * details and the thinking behind the implementation.
298 + * Implementation goals :
299 + * --------------------
300 + * The implementation goals were as follow :
301 + * o Obvious : you should not need a PhD to understand what's happening,
302 + * the benefit is easier maintainance.
303 + * o Flexible : it should accomodate a wide variety of driver
304 + * implementations and be as flexible as the old API.
305 + * o Lean : it should be efficient memory wise to minimise the impact
306 + * on kernel footprint.
307 + * o Transparent to user space : the large number of user space
308 + * applications that use Wireless Extensions should not need
309 + * any modifications.
311 + * Array of functions versus Struct of functions
312 + * ---------------------------------------------
313 + * 1) Having an array of functions allow the kernel code to access the
314 + * handler in a single lookup, which is much more efficient (think hash
316 + * 2) The only drawback is that driver writer may put their handler in
317 + * the wrong slot. This is trivial to test (I set the frequency, the
318 + * bitrate changes). Once the handler is in the proper slot, it will be
319 + * there forever, because the array is only extended at the end.
320 + * 3) Backward/forward compatibility : adding new handler just require
321 + * extending the array, so you can put newer driver in older kernel
322 + * without having to patch the kernel code (and vice versa).
324 + * All handler are of the same generic type
325 + * ----------------------------------------
326 + * That's a feature !!!
327 + * 1) Having a generic handler allow to have generic code, which is more
328 + * efficient. If each of the handler was individually typed I would need
329 + * to add a big switch in the kernel (== more bloat). This solution is
330 + * more scalable, adding new Wireless Extensions doesn't add new code.
331 + * 2) You can use the same handler in different slots of the array. For
332 + * hardware, it may be more efficient or logical to handle multiple
333 + * Wireless Extensions with a single function, and the API allow you to
334 + * do that. (An example would be a single record on the card to control
335 + * both bitrate and frequency, the handler would read the old record,
336 + * modify it according to info->cmd and rewrite it).
338 + * Functions prototype uses union iwreq_data
339 + * -----------------------------------------
340 + * Some would have prefered functions defined this way :
341 + * static int mydriver_ioctl_setrate(struct net_device *dev,
342 + * long rate, int auto)
343 + * 1) The kernel code doesn't "validate" the content of iwreq_data, and
344 + * can't do it (different hardware may have different notion of what a
345 + * valid frequency is), so we don't pretend that we do it.
346 + * 2) The above form is not extendable. If I want to add a flag (for
347 + * example to distinguish setting max rate and basic rate), I would
348 + * break the prototype. Using iwreq_data is more flexible.
349 + * 3) Also, the above form is not generic (see above).
350 + * 4) I don't expect driver developper using the wrong field of the
351 + * union (Doh !), so static typechecking doesn't add much value.
352 + * 5) Lastly, you can skip the union by doing :
353 + * static int mydriver_ioctl_setrate(struct net_device *dev,
354 + * struct iw_request_info *info,
355 + * struct iw_param *rrq,
357 + * And then adding the handler in the array like this :
358 + * (iw_handler) mydriver_ioctl_setrate, // SIOCSIWRATE
360 + * Using functions and not a registry
361 + * ----------------------------------
362 + * Another implementation option would have been for every instance to
363 + * define a registry (a struct containing all the Wireless Extensions)
364 + * and only have a function to commit the registry to the hardware.
365 + * 1) This approach can be emulated by the current code, but not
367 + * 2) Some drivers don't keep any configuration in the driver, for them
368 + * adding such a registry would be a significant bloat.
369 + * 3) The code to translate from Wireless Extension to native format is
370 + * needed anyway, so it would not reduce significantely the amount of code.
371 + * 4) The current approach only selectively translate Wireless Extensions
372 + * to native format and only selectively set, whereas the registry approach
373 + * would require to translate all WE and set all parameters for any single
375 + * 5) For many Wireless Extensions, the GET operation return the current
376 + * dynamic value, not the value that was set.
378 + * This header is <net/iw_handler.h>
379 + * ---------------------------------
380 + * 1) This header is kernel space only and should not be exported to
381 + * user space. Headers in "include/linux/" are exported, headers in
382 + * "include/net/" are not.
384 + * Mixed 32/64 bit issues
385 + * ----------------------
386 + * The Wireless Extensions are designed to be 64 bit clean, by using only
387 + * datatypes with explicit storage size.
388 + * There are some issues related to kernel and user space using different
389 + * memory model, and in particular 64bit kernel with 32bit user space.
390 + * The problem is related to struct iw_point, that contains a pointer
391 + * that *may* need to be translated.
392 + * This is quite messy. The new API doesn't solve this problem (it can't),
393 + * but is a step in the right direction :
394 + * 1) Meta data about each ioctl is easily available, so we know what type
395 + * of translation is needed.
396 + * 2) The move of data between kernel and user space is only done in a single
397 + * place in the kernel, so adding specific hooks in there is possible.
398 + * 3) In the long term, it allows to move away from using ioctl as the
401 + * So many comments and so few code
402 + * --------------------------------
403 + * That's a feature. Comments won't bloat the resulting kernel binary.
406 +/***************************** INCLUDES *****************************/
408 +#include <linux/wireless.h> /* IOCTL user space API */
410 +/***************************** VERSION *****************************/
412 + * This constant is used to know which version of the driver API is
413 + * available. Hopefully, this will be pretty stable and no changes
414 + * will be needed...
415 + * I just plan to increment with each new version.
417 +#define IW_HANDLER_VERSION 2
419 +/**************************** CONSTANTS ****************************/
421 +/* Special error message for the driver to indicate that we
422 + * should do a commit after return from the iw_handler */
423 +#define EIWCOMMIT EINPROGRESS
425 +/* Flags available in struct iw_request_info */
426 +#define IW_REQUEST_FLAG_NONE 0x0000 /* No flag so far */
428 +/* Type of headers we know about (basically union iwreq_data) */
429 +#define IW_HEADER_TYPE_NULL 0 /* Not available */
430 +#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
431 +#define IW_HEADER_TYPE_UINT 4 /* __u32 */
432 +#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
433 +#define IW_HEADER_TYPE_POINT 6 /* struct iw_point */
434 +#define IW_HEADER_TYPE_PARAM 7 /* struct iw_param */
435 +#define IW_HEADER_TYPE_ADDR 8 /* struct sockaddr */
437 +/* Handling flags */
438 +/* Most are not implemented. I just use them as a reminder of some
439 + * cool features we might need one day ;-) */
440 +#define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */
441 +/* Wrapper level flags */
442 +#define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
443 +#define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
444 +#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET request is ROOT only */
445 +/* Driver level flags */
446 +#define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
448 +/****************************** TYPES ******************************/
450 +/* ----------------------- WIRELESS HANDLER ----------------------- */
452 + * A wireless handler is just a standard function, that looks like the
454 + * We also define there how a handler list look like... As the Wireless
455 + * Extension space is quite dense, we use a simple array, which is faster
456 + * (that's the perfect hash table ;-).
460 + * Meta data about the request passed to the iw_handler.
461 + * Most handlers can safely ignore what's in there.
462 + * The 'cmd' field might come handy if you want to use the same handler
463 + * for multiple command...
464 + * This struct is also my long term insurance. I can add new fields here
465 + * without breaking the prototype of iw_handler...
467 +struct iw_request_info
469 + __u16 cmd; /* Wireless Extension command */
470 + __u16 flags; /* More to come ;-) */
474 + * This is how a function handling a Wireless Extension should look
475 + * like (both get and set, standard and private).
477 +typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
478 + union iwreq_data *wrqu, char *extra);
481 + * This define all the handler that the driver export.
482 + * As you need only one per driver type, please use a static const
483 + * shared by all driver instances... Same for the members...
484 + * This will be linked from net_device in <linux/netdevice.h>
486 +struct iw_handler_def
488 + /* Number of handlers defined (more precisely, index of the
489 + * last defined handler + 1) */
490 + __u16 num_standard;
492 + /* Number of private arg description */
493 + __u16 num_private_args;
495 + /* Array of handlers for standard ioctls
496 + * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
498 + iw_handler * standard;
500 + /* Array of handlers for private ioctls
501 + * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
503 + iw_handler * private;
505 + /* Arguments of private handler. This one is just a list, so you
506 + * can put it in any order you want and should not leave holes...
507 + * We will automatically export that to user space... */
508 + struct iw_priv_args * private_args;
510 + /* In the long term, get_wireless_stats will move from
511 + * 'struct net_device' to here, to minimise bloat. */
514 +/* ----------------------- WIRELESS EVENTS ----------------------- */
516 + * Currently we don't support events, so let's just plan for the
521 + * A Wireless Event.
523 +// How do we define short header ? We don't want a flag on length.
524 +// Probably a flag on event ? Highest bit to zero...
527 + __u16 length; /* Lenght of this stuff */
528 + __u16 event; /* Wireless IOCTL */
529 + union iwreq_data header; /* IOCTL fixed payload */
530 + char extra[0]; /* Optional IOCTL data */
533 +/* ---------------------- IOCTL DESCRIPTION ---------------------- */
535 + * One of the main goal of the new interface is to deal entirely with
536 + * user space/kernel space memory move.
537 + * For that, we need to know :
538 + * o if iwreq is a pointer or contain the full data
539 + * o what is the size of the data to copy
541 + * For private IOCTLs, we use the same rules as used by iwpriv and
542 + * defined in struct iw_priv_args.
544 + * For standard IOCTLs, things are quite different and we need to
545 + * use the stuctures below. Actually, this struct is also more
546 + * efficient, but that's another story...
550 + * Describe how a standard IOCTL looks like.
552 +struct iw_ioctl_description
554 + __u8 header_type; /* NULL, iw_point or other */
555 + __u8 token_type; /* Future */
556 + __u16 token_size; /* Granularity of payload */
557 + __u16 min_tokens; /* Min acceptable token number */
558 + __u16 max_tokens; /* Max acceptable token number */
559 + __u32 flags; /* Special handling of the request */
562 +/* Need to think of short header translation table. Later. */
564 +/**************************** PROTOTYPES ****************************/
566 + * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
567 + * Those may be called only within the kernel.
570 +/* First : function strictly used inside the kernel */
572 +/* Handle /proc/net/wireless, called in net/code/dev.c */
573 +extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
576 +/* Handle IOCTLs, called in net/code/dev.c */
577 +extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
579 +/* Second : functions that may be called by driver modules */
582 +#endif /* _LINUX_WIRELESS_H */
583 diff -u -p -r --new-file linux/net/core-w12/Makefile linux/net/core/Makefile
584 --- linux/net/core-w12/Makefile Tue Oct 30 15:08:12 2001
585 +++ linux/net/core/Makefile Thu Jan 17 11:06:07 2002
586 @@ -26,5 +26,8 @@ obj-$(CONFIG_NET) += dev.o dev_mcast.o d
587 obj-$(CONFIG_NETFILTER) += netfilter.o
588 obj-$(CONFIG_NET_DIVERT) += dv.o
589 obj-$(CONFIG_NET_PROFILE) += profile.o
590 +obj-$(CONFIG_NET_RADIO) += wireless.o
591 +# Ugly. I wish all wireless drivers were moved in drivers/net/wireless
592 +obj-$(CONFIG_NET_PCMCIA_RADIO) += wireless.o
594 include $(TOPDIR)/Rules.make
595 diff -u -p -r --new-file linux/net/core-w12/dev.c linux/net/core/dev.c
596 --- linux/net/core-w12/dev.c Wed Nov 7 14:39:36 2001
597 +++ linux/net/core/dev.c Thu Jan 17 11:06:07 2002
599 #include <linux/module.h>
600 #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
601 #include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
602 +#include <net/iw_handler.h>
603 #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
605 extern int plip_init(void);
606 @@ -1796,122 +1797,6 @@ static int dev_proc_stats(char *buffer,
607 #endif /* CONFIG_PROC_FS */
611 -#ifdef CONFIG_PROC_FS
614 - * Print one entry of /proc/net/wireless
615 - * This is a clone of /proc/net/dev (just above)
617 -static int sprintf_wireless_stats(char *buffer, struct net_device *dev)
619 - /* Get stats from the driver */
620 - struct iw_statistics *stats = (dev->get_wireless_stats ?
621 - dev->get_wireless_stats(dev) :
622 - (struct iw_statistics *) NULL);
625 - if (stats != (struct iw_statistics *) NULL) {
626 - size = sprintf(buffer,
627 - "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d %6d %6d %6d\n",
631 - stats->qual.updated & 1 ? '.' : ' ',
633 - stats->qual.updated & 2 ? '.' : ' ',
635 - stats->qual.updated & 4 ? '.' : ' ',
636 - stats->discard.nwid,
637 - stats->discard.code,
638 - stats->discard.fragment,
639 - stats->discard.retries,
640 - stats->discard.misc,
641 - stats->miss.beacon);
642 - stats->qual.updated = 0;
651 - * Print info for /proc/net/wireless (print all entries)
652 - * This is a clone of /proc/net/dev (just above)
654 -static int dev_get_wireless_info(char * buffer, char **start, off_t offset,
662 - struct net_device * dev;
664 - size = sprintf(buffer,
665 - "Inter-| sta-| Quality | Discarded packets | Missed\n"
666 - " face | tus | link level noise | nwid crypt frag retry misc | beacon\n"
672 - read_lock(&dev_base_lock);
673 - for (dev = dev_base; dev != NULL; dev = dev->next) {
674 - size = sprintf_wireless_stats(buffer + len, dev);
678 - if (pos < offset) {
682 - if (pos > offset + length)
685 - read_unlock(&dev_base_lock);
687 - *start = buffer + (offset - begin); /* Start of wanted data */
688 - len -= (offset - begin); /* Start slop */
690 - len = length; /* Ending slop */
696 -#endif /* CONFIG_PROC_FS */
699 - * Allow programatic access to /proc/net/wireless even if /proc
700 - * doesn't exist... Also more efficient...
702 -static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
704 - /* Get stats from the driver */
705 - struct iw_statistics *stats = (dev->get_wireless_stats ?
706 - dev->get_wireless_stats(dev) :
707 - (struct iw_statistics *) NULL);
709 - if (stats != (struct iw_statistics *) NULL) {
710 - struct iwreq * wrq = (struct iwreq *)ifr;
712 - /* Copy statistics to the user buffer */
713 - if(copy_to_user(wrq->u.data.pointer, stats,
714 - sizeof(struct iw_statistics)))
717 - /* Check if we need to clear the update flag */
718 - if(wrq->u.data.flags != 0)
719 - stats->qual.updated = 0;
722 - return -EOPNOTSUPP;
724 -#endif /* WIRELESS_EXT */
727 * netdev_set_master - set up master/slave pair
728 * @slave: slave device
729 @@ -2209,11 +2094,6 @@ static int dev_ifsioc(struct ifreq *ifr,
730 notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
735 - return dev_iwstats(dev, ifr);
736 -#endif /* WIRELESS_EXT */
739 * Unknown or private ioctl
741 @@ -2239,17 +2119,6 @@ static int dev_ifsioc(struct ifreq *ifr,
746 - if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
747 - if (dev->do_ioctl) {
748 - if (!netif_device_present(dev))
750 - return dev->do_ioctl(dev, ifr, cmd);
752 - return -EOPNOTSUPP;
754 -#endif /* WIRELESS_EXT */
759 @@ -2431,7 +2300,8 @@ int dev_ioctl(unsigned int cmd, void *ar
761 dev_load(ifr.ifr_name);
763 - ret = dev_ifsioc(&ifr, cmd);
764 + /* Follow me in net/core/wireless.c */
765 + ret = wireless_process_ioctl(&ifr, cmd);
767 if (!ret && IW_IS_GET(cmd) &&
768 copy_to_user(arg, &ifr, sizeof(struct ifreq)))
769 @@ -2856,6 +2726,7 @@ int __init net_dev_init(void)
770 proc_net_create("dev", 0, dev_get_info);
771 create_proc_read_entry("net/softnet_stat", 0, 0, dev_proc_stats, NULL);
773 + /* Available in net/core/wireless.c */
774 proc_net_create("wireless", 0, dev_get_wireless_info);
775 #endif /* WIRELESS_EXT */
776 #endif /* CONFIG_PROC_FS */
777 diff -u -p -r --new-file linux/net/core-w12/wireless.c linux/net/core/wireless.c
778 --- linux/net/core-w12/wireless.c Wed Dec 31 16:00:00 1969
779 +++ linux/net/core/wireless.c Mon Jan 21 11:13:23 2002
782 + * This file implement the Wireless Extensions APIs.
784 + * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
785 + * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
787 + * (As all part of the Linux kernel, this file is GPL)
790 +/************************** DOCUMENTATION **************************/
794 + * See <linux/wireless.h> for details of the APIs and the rest.
799 + * v1 - 5.12.01 - Jean II
800 + * o Created this file.
802 + * v2 - 13.12.01 - Jean II
803 + * o Move /proc/net/wireless stuff from net/core/dev.c to here
804 + * o Make Wireless Extension IOCTLs go through here
805 + * o Added iw_handler handling ;-)
806 + * o Added standard ioctl description
807 + * o Initial dumb commit strategy based on orinoco.c
810 +/***************************** INCLUDES *****************************/
812 +#include <asm/uaccess.h> /* copy_to_user() */
813 +#include <linux/config.h> /* Not needed ??? */
814 +#include <linux/types.h> /* off_t */
815 +#include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
817 +#include <linux/wireless.h> /* Pretty obvious */
818 +#include <net/iw_handler.h> /* New driver API */
820 +/**************************** CONSTANTS ****************************/
822 +/* This will be turned on later on... */
823 +#undef WE_STRICT_WRITE /* Check write buffer size */
825 +/* Debuging stuff */
826 +#undef WE_IOCTL_DEBUG /* Debug IOCTL API */
828 +/************************* GLOBAL VARIABLES *************************/
830 + * You should not use global variables, because or re-entrancy.
831 + * On our case, it's only const, so it's OK...
833 +static const struct iw_ioctl_description standard_ioctl[] = {
834 + /* SIOCSIWCOMMIT (internal) */
835 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
837 + { IW_HEADER_TYPE_CHAR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
839 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
841 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
843 + { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
845 + { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
847 + { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
849 + { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
851 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
853 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
855 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
857 + { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_range), IW_DESCR_FLAG_DUMP},
859 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
860 + /* SIOCGIWPRIV (handled directly by us) */
861 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
863 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
864 + /* SIOCGIWSTATS (handled directly by us) */
865 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
867 + { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
869 + { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
871 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
873 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
875 + { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
877 + { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
879 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
880 + /* SIOCGIWAPLIST */
881 + { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
883 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
885 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
887 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_EVENT},
889 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_DUMP},
891 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0},
893 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0},
895 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
897 + { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
899 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
901 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
903 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
905 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
907 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
909 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
911 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
913 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
915 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
917 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
918 + /* SIOCSIWENCODE */
919 + { IW_HEADER_TYPE_POINT, 4, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT},
920 + /* SIOCGIWENCODE */
921 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT},
923 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
925 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
928 +/* Size (in bytes) of the various private data types */
929 +char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 };
931 +/************************ COMMON SUBROUTINES ************************/
933 + * Stuff that may be used in various place or doesn't fit in one
934 + * of the section below.
937 +/* ---------------------------------------------------------------- */
939 + * Return the driver handler associated with a specific Wireless Extension.
940 + * Called from various place, so make sure it remains efficient.
942 +static inline iw_handler get_handler(struct net_device *dev,
945 + unsigned int index; /* MUST be unsigned */
947 + /* Check if we have some wireless handlers defined */
948 + if(dev->wireless_handlers == NULL)
951 + /* Try as a standard command */
952 + index = cmd - SIOCIWFIRST;
953 + if(index < dev->wireless_handlers->num_standard)
954 + return dev->wireless_handlers->standard[index];
956 + /* Try as a private command */
957 + index = cmd - SIOCIWFIRSTPRIV;
958 + if(index < dev->wireless_handlers->num_private)
959 + return dev->wireless_handlers->private[index];
965 +/* ---------------------------------------------------------------- */
967 + * Get statistics out of the driver
969 +static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
971 + return (dev->get_wireless_stats ?
972 + dev->get_wireless_stats(dev) :
973 + (struct iw_statistics *) NULL);
974 + /* In the future, get_wireless_stats may move from 'struct net_device'
975 + * to 'struct iw_handler_def', to de-bloat struct net_device.
976 + * Definitely worse a thought... */
979 +/* ---------------------------------------------------------------- */
981 + * Call the commit handler in the driver
982 + * (if exist and if conditions are right)
984 + * Note : our current commit strategy is currently pretty dumb,
985 + * but we will be able to improve on that...
986 + * The goal is to try to agreagate as many changes as possible
987 + * before doing the commit. Drivers that will define a commit handler
988 + * are usually those that need a reset after changing parameters, so
989 + * we want to minimise the number of reset.
990 + * A cool idea is to use a timer : at each "set" command, we re-set the
991 + * timer, when the timer eventually fires, we call the driver.
992 + * Hopefully, more on that later.
994 + * Also, I'm waiting to see how many people will complain about the
995 + * netif_running(dev) test. I'm open on that one...
996 + * Hopefully, the driver will remember to do a commit in "open()" ;-)
998 +static inline int call_commit_handler(struct net_device * dev)
1000 + if((netif_running(dev)) &&
1001 + (dev->wireless_handlers->standard[0] != NULL)) {
1002 + /* Call the commit handler on the driver */
1003 + return dev->wireless_handlers->standard[0](dev, NULL,
1006 + return 0; /* Command completed successfully */
1009 +/* ---------------------------------------------------------------- */
1011 + * Number of private arguments
1013 +static inline int get_priv_size(__u16 args)
1015 + int num = args & IW_PRIV_SIZE_MASK;
1016 + int type = (args & IW_PRIV_TYPE_MASK) >> 12;
1018 + return num * priv_type_size[type];
1022 +/******************** /proc/net/wireless SUPPORT ********************/
1024 + * The /proc/net/wireless file is a human readable user-space interface
1025 + * exporting various wireless specific statistics from the wireless devices.
1026 + * This is the most popular part of the Wireless Extensions ;-)
1028 + * This interface is a pure clone of /proc/net/dev (in net/core/dev.c).
1029 + * The content of the file is basically the content of "struct iw_statistics".
1032 +#ifdef CONFIG_PROC_FS
1034 +/* ---------------------------------------------------------------- */
1036 + * Print one entry (line) of /proc/net/wireless
1038 +static inline int sprintf_wireless_stats(char *buffer, struct net_device *dev)
1040 + /* Get stats from the driver */
1041 + struct iw_statistics *stats;
1044 + stats = get_wireless_stats(dev);
1045 + if (stats != (struct iw_statistics *) NULL) {
1046 + size = sprintf(buffer,
1047 + "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d %6d %6d %6d\n",
1051 + stats->qual.updated & 1 ? '.' : ' ',
1052 + stats->qual.level,
1053 + stats->qual.updated & 2 ? '.' : ' ',
1054 + stats->qual.noise,
1055 + stats->qual.updated & 4 ? '.' : ' ',
1056 + stats->discard.nwid,
1057 + stats->discard.code,
1058 + stats->discard.fragment,
1059 + stats->discard.retries,
1060 + stats->discard.misc,
1061 + stats->miss.beacon);
1062 + stats->qual.updated = 0;
1070 +/* ---------------------------------------------------------------- */
1072 + * Print info for /proc/net/wireless (print all entries)
1074 +int dev_get_wireless_info(char * buffer, char **start, off_t offset,
1082 + struct net_device * dev;
1084 + size = sprintf(buffer,
1085 + "Inter-| sta-| Quality | Discarded packets | Missed\n"
1086 + " face | tus | link level noise | nwid crypt frag retry misc | beacon\n"
1092 + read_lock(&dev_base_lock);
1093 + for (dev = dev_base; dev != NULL; dev = dev->next) {
1094 + size = sprintf_wireless_stats(buffer + len, dev);
1096 + pos = begin + len;
1098 + if (pos < offset) {
1102 + if (pos > offset + length)
1105 + read_unlock(&dev_base_lock);
1107 + *start = buffer + (offset - begin); /* Start of wanted data */
1108 + len -= (offset - begin); /* Start slop */
1110 + len = length; /* Ending slop */
1116 +#endif /* CONFIG_PROC_FS */
1118 +/************************** IOCTL SUPPORT **************************/
1120 + * The original user space API to configure all those Wireless Extensions
1121 + * is through IOCTLs.
1122 + * In there, we check if we need to call the new driver API (iw_handler)
1123 + * or just call the driver ioctl handler.
1126 +/* ---------------------------------------------------------------- */
1128 + * Allow programatic access to /proc/net/wireless even if /proc
1129 + * doesn't exist... Also more efficient...
1131 +static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
1133 + /* Get stats from the driver */
1134 + struct iw_statistics *stats;
1136 + stats = get_wireless_stats(dev);
1137 + if (stats != (struct iw_statistics *) NULL) {
1138 + struct iwreq * wrq = (struct iwreq *)ifr;
1140 + /* Copy statistics to the user buffer */
1141 + if(copy_to_user(wrq->u.data.pointer, stats,
1142 + sizeof(struct iw_statistics)))
1145 + /* Check if we need to clear the update flag */
1146 + if(wrq->u.data.flags != 0)
1147 + stats->qual.updated = 0;
1150 + return -EOPNOTSUPP;
1153 +/* ---------------------------------------------------------------- */
1155 + * Export the driver private handler definition
1156 + * They will be picked up by tools like iwpriv...
1158 +static inline int ioctl_export_private(struct net_device * dev,
1159 + struct ifreq * ifr)
1161 + struct iwreq * iwr = (struct iwreq *) ifr;
1163 + /* Check if the driver has something to export */
1164 + if((dev->wireless_handlers->num_private_args == 0) ||
1165 + (dev->wireless_handlers->private_args == NULL))
1166 + return -EOPNOTSUPP;
1168 + /* Check NULL pointer */
1169 + if(iwr->u.data.pointer == NULL)
1171 +#ifdef WE_STRICT_WRITE
1172 + /* Check if there is enough buffer up there */
1173 + if(iwr->u.data.length < (SIOCIWLASTPRIV - SIOCIWFIRSTPRIV + 1))
1175 +#endif /* WE_STRICT_WRITE */
1177 + /* Set the number of available ioctls. */
1178 + iwr->u.data.length = dev->wireless_handlers->num_private_args;
1180 + /* Copy structure to the user buffer. */
1181 + if (copy_to_user(iwr->u.data.pointer,
1182 + dev->wireless_handlers->private_args,
1183 + sizeof(struct iw_priv_args) * iwr->u.data.length))
1189 +/* ---------------------------------------------------------------- */
1191 + * Wrapper to call a standard Wireless Extension handler.
1192 + * We do various checks and also take care of moving data between
1193 + * user space and kernel space.
1195 +static inline int ioctl_standard_call(struct net_device * dev,
1196 + struct ifreq * ifr,
1198 + iw_handler handler)
1200 + struct iwreq * iwr = (struct iwreq *) ifr;
1201 + const struct iw_ioctl_description * descr;
1202 + struct iw_request_info info;
1203 + int ret = -EINVAL;
1205 + /* Get the description of the IOCTL */
1206 + descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
1208 +#ifdef WE_IOCTL_DEBUG
1209 + printk(KERN_DEBUG "%s : Found standard handler for 0x%04X\n",
1210 + ifr->ifr_name, cmd);
1211 + printk(KERN_DEBUG "Header type : %d, token type : %d, token_size : %d, max_token : %d\n", descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
1212 +#endif /* WE_IOCTL_DEBUG */
1214 + /* Prepare the call */
1218 + /* Check if we have a pointer to user space data or not */
1219 + if(descr->header_type != IW_HEADER_TYPE_POINT) {
1220 + /* No extra arguments. Trivial to handle */
1221 + ret = handler(dev, &info, &(iwr->u), NULL);
1226 + /* Check what user space is giving us */
1227 + if(IW_IS_SET(cmd)) {
1228 + /* Check NULL pointer */
1229 + if((iwr->u.data.pointer == NULL) &&
1230 + (iwr->u.data.length != 0))
1232 + /* Check if number of token fits within bounds */
1233 + if(iwr->u.data.length > descr->max_tokens)
1235 + if(iwr->u.data.length < descr->min_tokens)
1238 + /* Check NULL pointer */
1239 + if(iwr->u.data.pointer == NULL)
1241 +#ifdef WE_STRICT_WRITE
1242 + /* Check if there is enough buffer up there */
1243 + if(iwr->u.data.length < descr->max_tokens)
1245 +#endif /* WE_STRICT_WRITE */
1248 +#ifdef WE_IOCTL_DEBUG
1249 + printk(KERN_DEBUG "Malloc %d bytes\n",
1250 + descr->max_tokens * descr->token_size);
1251 +#endif /* WE_IOCTL_DEBUG */
1253 + /* Always allocate for max space. Easier, and won't last
1255 + extra = kmalloc(descr->max_tokens * descr->token_size,
1257 + if (extra == NULL) {
1261 + /* If it is a SET, get all the extra data in here */
1262 + if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
1263 + err = copy_from_user(extra, iwr->u.data.pointer,
1264 + iwr->u.data.length *
1265 + descr->token_size);
1270 +#ifdef WE_IOCTL_DEBUG
1271 + printk(KERN_DEBUG "Got %d bytes\n",
1272 + iwr->u.data.length * descr->token_size);
1273 +#endif /* WE_IOCTL_DEBUG */
1276 + /* Call the handler */
1277 + ret = handler(dev, &info, &(iwr->u), extra);
1279 + /* If we have something to return to the user */
1280 + if (!ret && IW_IS_GET(cmd)) {
1281 + err = copy_to_user(iwr->u.data.pointer, extra,
1282 + iwr->u.data.length *
1283 + descr->token_size);
1286 +#ifdef WE_IOCTL_DEBUG
1287 + printk(KERN_DEBUG "Wrote %d bytes\n",
1288 + iwr->u.data.length * descr->token_size);
1289 +#endif /* WE_IOCTL_DEBUG */
1292 + /* Cleanup - I told you it wasn't that long ;-) */
1296 + /* Call commit handler if needed and defined */
1297 + if(ret == -EIWCOMMIT)
1298 + ret = call_commit_handler(dev);
1300 + /* Here, we will generate the appropriate event if needed */
1305 +/* ---------------------------------------------------------------- */
1307 + * Wrapper to call a private Wireless Extension handler.
1308 + * We do various checks and also take care of moving data between
1309 + * user space and kernel space.
1310 + * It's not as nice and slimline as the standard wrapper. The cause
1311 + * is struct iw_priv_args, which was not really designed for the
1312 + * job we are going here.
1314 + * IMPORTANT : This function prevent to set and get data on the same
1315 + * IOCTL and enforce the SET/GET convention. Not doing it would be
1316 + * far too hairy...
1317 + * If you need to set and get data at the same time, please don't use
1318 + * a iw_handler but process it in your ioctl handler (i.e. use the
1319 + * old driver API).
1321 +static inline int ioctl_private_call(struct net_device * dev,
1322 + struct ifreq * ifr,
1324 + iw_handler handler)
1326 + struct iwreq * iwr = (struct iwreq *) ifr;
1327 + struct iw_priv_args * descr = NULL;
1328 + struct iw_request_info info;
1329 + int extra_size = 0;
1331 + int ret = -EINVAL;
1333 + /* Get the description of the IOCTL */
1334 + for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
1335 + if(cmd == dev->wireless_handlers->private_args[i].cmd) {
1336 + descr = &(dev->wireless_handlers->private_args[i]);
1340 +#ifdef WE_IOCTL_DEBUG
1341 + printk(KERN_DEBUG "%s : Found private handler for 0x%04X\n",
1342 + ifr->ifr_name, cmd);
1344 + printk(KERN_DEBUG "Name %s, set %X, get %X\n",
1345 + descr->name, descr->set_args, descr->get_args);
1347 +#endif /* WE_IOCTL_DEBUG */
1349 + /* Compute the size of the set/get arguments */
1350 + if(descr != NULL) {
1351 + if(IW_IS_SET(cmd)) {
1352 + /* Size of set arguments */
1353 + extra_size = get_priv_size(descr->set_args);
1355 + /* Does it fits in iwr ? */
1356 + if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
1357 + (extra_size < IFNAMSIZ))
1360 + /* Size of set arguments */
1361 + extra_size = get_priv_size(descr->get_args);
1363 + /* Does it fits in iwr ? */
1364 + if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
1365 + (extra_size < IFNAMSIZ))
1370 + /* Prepare the call */
1374 + /* Check if we have a pointer to user space data or not. */
1375 + if(extra_size == 0) {
1376 + /* No extra arguments. Trivial to handle */
1377 + ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u));
1382 + /* Check what user space is giving us */
1383 + if(IW_IS_SET(cmd)) {
1384 + /* Check NULL pointer */
1385 + if((iwr->u.data.pointer == NULL) &&
1386 + (iwr->u.data.length != 0))
1389 + /* Does it fits within bounds ? */
1390 + if(iwr->u.data.length > (descr->set_args &
1391 + IW_PRIV_SIZE_MASK))
1394 + /* Check NULL pointer */
1395 + if(iwr->u.data.pointer == NULL)
1399 +#ifdef WE_IOCTL_DEBUG
1400 + printk(KERN_DEBUG "Malloc %d bytes\n", extra_size);
1401 +#endif /* WE_IOCTL_DEBUG */
1403 + /* Always allocate for max space. Easier, and won't last
1405 + extra = kmalloc(extra_size, GFP_KERNEL);
1406 + if (extra == NULL) {
1410 + /* If it is a SET, get all the extra data in here */
1411 + if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
1412 + err = copy_from_user(extra, iwr->u.data.pointer,
1418 +#ifdef WE_IOCTL_DEBUG
1419 + printk(KERN_DEBUG "Got %d elem\n", iwr->u.data.length);
1420 +#endif /* WE_IOCTL_DEBUG */
1423 + /* Call the handler */
1424 + ret = handler(dev, &info, &(iwr->u), extra);
1426 + /* If we have something to return to the user */
1427 + if (!ret && IW_IS_GET(cmd)) {
1428 + err = copy_to_user(iwr->u.data.pointer, extra,
1432 +#ifdef WE_IOCTL_DEBUG
1433 + printk(KERN_DEBUG "Wrote %d elem\n",
1434 + iwr->u.data.length);
1435 +#endif /* WE_IOCTL_DEBUG */
1438 + /* Cleanup - I told you it wasn't that long ;-) */
1443 + /* Call commit handler if needed and defined */
1444 + if(ret == -EIWCOMMIT)
1445 + ret = call_commit_handler(dev);
1450 +/* ---------------------------------------------------------------- */
1452 + * Main IOCTl dispatcher. Called from the main networking code
1453 + * (dev_ioctl() in net/core/dev.c).
1454 + * Check the type of IOCTL and call the appropriate wrapper...
1456 +int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
1458 + struct net_device *dev;
1459 + iw_handler handler;
1461 + /* Permissions are already checked in dev_ioctl() before calling us.
1462 + * The copy_to/from_user() of ifr is also dealt with in there */
1464 + /* Make sure the device exist */
1465 + if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
1468 + /* A bunch of special cases, then the generic case...
1469 + * Note that 'cmd' is already filtered in dev_ioctl() with
1470 + * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
1473 + case SIOCGIWSTATS:
1474 + /* Get Wireless Stats */
1475 + return dev_iwstats(dev, ifr);
1478 + /* Check if we have some wireless handlers defined */
1479 + if(dev->wireless_handlers != NULL) {
1480 + /* We export to user space the definition of
1481 + * the private handler ourselves */
1482 + return ioctl_export_private(dev, ifr);
1484 + // ## Fall-through for old API ##
1486 + /* Generic IOCTL */
1488 + if (!netif_device_present(dev))
1490 + /* New driver API : try to find the handler */
1491 + handler = get_handler(dev, cmd);
1492 + if(handler != NULL) {
1493 + /* Standard and private are not the same */
1494 + if(cmd < SIOCIWFIRSTPRIV)
1495 + return ioctl_standard_call(dev,
1500 + return ioctl_private_call(dev,
1505 + /* Old driver API : call driver ioctl handler */
1506 + if (dev->do_ioctl) {
1507 + return dev->do_ioctl(dev, ifr, cmd);
1509 + return -EOPNOTSUPP;