1 diff -u -p -r --new-file linux/include/linux-w13/rtnetlink.h linux/include/linux/rtnetlink.h
2 --- linux/include/linux-w13/rtnetlink.h Thu Jun 6 14:44:08 2002
3 +++ linux/include/linux/rtnetlink.h Thu Jun 6 15:47:44 2002
4 @@ -440,12 +440,14 @@ enum
5 #define IFLA_COST IFLA_COST
7 #define IFLA_PRIORITY IFLA_PRIORITY
10 #define IFLA_MASTER IFLA_MASTER
11 + IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
12 +#define IFLA_WIRELESS IFLA_WIRELESS
16 -#define IFLA_MAX IFLA_MASTER
17 +#define IFLA_MAX IFLA_WIRELESS
19 #define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
20 #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
21 diff -u -p -r --new-file linux/include/linux-w13/wireless.h linux/include/linux/wireless.h
22 --- linux/include/linux-w13/wireless.h Thu Jun 6 15:00:28 2002
23 +++ linux/include/linux/wireless.h Thu Jun 6 15:47:44 2002
26 * This file define a set of standard wireless extensions
28 - * Version : 13 6.12.01
29 + * Version : 14 25.1.02
31 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
32 - * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
33 + * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
36 #ifndef _LINUX_WIRELESS_H
38 * # include/linux/netdevice.h (one place)
39 * # include/linux/proc_fs.h (one place)
41 - * New driver API (2001 -> onward) :
42 + * New driver API (2002 -> onward) :
43 * -------------------------------
44 * This file is only concerned with the user space API and common definitions.
45 * The new driver API is defined and documented in :
47 * Note as well that /proc/net/wireless implementation has now moved in :
48 * # include/linux/wireless.c
50 + * Wireless Events (2002 -> onward) :
51 + * --------------------------------
52 + * Events are defined at the end of this file, and implemented in :
53 + * # include/linux/wireless.c
57 * Do not add here things that are redundant with other mechanisms
59 * (there is some stuff that will be added in the future...)
60 * I just plan to increment with each new version.
62 -#define WIRELESS_EXT 13
63 +#define WIRELESS_EXT 14
68 * - Document creation of new driver API.
69 * - Extract union iwreq_data from struct iwreq (for new driver API).
70 * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
74 + * - Wireless Events support : define struct iw_event
75 + * - Define additional specific event numbers
76 + * - Add "addr" and "param" fields in union iwreq_data
77 + * - AP scanning stuff (SIOCSIWSCAN and friends)
80 /**************************** CONSTANTS ****************************/
82 #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
83 #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
84 #define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */
85 +#define SIOCSIWSCAN 0x8B18 /* trigger scanning */
86 +#define SIOCGIWSCAN 0x8B19 /* get scanning results */
88 /* 802.11 specific support */
89 #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
91 #define IW_IS_SET(cmd) (!((cmd) & 0x1))
92 #define IW_IS_GET(cmd) ((cmd) & 0x1)
94 +/* ----------------------- WIRELESS EVENTS ----------------------- */
95 +/* Those are *NOT* ioctls, do not issue request on them !!! */
96 +/* Most events use the same identifier as ioctl requests */
98 +#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
99 +#define IWEVQUAL 0x8C01 /* Quality part of statistics */
101 +#define IWEVFIRST 0x8C00
103 /* ------------------------- PRIVATE INFO ------------------------- */
105 * The following is used with SIOCGIWPRIV. It allow a driver to define
107 #define IW_RETRY_MAX 0x0002 /* Value is a maximum */
108 #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
110 +/* Scanning request flags */
111 +#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */
112 +#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */
113 +#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */
114 +#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */
115 +#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */
116 +#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */
117 +#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
118 +#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
119 +#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
120 +/* Maximum size of returned data */
121 +#define IW_SCAN_MAX_DATA 4096 /* In bytes */
123 /****************************** TYPES ******************************/
125 /* --------------------------- SUBTYPES --------------------------- */
126 @@ -466,9 +502,12 @@ union iwreq_data
128 struct iw_point encoding; /* Encoding stuff : tokens */
129 struct iw_param power; /* PM duration/timeout */
130 + struct iw_quality qual; /* Quality part of statistics */
132 struct sockaddr ap_addr; /* Access point address */
133 + struct sockaddr addr; /* Destination address (hw) */
135 + struct iw_param param; /* Other small parameters */
136 struct iw_point data; /* Other large parameters */
139 @@ -595,5 +634,36 @@ struct iw_priv_args
140 __u16 get_args; /* Type and number of args */
141 char name[IFNAMSIZ]; /* Name of the extension */
144 +/* ----------------------- WIRELESS EVENTS ----------------------- */
146 + * Wireless events are carried through the rtnetlink socket to user
147 + * space. They are encapsulated in the IFLA_WIRELESS field of
148 + * a RTM_NEWLINK message.
152 + * A Wireless Event. Contains basically the same data as the ioctl...
156 + __u16 len; /* Real lenght of this stuff */
157 + __u16 cmd; /* Wireless IOCTL */
158 + union iwreq_data u; /* IOCTL fixed payload */
161 +/* Size of the Event prefix (including padding and alignement junk) */
162 +#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data))
163 +/* Size of the various events */
164 +#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
165 +#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
166 +#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
167 +#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point))
168 +#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
169 +#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
170 +#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
172 +/* Note : in the case of iw_point, the extra data will come at the
173 + * end of the event */
175 #endif /* _LINUX_WIRELESS_H */
176 diff -u -p -r --new-file linux/include/net-w13/iw_handler.h linux/include/net/iw_handler.h
177 --- linux/include/net-w13/iw_handler.h Thu Jun 6 15:06:16 2002
178 +++ linux/include/net/iw_handler.h Thu Jun 6 15:48:06 2002
181 * This file define the new driver API for Wireless Extensions
183 - * Version : 2 6.12.01
184 + * Version : 3 17.1.02
186 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
187 - * Copyright (c) 2001 Jean Tourrilhes, All Rights Reserved.
188 + * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
191 #ifndef _IW_HANDLER_H
193 * o The user space interface is tied to ioctl because of the use
196 - * New driver API (2001 -> onward) :
197 + * New driver API (2002 -> onward) :
198 * -------------------------------
199 * The new driver API is just a bunch of standard functions (handlers),
200 * each handling a specific Wireless Extension. The driver just export
203 * I just plan to increment with each new version.
205 -#define IW_HANDLER_VERSION 2
206 +#define IW_HANDLER_VERSION 3
213 + * - Move event definition in <linux/wireless.h>
214 + * - Add Wireless Event support :
215 + * o wireless_send_event() prototype
216 + * o iwe_stream_add_event/point() inline functions
219 /**************************** CONSTANTS ****************************/
222 #define IW_HEADER_TYPE_POINT 6 /* struct iw_point */
223 #define IW_HEADER_TYPE_PARAM 7 /* struct iw_param */
224 #define IW_HEADER_TYPE_ADDR 8 /* struct sockaddr */
225 +#define IW_HEADER_TYPE_QUAL 9 /* struct iw_quality */
228 /* Most are not implemented. I just use them as a reminder of some
230 /* Wrapper level flags */
231 #define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
232 #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
233 -#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET request is ROOT only */
234 +#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
235 + /* SET : Omit payload from generated iwevent */
236 /* Driver level flags */
237 #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
239 @@ -303,25 +316,6 @@ struct iw_handler_def
240 * 'struct net_device' to here, to minimise bloat. */
243 -/* ----------------------- WIRELESS EVENTS ----------------------- */
245 - * Currently we don't support events, so let's just plan for the
250 - * A Wireless Event.
252 -// How do we define short header ? We don't want a flag on length.
253 -// Probably a flag on event ? Highest bit to zero...
256 - __u16 length; /* Lenght of this stuff */
257 - __u16 event; /* Wireless IOCTL */
258 - union iwreq_data header; /* IOCTL fixed payload */
259 - char extra[0]; /* Optional IOCTL data */
262 /* ---------------------- IOCTL DESCRIPTION ---------------------- */
264 * One of the main goal of the new interface is to deal entirely with
265 @@ -369,6 +363,88 @@ extern int dev_get_wireless_info(char *
266 extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
268 /* Second : functions that may be called by driver modules */
271 -#endif /* _LINUX_WIRELESS_H */
272 +/* Send a single event to user space */
273 +extern void wireless_send_event(struct net_device * dev,
275 + union iwreq_data * wrqu,
278 +/* We may need a function to send a stream of events to user space.
279 + * More on that later... */
281 +/************************* INLINE FUNTIONS *************************/
283 + * Function that are so simple that it's more efficient inlining them
286 +/*------------------------------------------------------------------*/
288 + * Wrapper to add an Wireless Event to a stream of events.
290 +static inline char *
291 +iwe_stream_add_event(char * stream, /* Stream of events */
292 + char * ends, /* End of stream */
293 + struct iw_event *iwe, /* Payload */
294 + int event_len) /* Real size of payload */
296 + /* Check if it's possible */
297 + if((stream + event_len) < ends) {
298 + iwe->len = event_len;
299 + memcpy(stream, (char *) iwe, event_len);
300 + stream += event_len;
305 +/*------------------------------------------------------------------*/
307 + * Wrapper to add an short Wireless Event containing a pointer to a
308 + * stream of events.
310 +static inline char *
311 +iwe_stream_add_point(char * stream, /* Stream of events */
312 + char * ends, /* End of stream */
313 + struct iw_event *iwe, /* Payload */
316 + int event_len = IW_EV_POINT_LEN + iwe->u.data.length;
317 + /* Check if it's possible */
318 + if((stream + event_len) < ends) {
319 + iwe->len = event_len;
320 + memcpy(stream, (char *) iwe, IW_EV_POINT_LEN);
321 + memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
322 + stream += event_len;
327 +/*------------------------------------------------------------------*/
329 + * Wrapper to add a value to a Wireless Event in a stream of events.
330 + * Be careful, this one is tricky to use properly :
331 + * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
333 +static inline char *
334 +iwe_stream_add_value(char * event, /* Event in the stream */
335 + char * value, /* Value in event */
336 + char * ends, /* End of stream */
337 + struct iw_event *iwe, /* Payload */
338 + int event_len) /* Real size of payload */
340 + /* Don't duplicate LCP */
341 + event_len -= IW_EV_LCP_LEN;
343 + /* Check if it's possible */
344 + if((value + event_len) < ends) {
345 + /* Add new value */
346 + memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
347 + value += event_len;
349 + iwe->len = value - event;
350 + memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
355 +#endif /* _IW_HANDLER_H */
356 diff -u -p -r --new-file linux/net/netsyms-w13.c linux/net/netsyms.c
357 --- linux/net/netsyms-w13.c Thu Jun 6 15:46:34 2002
358 +++ linux/net/netsyms.c Thu Jun 6 15:47:44 2002
359 @@ -588,4 +588,10 @@ EXPORT_SYMBOL(register_gifconf);
360 EXPORT_SYMBOL(net_call_rx_atomic);
361 EXPORT_SYMBOL(softnet_data);
363 +#if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
364 +/* Don't include the whole header mess for a single function */
365 +extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, char *extra);
366 +EXPORT_SYMBOL(wireless_send_event);
367 +#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
369 #endif /* CONFIG_NET */
370 diff -u -p -r --new-file linux/net/core/wireless-w13.c linux/net/core/wireless.c
371 --- linux/net/core/wireless-w13.c Thu Jun 6 15:46:45 2002
372 +++ linux/net/core/wireless.c Thu Jun 6 15:48:06 2002
374 * This file implement the Wireless Extensions APIs.
376 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
377 - * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
378 + * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
380 * (As all part of the Linux kernel, this file is GPL)
383 * o Added iw_handler handling ;-)
384 * o Added standard ioctl description
385 * o Initial dumb commit strategy based on orinoco.c
387 + * v3 - 19.12.01 - Jean II
388 + * o Make sure we don't go out of standard_ioctl[] in ioctl_standard_call
389 + * o Add event dispatcher function
390 + * o Add event description
391 + * o Propagate events as rtnetlink IFLA_WIRELESS option
392 + * o Generate event on selected SET requests
394 + * v4 - 18.04.01 - Jean II
395 + * o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1
398 /***************************** INCLUDES *****************************/
400 #include <linux/config.h> /* Not needed ??? */
401 #include <linux/types.h> /* off_t */
402 #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
403 +#include <linux/rtnetlink.h> /* rtnetlink stuff */
405 #include <linux/wireless.h> /* Pretty obvious */
406 #include <net/iw_handler.h> /* New driver API */
410 #undef WE_IOCTL_DEBUG /* Debug IOCTL API */
411 +#undef WE_EVENT_DEBUG /* Debug Event dispatcher */
414 +#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */
415 +#define WE_SET_EVENT /* Generate an event on some set commands */
417 /************************* GLOBAL VARIABLES *************************/
419 * You should not use global variables, because or re-entrancy.
420 * On our case, it's only const, so it's OK...
423 + * Meta-data about all the standard Wireless Extension request we
426 static const struct iw_ioctl_description standard_ioctl[] = {
427 - /* SIOCSIWCOMMIT (internal) */
428 + /* SIOCSIWCOMMIT */
429 { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
431 { IW_HEADER_TYPE_CHAR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
432 @@ -99,18 +119,18 @@ static const struct iw_ioctl_description
433 { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
435 { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
437 - { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
439 - { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
441 + { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
443 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0},
445 - { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_EVENT},
446 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT},
448 - { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_DUMP},
449 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_DUMP},
451 - { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0},
452 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0},
454 - { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0},
455 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0},
457 { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
459 @@ -136,7 +156,7 @@ static const struct iw_ioctl_description
461 { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
463 - { IW_HEADER_TYPE_POINT, 4, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT},
464 + { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT},
466 { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT},
468 @@ -144,9 +164,38 @@ static const struct iw_ioctl_description
470 { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
472 +static const int standard_ioctl_num = (sizeof(standard_ioctl) /
473 + sizeof(struct iw_ioctl_description));
476 + * Meta-data about all the additional standard Wireless Extension events
479 +static const struct iw_ioctl_description standard_event[] = {
481 + { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
483 + { IW_HEADER_TYPE_QUAL, 0, 0, 0, 0, 0},
485 +static const int standard_event_num = (sizeof(standard_event) /
486 + sizeof(struct iw_ioctl_description));
488 /* Size (in bytes) of the various private data types */
489 -char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 };
490 +static const char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 };
492 +/* Size (in bytes) of various events */
493 +static const int event_type_size[] = {
500 + IW_EV_POINT_LEN, /* Without variable payload */
506 /************************ COMMON SUBROUTINES ************************/
508 @@ -162,7 +211,8 @@ char priv_type_size[] = { 0, 1, 1, 0, 4,
509 static inline iw_handler get_handler(struct net_device *dev,
512 - unsigned int index; /* MUST be unsigned */
513 + /* Don't "optimise" the following variable, it will crash */
514 + unsigned int index; /* *MUST* be unsigned */
516 /* Check if we have some wireless handlers defined */
517 if(dev->wireless_handlers == NULL)
518 @@ -269,9 +319,9 @@ static inline int sprintf_wireless_stats
521 stats->qual.updated & 1 ? '.' : ' ',
523 + ((__u8) stats->qual.level),
524 stats->qual.updated & 2 ? '.' : ' ',
526 + ((__u8) stats->qual.noise),
527 stats->qual.updated & 4 ? '.' : ' ',
530 @@ -423,12 +473,14 @@ static inline int ioctl_standard_call(st
533 /* Get the description of the IOCTL */
534 + if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
535 + return -EOPNOTSUPP;
536 descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
538 #ifdef WE_IOCTL_DEBUG
539 - printk(KERN_DEBUG "%s : Found standard handler for 0x%04X\n",
540 + printk(KERN_DEBUG "%s (WE) : Found standard handler for 0x%04X\n",
542 - 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);
543 + 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);
544 #endif /* WE_IOCTL_DEBUG */
546 /* Prepare the call */
547 @@ -437,8 +489,16 @@ static inline int ioctl_standard_call(st
549 /* Check if we have a pointer to user space data or not */
550 if(descr->header_type != IW_HEADER_TYPE_POINT) {
552 /* No extra arguments. Trivial to handle */
553 ret = handler(dev, &info, &(iwr->u), NULL);
556 + /* Generate an event to notify listeners of the change */
557 + if((descr->flags & IW_DESCR_FLAG_EVENT) &&
558 + ((ret == 0) || (ret == -EIWCOMMIT)))
559 + wireless_send_event(dev, cmd, &(iwr->u), NULL);
560 +#endif /* WE_SET_EVENT */
564 @@ -466,8 +526,8 @@ static inline int ioctl_standard_call(st
567 #ifdef WE_IOCTL_DEBUG
568 - printk(KERN_DEBUG "Malloc %d bytes\n",
569 - descr->max_tokens * descr->token_size);
570 + printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
571 + dev->name, descr->max_tokens * descr->token_size);
572 #endif /* WE_IOCTL_DEBUG */
574 /* Always allocate for max space. Easier, and won't last
575 @@ -488,7 +548,8 @@ static inline int ioctl_standard_call(st
578 #ifdef WE_IOCTL_DEBUG
579 - printk(KERN_DEBUG "Got %d bytes\n",
580 + printk(KERN_DEBUG "%s (WE) : Got %d bytes\n",
582 iwr->u.data.length * descr->token_size);
583 #endif /* WE_IOCTL_DEBUG */
585 @@ -504,11 +565,26 @@ static inline int ioctl_standard_call(st
588 #ifdef WE_IOCTL_DEBUG
589 - printk(KERN_DEBUG "Wrote %d bytes\n",
590 + printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n",
592 iwr->u.data.length * descr->token_size);
593 #endif /* WE_IOCTL_DEBUG */
597 + /* Generate an event to notify listeners of the change */
598 + if((descr->flags & IW_DESCR_FLAG_EVENT) &&
599 + ((ret == 0) || (ret == -EIWCOMMIT))) {
600 + if(descr->flags & IW_DESCR_FLAG_RESTRICT)
601 + /* If the event is restricted, don't
602 + * export the payload */
603 + wireless_send_event(dev, cmd, &(iwr->u), NULL);
605 + wireless_send_event(dev, cmd, &(iwr->u),
608 +#endif /* WE_SET_EVENT */
610 /* Cleanup - I told you it wasn't that long ;-) */
613 @@ -558,11 +634,12 @@ static inline int ioctl_private_call(str
616 #ifdef WE_IOCTL_DEBUG
617 - printk(KERN_DEBUG "%s : Found private handler for 0x%04X\n",
618 + printk(KERN_DEBUG "%s (WE) : Found private handler for 0x%04X\n",
621 - printk(KERN_DEBUG "Name %s, set %X, get %X\n",
622 - descr->name, descr->set_args, descr->get_args);
623 + printk(KERN_DEBUG "%s (WE) : Name %s, set %X, get %X\n",
624 + dev->name, descr->name,
625 + descr->set_args, descr->get_args);
627 #endif /* WE_IOCTL_DEBUG */
629 @@ -617,7 +694,8 @@ static inline int ioctl_private_call(str
632 #ifdef WE_IOCTL_DEBUG
633 - printk(KERN_DEBUG "Malloc %d bytes\n", extra_size);
634 + printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
635 + dev->name, extra_size);
636 #endif /* WE_IOCTL_DEBUG */
638 /* Always allocate for max space. Easier, and won't last
639 @@ -636,7 +714,8 @@ static inline int ioctl_private_call(str
642 #ifdef WE_IOCTL_DEBUG
643 - printk(KERN_DEBUG "Got %d elem\n", iwr->u.data.length);
644 + printk(KERN_DEBUG "%s (WE) : Got %d elem\n",
645 + dev->name, iwr->u.data.length);
646 #endif /* WE_IOCTL_DEBUG */
649 @@ -650,8 +729,8 @@ static inline int ioctl_private_call(str
652 #ifdef WE_IOCTL_DEBUG
653 - printk(KERN_DEBUG "Wrote %d elem\n",
654 - iwr->u.data.length);
655 + printk(KERN_DEBUG "%s (WE) : Wrote %d elem\n",
656 + dev->name, iwr->u.data.length);
657 #endif /* WE_IOCTL_DEBUG */
660 @@ -730,4 +809,178 @@ int wireless_process_ioctl(struct ifreq
666 +/************************* EVENT PROCESSING *************************/
668 + * Process events generated by the wireless layer or the driver.
669 + * Most often, the event will be propagated through rtnetlink
672 +#ifdef WE_EVENT_NETLINK
673 +/* "rtnl" is defined in net/core/rtnetlink.c, but we need it here.
674 + * It is declared in <linux/rtnetlink.h> */
676 +/* ---------------------------------------------------------------- */
678 + * Fill a rtnetlink message with our event data.
679 + * Note that we propage only the specified event and don't dump the
680 + * current wireless config. Dumping the wireless config is far too
681 + * expensive (for each parameter, the driver need to query the hardware).
683 +static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb,
684 + struct net_device * dev,
689 + struct ifinfomsg *r;
690 + struct nlmsghdr *nlh;
691 + unsigned char *b = skb->tail;
693 + nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(*r));
694 + r = NLMSG_DATA(nlh);
695 + r->ifi_family = AF_UNSPEC;
696 + r->ifi_type = dev->type;
697 + r->ifi_index = dev->ifindex;
698 + r->ifi_flags = dev->flags;
699 + r->ifi_change = 0; /* Wireless changes don't affect those flags */
701 + /* Add the wireless events in the netlink packet */
702 + RTA_PUT(skb, IFLA_WIRELESS,
705 + nlh->nlmsg_len = skb->tail - b;
710 + skb_trim(skb, b - skb->data);
714 +/* ---------------------------------------------------------------- */
716 + * Create and broadcast and send it on the standard rtnetlink socket
717 + * This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c
718 + * Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field
719 + * within a RTM_NEWLINK event.
721 +static inline void rtmsg_iwinfo(struct net_device * dev,
725 + struct sk_buff *skb;
726 + int size = NLMSG_GOODSIZE;
728 + skb = alloc_skb(size, GFP_ATOMIC);
732 + if (rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK,
733 + event, event_len) < 0) {
737 + NETLINK_CB(skb).dst_groups = RTMGRP_LINK;
738 + netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_ATOMIC);
740 +#endif /* WE_EVENT_NETLINK */
742 +/* ---------------------------------------------------------------- */
744 + * Main event dispatcher. Called from other parts and drivers.
745 + * Send the event on the apropriate channels.
746 + * May be called from interrupt context.
748 +void wireless_send_event(struct net_device * dev,
750 + union iwreq_data * wrqu,
753 + const struct iw_ioctl_description * descr = NULL;
755 + struct iw_event *event; /* Mallocated whole event */
756 + int event_len; /* Its size */
757 + int hdr_len; /* Size of the event header */
758 + /* Don't "optimise" the following variable, it will crash */
759 + unsigned cmd_index; /* *MUST* be unsigned */
761 + /* Get the description of the IOCTL */
762 + if(cmd <= SIOCIWLAST) {
763 + cmd_index = cmd - SIOCIWFIRST;
764 + if(cmd_index < standard_ioctl_num)
765 + descr = &(standard_ioctl[cmd_index]);
767 + cmd_index = cmd - IWEVFIRST;
768 + if(cmd_index < standard_event_num)
769 + descr = &(standard_event[cmd_index]);
771 + /* Don't accept unknown events */
772 + if(descr == NULL) {
773 + /* Note : we don't return an error to the driver, because
774 + * the driver would not know what to do about it. It can't
775 + * return an error to the user, because the event is not
776 + * initiated by a user request.
777 + * The best the driver could do is to log an error message.
778 + * We will do it ourselves instead...
780 + printk(KERN_ERR "%s (WE) : Invalid Wireless Event (0x%04X)\n",
784 +#ifdef WE_EVENT_DEBUG
785 + printk(KERN_DEBUG "%s (WE) : Got event 0x%04X\n",
787 + 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);
788 +#endif /* WE_EVENT_DEBUG */
790 + /* Check extra parameters and set extra_len */
791 + if(descr->header_type == IW_HEADER_TYPE_POINT) {
792 + /* Check if number of token fits within bounds */
793 + if(wrqu->data.length > descr->max_tokens) {
794 + printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length);
797 + if(wrqu->data.length < descr->min_tokens) {
798 + printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length);
801 + /* Calculate extra_len - extra is NULL for restricted events */
803 + extra_len = wrqu->data.length * descr->token_size;
804 +#ifdef WE_EVENT_DEBUG
805 + printk(KERN_DEBUG "%s (WE) : Event 0x%04X, tokens %d, extra_len %d\n", dev->name, cmd, wrqu->data.length, extra_len);
806 +#endif /* WE_EVENT_DEBUG */
809 + /* Total length of the event */
810 + hdr_len = event_type_size[descr->header_type];
811 + event_len = hdr_len + extra_len;
813 +#ifdef WE_EVENT_DEBUG
814 + printk(KERN_DEBUG "%s (WE) : Event 0x%04X, hdr_len %d, event_len %d\n", dev->name, cmd, hdr_len, event_len);
815 +#endif /* WE_EVENT_DEBUG */
817 + /* Create temporary buffer to hold the event */
818 + event = kmalloc(event_len, GFP_ATOMIC);
823 + event->len = event_len;
825 + memcpy(&event->u, wrqu, hdr_len - IW_EV_LCP_LEN);
827 + memcpy(((char *) event) + hdr_len, extra, extra_len);
829 +#ifdef WE_EVENT_NETLINK
830 + /* rtnetlink event channel */
831 + rtmsg_iwinfo(dev, (char *) event, event_len);
832 +#endif /* WE_EVENT_NETLINK */
837 + return; /* Always success, I guess ;-) */