]> git.pld-linux.org Git - packages/kernel.git/blame - iw_handlers.w14-5.diff
- fix unresolved symbols in ipv6 netfilter
[packages/kernel.git] / iw_handlers.w14-5.diff
CommitLineData
3bccf403
AM
1diff -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
6 IFLA_PRIORITY,
7 #define IFLA_PRIORITY IFLA_PRIORITY
8- IFLA_MASTER
9+ IFLA_MASTER,
10 #define IFLA_MASTER IFLA_MASTER
11+ IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
12+#define IFLA_WIRELESS IFLA_WIRELESS
13 };
14
15
16-#define IFLA_MAX IFLA_MASTER
17+#define IFLA_MAX IFLA_WIRELESS
18
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))
21diff -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
24@@ -1,10 +1,10 @@
25 /*
26 * This file define a set of standard wireless extensions
27 *
28- * Version : 13 6.12.01
29+ * Version : 14 25.1.02
30 *
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.
34 */
35
36 #ifndef _LINUX_WIRELESS_H
37@@ -40,7 +40,7 @@
38 * # include/linux/netdevice.h (one place)
39 * # include/linux/proc_fs.h (one place)
40 *
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 :
46@@ -49,6 +49,11 @@
47 * Note as well that /proc/net/wireless implementation has now moved in :
48 * # include/linux/wireless.c
49 *
50+ * Wireless Events (2002 -> onward) :
51+ * --------------------------------
52+ * Events are defined at the end of this file, and implemented in :
53+ * # include/linux/wireless.c
54+ *
55 * Other comments :
56 * --------------
57 * Do not add here things that are redundant with other mechanisms
58@@ -75,7 +80,7 @@
59 * (there is some stuff that will be added in the future...)
60 * I just plan to increment with each new version.
61 */
62-#define WIRELESS_EXT 13
63+#define WIRELESS_EXT 14
64
65 /*
66 * Changes :
67@@ -141,6 +146,13 @@
68 * - Document creation of new driver API.
69 * - Extract union iwreq_data from struct iwreq (for new driver API).
70 * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
71+ *
72+ * V13 to V14
73+ * ----------
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)
78 */
79
80 /**************************** CONSTANTS ****************************/
81@@ -175,6 +187,8 @@
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 */
87
88 /* 802.11 specific support */
89 #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
90@@ -238,6 +252,15 @@
91 #define IW_IS_SET(cmd) (!((cmd) & 0x1))
92 #define IW_IS_GET(cmd) ((cmd) & 0x1)
93
94+/* ----------------------- WIRELESS EVENTS ----------------------- */
95+/* Those are *NOT* ioctls, do not issue request on them !!! */
96+/* Most events use the same identifier as ioctl requests */
97+
98+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
99+#define IWEVQUAL 0x8C01 /* Quality part of statistics */
100+
101+#define IWEVFIRST 0x8C00
102+
103 /* ------------------------- PRIVATE INFO ------------------------- */
104 /*
105 * The following is used with SIOCGIWPRIV. It allow a driver to define
106@@ -340,6 +363,19 @@
107 #define IW_RETRY_MAX 0x0002 /* Value is a maximum */
108 #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
109
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 */
122+
123 /****************************** TYPES ******************************/
124
125 /* --------------------------- SUBTYPES --------------------------- */
126@@ -466,9 +502,12 @@ union iwreq_data
127
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 */
131
132 struct sockaddr ap_addr; /* Access point address */
133+ struct sockaddr addr; /* Destination address (hw) */
134
135+ struct iw_param param; /* Other small parameters */
136 struct iw_point data; /* Other large parameters */
137 };
138
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 */
142 };
143+
144+/* ----------------------- WIRELESS EVENTS ----------------------- */
145+/*
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.
149+ */
150+
151+/*
152+ * A Wireless Event. Contains basically the same data as the ioctl...
153+ */
154+struct iw_event
155+{
156+ __u16 len; /* Real lenght of this stuff */
157+ __u16 cmd; /* Wireless IOCTL */
158+ union iwreq_data u; /* IOCTL fixed payload */
159+};
160+
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))
171+
172+/* Note : in the case of iw_point, the extra data will come at the
173+ * end of the event */
174
175 #endif /* _LINUX_WIRELESS_H */
176diff -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
179@@ -1,10 +1,10 @@
180 /*
181 * This file define the new driver API for Wireless Extensions
182 *
183- * Version : 2 6.12.01
184+ * Version : 3 17.1.02
185 *
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.
189 */
190
191 #ifndef _IW_HANDLER_H
192@@ -33,7 +33,7 @@
193 * o The user space interface is tied to ioctl because of the use
194 * copy_to/from_user.
195 *
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
201@@ -206,7 +206,18 @@
202 * will be needed...
203 * I just plan to increment with each new version.
204 */
205-#define IW_HANDLER_VERSION 2
206+#define IW_HANDLER_VERSION 3
207+
208+/*
209+ * Changes :
210+ *
211+ * V2 to V3
212+ * --------
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
217+ */
218
219 /**************************** CONSTANTS ****************************/
220
221@@ -225,6 +236,7 @@
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 */
226
227 /* Handling flags */
228 /* Most are not implemented. I just use them as a reminder of some
229@@ -233,7 +245,8 @@
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 */
238
239@@ -303,25 +316,6 @@ struct iw_handler_def
240 * 'struct net_device' to here, to minimise bloat. */
241 };
242
243-/* ----------------------- WIRELESS EVENTS ----------------------- */
244-/*
245- * Currently we don't support events, so let's just plan for the
246- * future...
247- */
248-
249-/*
250- * A Wireless Event.
251- */
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...
254-struct iw_event
255-{
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 */
260-};
261-
262 /* ---------------------- IOCTL DESCRIPTION ---------------------- */
263 /*
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);
267
268 /* Second : functions that may be called by driver modules */
269-/* None yet */
270
271-#endif /* _LINUX_WIRELESS_H */
272+/* Send a single event to user space */
273+extern void wireless_send_event(struct net_device * dev,
274+ unsigned int cmd,
275+ union iwreq_data * wrqu,
276+ char * extra);
277+
278+/* We may need a function to send a stream of events to user space.
279+ * More on that later... */
280+
281+/************************* INLINE FUNTIONS *************************/
282+/*
283+ * Function that are so simple that it's more efficient inlining them
284+ */
285+
286+/*------------------------------------------------------------------*/
287+/*
288+ * Wrapper to add an Wireless Event to a stream of events.
289+ */
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 */
295+{
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;
301+ }
302+ return stream;
303+}
304+
305+/*------------------------------------------------------------------*/
306+/*
307+ * Wrapper to add an short Wireless Event containing a pointer to a
308+ * stream of events.
309+ */
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 */
314+ char * extra)
315+{
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;
323+ }
324+ return stream;
325+}
326+
327+/*------------------------------------------------------------------*/
328+/*
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).
332+ */
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 */
339+{
340+ /* Don't duplicate LCP */
341+ event_len -= IW_EV_LCP_LEN;
342+
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;
348+ /* Patch LCP */
349+ iwe->len = value - event;
350+ memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
351+ }
352+ return value;
353+}
354+
355+#endif /* _IW_HANDLER_H */
356diff -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);
362
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 */
368+
369 #endif /* CONFIG_NET */
370diff -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
373@@ -2,7 +2,7 @@
374 * This file implement the Wireless Extensions APIs.
375 *
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.
379 *
380 * (As all part of the Linux kernel, this file is GPL)
381 */
382@@ -25,6 +25,16 @@
383 * o Added iw_handler handling ;-)
384 * o Added standard ioctl description
385 * o Initial dumb commit strategy based on orinoco.c
386+ *
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
393+ *
394+ * v4 - 18.04.01 - Jean II
395+ * o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1
396 */
397
398 /***************************** INCLUDES *****************************/
399@@ -33,6 +43,7 @@
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 */
404
405 #include <linux/wireless.h> /* Pretty obvious */
406 #include <net/iw_handler.h> /* New driver API */
407@@ -44,14 +55,23 @@
408
409 /* Debuging stuff */
410 #undef WE_IOCTL_DEBUG /* Debug IOCTL API */
411+#undef WE_EVENT_DEBUG /* Debug Event dispatcher */
412+
413+/* Options */
414+#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */
415+#define WE_SET_EVENT /* Generate an event on some set commands */
416
417 /************************* GLOBAL VARIABLES *************************/
418 /*
419 * You should not use global variables, because or re-entrancy.
420 * On our case, it's only const, so it's OK...
421 */
422+/*
423+ * Meta-data about all the standard Wireless Extension request we
424+ * know about.
425+ */
426 static const struct iw_ioctl_description standard_ioctl[] = {
427- /* SIOCSIWCOMMIT (internal) */
428+ /* SIOCSIWCOMMIT */
429 { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
430 /* SIOCGIWNAME */
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},
434 /* SIOCGIWAPLIST */
435 { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
436- /* -- hole -- */
437- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
438- /* -- hole -- */
439- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
440+ /* SIOCSIWSCAN */
441+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
442+ /* SIOCGIWSCAN */
443+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0},
444 /* SIOCSIWESSID */
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},
447 /* SIOCGIWESSID */
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},
450 /* SIOCSIWNICKN */
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},
453 /* SIOCGIWNICKN */
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},
456 /* -- hole -- */
457 { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
458 /* -- hole -- */
459@@ -136,7 +156,7 @@ static const struct iw_ioctl_description
460 /* SIOCGIWRETRY */
461 { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
462 /* SIOCSIWENCODE */
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},
465 /* SIOCGIWENCODE */
466 { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT},
467 /* SIOCSIWPOWER */
468@@ -144,9 +164,38 @@ static const struct iw_ioctl_description
469 /* SIOCGIWPOWER */
470 { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
471 };
472+static const int standard_ioctl_num = (sizeof(standard_ioctl) /
473+ sizeof(struct iw_ioctl_description));
474+
475+/*
476+ * Meta-data about all the additional standard Wireless Extension events
477+ * we know about.
478+ */
479+static const struct iw_ioctl_description standard_event[] = {
480+ /* IWEVTXDROP */
481+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
482+ /* IWEVQUAL */
483+ { IW_HEADER_TYPE_QUAL, 0, 0, 0, 0, 0},
484+};
485+static const int standard_event_num = (sizeof(standard_event) /
486+ sizeof(struct iw_ioctl_description));
487
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 };
491+
492+/* Size (in bytes) of various events */
493+static const int event_type_size[] = {
494+ IW_EV_LCP_LEN,
495+ 0,
496+ IW_EV_CHAR_LEN,
497+ 0,
498+ IW_EV_UINT_LEN,
499+ IW_EV_FREQ_LEN,
500+ IW_EV_POINT_LEN, /* Without variable payload */
501+ IW_EV_PARAM_LEN,
502+ IW_EV_ADDR_LEN,
503+ IW_EV_QUAL_LEN,
504+};
505
506 /************************ COMMON SUBROUTINES ************************/
507 /*
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,
510 unsigned int cmd)
511 {
512- unsigned int index; /* MUST be unsigned */
513+ /* Don't "optimise" the following variable, it will crash */
514+ unsigned int index; /* *MUST* be unsigned */
515
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
519 stats->status,
520 stats->qual.qual,
521 stats->qual.updated & 1 ? '.' : ' ',
522- stats->qual.level,
523+ ((__u8) stats->qual.level),
524 stats->qual.updated & 2 ? '.' : ' ',
525- stats->qual.noise,
526+ ((__u8) stats->qual.noise),
527 stats->qual.updated & 4 ? '.' : ' ',
528 stats->discard.nwid,
529 stats->discard.code,
530@@ -423,12 +473,14 @@ static inline int ioctl_standard_call(st
531 int ret = -EINVAL;
532
533 /* Get the description of the IOCTL */
534+ if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
535+ return -EOPNOTSUPP;
536 descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
537
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",
541 ifr->ifr_name, cmd);
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 */
545
546 /* Prepare the call */
547@@ -437,8 +489,16 @@ static inline int ioctl_standard_call(st
548
549 /* Check if we have a pointer to user space data or not */
550 if(descr->header_type != IW_HEADER_TYPE_POINT) {
551+
552 /* No extra arguments. Trivial to handle */
553 ret = handler(dev, &info, &(iwr->u), NULL);
554+
555+#ifdef WE_SET_EVENT
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 */
561 } else {
562 char * extra;
563 int err;
564@@ -466,8 +526,8 @@ static inline int ioctl_standard_call(st
565 }
566
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 */
573
574 /* Always allocate for max space. Easier, and won't last
575@@ -488,7 +548,8 @@ static inline int ioctl_standard_call(st
576 return -EFAULT;
577 }
578 #ifdef WE_IOCTL_DEBUG
579- printk(KERN_DEBUG "Got %d bytes\n",
580+ printk(KERN_DEBUG "%s (WE) : Got %d bytes\n",
581+ dev->name,
582 iwr->u.data.length * descr->token_size);
583 #endif /* WE_IOCTL_DEBUG */
584 }
585@@ -504,11 +565,26 @@ static inline int ioctl_standard_call(st
586 if (err)
587 ret = -EFAULT;
588 #ifdef WE_IOCTL_DEBUG
589- printk(KERN_DEBUG "Wrote %d bytes\n",
590+ printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n",
591+ dev->name,
592 iwr->u.data.length * descr->token_size);
593 #endif /* WE_IOCTL_DEBUG */
594 }
595
596+#ifdef WE_SET_EVENT
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);
604+ else
605+ wireless_send_event(dev, cmd, &(iwr->u),
606+ extra);
607+ }
608+#endif /* WE_SET_EVENT */
609+
610 /* Cleanup - I told you it wasn't that long ;-) */
611 kfree(extra);
612 }
613@@ -558,11 +634,12 @@ static inline int ioctl_private_call(str
614 }
615
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",
619 ifr->ifr_name, cmd);
620 if(descr) {
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);
626 }
627 #endif /* WE_IOCTL_DEBUG */
628
629@@ -617,7 +694,8 @@ static inline int ioctl_private_call(str
630 }
631
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 */
637
638 /* Always allocate for max space. Easier, and won't last
639@@ -636,7 +714,8 @@ static inline int ioctl_private_call(str
640 return -EFAULT;
641 }
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 */
647 }
648
649@@ -650,8 +729,8 @@ static inline int ioctl_private_call(str
650 if (err)
651 ret = -EFAULT;
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 */
658 }
659
660@@ -730,4 +809,178 @@ int wireless_process_ioctl(struct ifreq
661 }
662 /* Not reached */
663 return -EINVAL;
664+}
665+
666+/************************* EVENT PROCESSING *************************/
667+/*
668+ * Process events generated by the wireless layer or the driver.
669+ * Most often, the event will be propagated through rtnetlink
670+ */
671+
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> */
675+
676+/* ---------------------------------------------------------------- */
677+/*
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).
682+ */
683+static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb,
684+ struct net_device * dev,
685+ int type,
686+ char * event,
687+ int event_len)
688+{
689+ struct ifinfomsg *r;
690+ struct nlmsghdr *nlh;
691+ unsigned char *b = skb->tail;
692+
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 */
700+
701+ /* Add the wireless events in the netlink packet */
702+ RTA_PUT(skb, IFLA_WIRELESS,
703+ event_len, event);
704+
705+ nlh->nlmsg_len = skb->tail - b;
706+ return skb->len;
707+
708+nlmsg_failure:
709+rtattr_failure:
710+ skb_trim(skb, b - skb->data);
711+ return -1;
712+}
713+
714+/* ---------------------------------------------------------------- */
715+/*
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.
720+ */
721+static inline void rtmsg_iwinfo(struct net_device * dev,
722+ char * event,
723+ int event_len)
724+{
725+ struct sk_buff *skb;
726+ int size = NLMSG_GOODSIZE;
727+
728+ skb = alloc_skb(size, GFP_ATOMIC);
729+ if (!skb)
730+ return;
731+
732+ if (rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK,
733+ event, event_len) < 0) {
734+ kfree_skb(skb);
735+ return;
736+ }
737+ NETLINK_CB(skb).dst_groups = RTMGRP_LINK;
738+ netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_ATOMIC);
739+}
740+#endif /* WE_EVENT_NETLINK */
741+
742+/* ---------------------------------------------------------------- */
743+/*
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.
747+ */
748+void wireless_send_event(struct net_device * dev,
749+ unsigned int cmd,
750+ union iwreq_data * wrqu,
751+ char * extra)
752+{
753+ const struct iw_ioctl_description * descr = NULL;
754+ int extra_len = 0;
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 */
760+
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]);
766+ } else {
767+ cmd_index = cmd - IWEVFIRST;
768+ if(cmd_index < standard_event_num)
769+ descr = &(standard_event[cmd_index]);
770+ }
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...
779+ */
780+ printk(KERN_ERR "%s (WE) : Invalid Wireless Event (0x%04X)\n",
781+ dev->name, cmd);
782+ return;
783+ }
784+#ifdef WE_EVENT_DEBUG
785+ printk(KERN_DEBUG "%s (WE) : Got event 0x%04X\n",
786+ dev->name, cmd);
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 */
789+
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);
795+ return;
796+ }
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);
799+ return;
800+ }
801+ /* Calculate extra_len - extra is NULL for restricted events */
802+ if(extra != NULL)
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 */
807+ }
808+
809+ /* Total length of the event */
810+ hdr_len = event_type_size[descr->header_type];
811+ event_len = hdr_len + extra_len;
812+
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 */
816+
817+ /* Create temporary buffer to hold the event */
818+ event = kmalloc(event_len, GFP_ATOMIC);
819+ if(event == NULL)
820+ return;
821+
822+ /* Fill event */
823+ event->len = event_len;
824+ event->cmd = cmd;
825+ memcpy(&event->u, wrqu, hdr_len - IW_EV_LCP_LEN);
826+ if(extra != NULL)
827+ memcpy(((char *) event) + hdr_len, extra, extra_len);
828+
829+#ifdef WE_EVENT_NETLINK
830+ /* rtnetlink event channel */
831+ rtmsg_iwinfo(dev, (char *) event, event_len);
832+#endif /* WE_EVENT_NETLINK */
833+
834+ /* Cleanup */
835+ kfree(event);
836+
837+ return; /* Always success, I guess ;-) */
838 }
This page took 0.876973 seconds and 4 git commands to generate.