diff options
Diffstat (limited to 'recipes/linux/files/iw_handlers.w14-5.diff')
-rw-r--r-- | recipes/linux/files/iw_handlers.w14-5.diff | 838 |
1 files changed, 0 insertions, 838 deletions
diff --git a/recipes/linux/files/iw_handlers.w14-5.diff b/recipes/linux/files/iw_handlers.w14-5.diff deleted file mode 100644 index 539b160068..0000000000 --- a/recipes/linux/files/iw_handlers.w14-5.diff +++ /dev/null @@ -1,838 +0,0 @@ -diff -u -p -r --new-file linux/include/linux-w13/rtnetlink.h linux/include/linux/rtnetlink.h ---- linux/include/linux-w13/rtnetlink.h Thu Jun 6 14:44:08 2002 -+++ linux/include/linux/rtnetlink.h Thu Jun 6 15:47:44 2002 -@@ -440,12 +440,14 @@ enum - #define IFLA_COST IFLA_COST - IFLA_PRIORITY, - #define IFLA_PRIORITY IFLA_PRIORITY -- IFLA_MASTER -+ IFLA_MASTER, - #define IFLA_MASTER IFLA_MASTER -+ IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ -+#define IFLA_WIRELESS IFLA_WIRELESS - }; - - --#define IFLA_MAX IFLA_MASTER -+#define IFLA_MAX IFLA_WIRELESS - - #define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) - #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) -diff -u -p -r --new-file linux/include/linux-w13/wireless.h linux/include/linux/wireless.h ---- linux/include/linux-w13/wireless.h Thu Jun 6 15:00:28 2002 -+++ linux/include/linux/wireless.h Thu Jun 6 15:47:44 2002 -@@ -1,10 +1,10 @@ - /* - * This file define a set of standard wireless extensions - * -- * Version : 13 6.12.01 -+ * Version : 14 25.1.02 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. - */ - - #ifndef _LINUX_WIRELESS_H -@@ -40,7 +40,7 @@ - * # include/linux/netdevice.h (one place) - * # include/linux/proc_fs.h (one place) - * -- * New driver API (2001 -> onward) : -+ * New driver API (2002 -> onward) : - * ------------------------------- - * This file is only concerned with the user space API and common definitions. - * The new driver API is defined and documented in : -@@ -49,6 +49,11 @@ - * Note as well that /proc/net/wireless implementation has now moved in : - * # include/linux/wireless.c - * -+ * Wireless Events (2002 -> onward) : -+ * -------------------------------- -+ * Events are defined at the end of this file, and implemented in : -+ * # include/linux/wireless.c -+ * - * Other comments : - * -------------- - * Do not add here things that are redundant with other mechanisms -@@ -75,7 +80,7 @@ - * (there is some stuff that will be added in the future...) - * I just plan to increment with each new version. - */ --#define WIRELESS_EXT 13 -+#define WIRELESS_EXT 14 - - /* - * Changes : -@@ -141,6 +146,13 @@ - * - Document creation of new driver API. - * - Extract union iwreq_data from struct iwreq (for new driver API). - * - Rename SIOCSIWNAME as SIOCSIWCOMMIT -+ * -+ * V13 to V14 -+ * ---------- -+ * - Wireless Events support : define struct iw_event -+ * - Define additional specific event numbers -+ * - Add "addr" and "param" fields in union iwreq_data -+ * - AP scanning stuff (SIOCSIWSCAN and friends) - */ - - /**************************** CONSTANTS ****************************/ -@@ -175,6 +187,8 @@ - #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ - #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ - #define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ -+#define SIOCSIWSCAN 0x8B18 /* trigger scanning */ -+#define SIOCGIWSCAN 0x8B19 /* get scanning results */ - - /* 802.11 specific support */ - #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ -@@ -238,6 +252,15 @@ - #define IW_IS_SET(cmd) (!((cmd) & 0x1)) - #define IW_IS_GET(cmd) ((cmd) & 0x1) - -+/* ----------------------- WIRELESS EVENTS ----------------------- */ -+/* Those are *NOT* ioctls, do not issue request on them !!! */ -+/* Most events use the same identifier as ioctl requests */ -+ -+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ -+#define IWEVQUAL 0x8C01 /* Quality part of statistics */ -+ -+#define IWEVFIRST 0x8C00 -+ - /* ------------------------- PRIVATE INFO ------------------------- */ - /* - * The following is used with SIOCGIWPRIV. It allow a driver to define -@@ -340,6 +363,19 @@ - #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ - #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ - -+/* Scanning request flags */ -+#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ -+#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ -+#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ -+#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ -+#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ -+#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ -+#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ -+#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ -+#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ -+/* Maximum size of returned data */ -+#define IW_SCAN_MAX_DATA 4096 /* In bytes */ -+ - /****************************** TYPES ******************************/ - - /* --------------------------- SUBTYPES --------------------------- */ -@@ -466,9 +502,12 @@ union iwreq_data - - struct iw_point encoding; /* Encoding stuff : tokens */ - struct iw_param power; /* PM duration/timeout */ -+ struct iw_quality qual; /* Quality part of statistics */ - - struct sockaddr ap_addr; /* Access point address */ -+ struct sockaddr addr; /* Destination address (hw) */ - -+ struct iw_param param; /* Other small parameters */ - struct iw_point data; /* Other large parameters */ - }; - -@@ -595,5 +634,36 @@ struct iw_priv_args - __u16 get_args; /* Type and number of args */ - char name[IFNAMSIZ]; /* Name of the extension */ - }; -+ -+/* ----------------------- WIRELESS EVENTS ----------------------- */ -+/* -+ * Wireless events are carried through the rtnetlink socket to user -+ * space. They are encapsulated in the IFLA_WIRELESS field of -+ * a RTM_NEWLINK message. -+ */ -+ -+/* -+ * A Wireless Event. Contains basically the same data as the ioctl... -+ */ -+struct iw_event -+{ -+ __u16 len; /* Real lenght of this stuff */ -+ __u16 cmd; /* Wireless IOCTL */ -+ union iwreq_data u; /* IOCTL fixed payload */ -+}; -+ -+/* Size of the Event prefix (including padding and alignement junk) */ -+#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) -+/* Size of the various events */ -+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) -+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) -+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) -+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point)) -+#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) -+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) -+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) -+ -+/* Note : in the case of iw_point, the extra data will come at the -+ * end of the event */ - - #endif /* _LINUX_WIRELESS_H */ -diff -u -p -r --new-file linux/include/net-w13/iw_handler.h linux/include/net/iw_handler.h ---- linux/include/net-w13/iw_handler.h Thu Jun 6 15:06:16 2002 -+++ linux/include/net/iw_handler.h Thu Jun 6 15:48:06 2002 -@@ -1,10 +1,10 @@ - /* - * This file define the new driver API for Wireless Extensions - * -- * Version : 2 6.12.01 -+ * Version : 3 17.1.02 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 2001 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved. - */ - - #ifndef _IW_HANDLER_H -@@ -33,7 +33,7 @@ - * o The user space interface is tied to ioctl because of the use - * copy_to/from_user. - * -- * New driver API (2001 -> onward) : -+ * New driver API (2002 -> onward) : - * ------------------------------- - * The new driver API is just a bunch of standard functions (handlers), - * each handling a specific Wireless Extension. The driver just export -@@ -206,7 +206,18 @@ - * will be needed... - * I just plan to increment with each new version. - */ --#define IW_HANDLER_VERSION 2 -+#define IW_HANDLER_VERSION 3 -+ -+/* -+ * Changes : -+ * -+ * V2 to V3 -+ * -------- -+ * - Move event definition in <linux/wireless.h> -+ * - Add Wireless Event support : -+ * o wireless_send_event() prototype -+ * o iwe_stream_add_event/point() inline functions -+ */ - - /**************************** CONSTANTS ****************************/ - -@@ -225,6 +236,7 @@ - #define IW_HEADER_TYPE_POINT 6 /* struct iw_point */ - #define IW_HEADER_TYPE_PARAM 7 /* struct iw_param */ - #define IW_HEADER_TYPE_ADDR 8 /* struct sockaddr */ -+#define IW_HEADER_TYPE_QUAL 9 /* struct iw_quality */ - - /* Handling flags */ - /* Most are not implemented. I just use them as a reminder of some -@@ -233,7 +245,8 @@ - /* Wrapper level flags */ - #define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */ - #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */ --#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET request is ROOT only */ -+#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */ -+ /* SET : Omit payload from generated iwevent */ - /* Driver level flags */ - #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */ - -@@ -303,25 +316,6 @@ struct iw_handler_def - * 'struct net_device' to here, to minimise bloat. */ - }; - --/* ----------------------- WIRELESS EVENTS ----------------------- */ --/* -- * Currently we don't support events, so let's just plan for the -- * future... -- */ -- --/* -- * A Wireless Event. -- */ --// How do we define short header ? We don't want a flag on length. --// Probably a flag on event ? Highest bit to zero... --struct iw_event --{ -- __u16 length; /* Lenght of this stuff */ -- __u16 event; /* Wireless IOCTL */ -- union iwreq_data header; /* IOCTL fixed payload */ -- char extra[0]; /* Optional IOCTL data */ --}; -- - /* ---------------------- IOCTL DESCRIPTION ---------------------- */ - /* - * One of the main goal of the new interface is to deal entirely with -@@ -369,6 +363,88 @@ extern int dev_get_wireless_info(char * - extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); - - /* Second : functions that may be called by driver modules */ --/* None yet */ - --#endif /* _LINUX_WIRELESS_H */ -+/* Send a single event to user space */ -+extern void wireless_send_event(struct net_device * dev, -+ unsigned int cmd, -+ union iwreq_data * wrqu, -+ char * extra); -+ -+/* We may need a function to send a stream of events to user space. -+ * More on that later... */ -+ -+/************************* INLINE FUNTIONS *************************/ -+/* -+ * Function that are so simple that it's more efficient inlining them -+ */ -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Wrapper to add an Wireless Event to a stream of events. -+ */ -+static inline char * -+iwe_stream_add_event(char * stream, /* Stream of events */ -+ char * ends, /* End of stream */ -+ struct iw_event *iwe, /* Payload */ -+ int event_len) /* Real size of payload */ -+{ -+ /* Check if it's possible */ -+ if((stream + event_len) < ends) { -+ iwe->len = event_len; -+ memcpy(stream, (char *) iwe, event_len); -+ stream += event_len; -+ } -+ return stream; -+} -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Wrapper to add an short Wireless Event containing a pointer to a -+ * stream of events. -+ */ -+static inline char * -+iwe_stream_add_point(char * stream, /* Stream of events */ -+ char * ends, /* End of stream */ -+ struct iw_event *iwe, /* Payload */ -+ char * extra) -+{ -+ int event_len = IW_EV_POINT_LEN + iwe->u.data.length; -+ /* Check if it's possible */ -+ if((stream + event_len) < ends) { -+ iwe->len = event_len; -+ memcpy(stream, (char *) iwe, IW_EV_POINT_LEN); -+ memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length); -+ stream += event_len; -+ } -+ return stream; -+} -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Wrapper to add a value to a Wireless Event in a stream of events. -+ * Be careful, this one is tricky to use properly : -+ * At the first run, you need to have (value = event + IW_EV_LCP_LEN). -+ */ -+static inline char * -+iwe_stream_add_value(char * event, /* Event in the stream */ -+ char * value, /* Value in event */ -+ char * ends, /* End of stream */ -+ struct iw_event *iwe, /* Payload */ -+ int event_len) /* Real size of payload */ -+{ -+ /* Don't duplicate LCP */ -+ event_len -= IW_EV_LCP_LEN; -+ -+ /* Check if it's possible */ -+ if((value + event_len) < ends) { -+ /* Add new value */ -+ memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len); -+ value += event_len; -+ /* Patch LCP */ -+ iwe->len = value - event; -+ memcpy(event, (char *) iwe, IW_EV_LCP_LEN); -+ } -+ return value; -+} -+ -+#endif /* _IW_HANDLER_H */ -diff -u -p -r --new-file linux/net/netsyms-w13.c linux/net/netsyms.c ---- linux/net/netsyms-w13.c Thu Jun 6 15:46:34 2002 -+++ linux/net/netsyms.c Thu Jun 6 15:47:44 2002 -@@ -588,4 +588,10 @@ EXPORT_SYMBOL(register_gifconf); - EXPORT_SYMBOL(net_call_rx_atomic); - EXPORT_SYMBOL(softnet_data); - -+#if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO) -+/* Don't include the whole header mess for a single function */ -+extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, char *extra); -+EXPORT_SYMBOL(wireless_send_event); -+#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */ -+ - #endif /* CONFIG_NET */ -diff -u -p -r --new-file linux/net/core/wireless-w13.c linux/net/core/wireless.c ---- linux/net/core/wireless-w13.c Thu Jun 6 15:46:45 2002 -+++ linux/net/core/wireless.c Thu Jun 6 15:48:06 2002 -@@ -2,7 +2,7 @@ - * This file implement the Wireless Extensions APIs. - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. - * - * (As all part of the Linux kernel, this file is GPL) - */ -@@ -25,6 +25,16 @@ - * o Added iw_handler handling ;-) - * o Added standard ioctl description - * o Initial dumb commit strategy based on orinoco.c -+ * -+ * v3 - 19.12.01 - Jean II -+ * o Make sure we don't go out of standard_ioctl[] in ioctl_standard_call -+ * o Add event dispatcher function -+ * o Add event description -+ * o Propagate events as rtnetlink IFLA_WIRELESS option -+ * o Generate event on selected SET requests -+ * -+ * v4 - 18.04.01 - Jean II -+ * o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1 - */ - - /***************************** INCLUDES *****************************/ -@@ -33,6 +43,7 @@ - #include <linux/config.h> /* Not needed ??? */ - #include <linux/types.h> /* off_t */ - #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */ -+#include <linux/rtnetlink.h> /* rtnetlink stuff */ - - #include <linux/wireless.h> /* Pretty obvious */ - #include <net/iw_handler.h> /* New driver API */ -@@ -44,14 +55,23 @@ - - /* Debuging stuff */ - #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ -+#undef WE_EVENT_DEBUG /* Debug Event dispatcher */ -+ -+/* Options */ -+#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */ -+#define WE_SET_EVENT /* Generate an event on some set commands */ - - /************************* GLOBAL VARIABLES *************************/ - /* - * You should not use global variables, because or re-entrancy. - * On our case, it's only const, so it's OK... - */ -+/* -+ * Meta-data about all the standard Wireless Extension request we -+ * know about. -+ */ - static const struct iw_ioctl_description standard_ioctl[] = { -- /* SIOCSIWCOMMIT (internal) */ -+ /* SIOCSIWCOMMIT */ - { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, - /* SIOCGIWNAME */ - { IW_HEADER_TYPE_CHAR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP}, -@@ -99,18 +119,18 @@ static const struct iw_ioctl_description - { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, - /* SIOCGIWAPLIST */ - { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0}, -- /* -- hole -- */ -- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -- /* -- hole -- */ -- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCSIWSCAN */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCGIWSCAN */ -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0}, - /* SIOCSIWESSID */ -- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_EVENT}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT}, - /* SIOCGIWESSID */ -- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_DUMP}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_DUMP}, - /* SIOCSIWNICKN */ -- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0}, - /* SIOCGIWNICKN */ -- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0}, - /* -- hole -- */ - { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, - /* -- hole -- */ -@@ -136,7 +156,7 @@ static const struct iw_ioctl_description - /* SIOCGIWRETRY */ - { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, - /* SIOCSIWENCODE */ -- { IW_HEADER_TYPE_POINT, 4, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT}, - /* SIOCGIWENCODE */ - { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT}, - /* SIOCSIWPOWER */ -@@ -144,9 +164,38 @@ static const struct iw_ioctl_description - /* SIOCGIWPOWER */ - { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, - }; -+static const int standard_ioctl_num = (sizeof(standard_ioctl) / -+ sizeof(struct iw_ioctl_description)); -+ -+/* -+ * Meta-data about all the additional standard Wireless Extension events -+ * we know about. -+ */ -+static const struct iw_ioctl_description standard_event[] = { -+ /* IWEVTXDROP */ -+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, -+ /* IWEVQUAL */ -+ { IW_HEADER_TYPE_QUAL, 0, 0, 0, 0, 0}, -+}; -+static const int standard_event_num = (sizeof(standard_event) / -+ sizeof(struct iw_ioctl_description)); - - /* Size (in bytes) of the various private data types */ --char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 }; -+static const char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 }; -+ -+/* Size (in bytes) of various events */ -+static const int event_type_size[] = { -+ IW_EV_LCP_LEN, -+ 0, -+ IW_EV_CHAR_LEN, -+ 0, -+ IW_EV_UINT_LEN, -+ IW_EV_FREQ_LEN, -+ IW_EV_POINT_LEN, /* Without variable payload */ -+ IW_EV_PARAM_LEN, -+ IW_EV_ADDR_LEN, -+ IW_EV_QUAL_LEN, -+}; - - /************************ COMMON SUBROUTINES ************************/ - /* -@@ -162,7 +211,8 @@ char priv_type_size[] = { 0, 1, 1, 0, 4, - static inline iw_handler get_handler(struct net_device *dev, - unsigned int cmd) - { -- unsigned int index; /* MUST be unsigned */ -+ /* Don't "optimise" the following variable, it will crash */ -+ unsigned int index; /* *MUST* be unsigned */ - - /* Check if we have some wireless handlers defined */ - if(dev->wireless_handlers == NULL) -@@ -269,9 +319,9 @@ static inline int sprintf_wireless_stats - stats->status, - stats->qual.qual, - stats->qual.updated & 1 ? '.' : ' ', -- stats->qual.level, -+ ((__u8) stats->qual.level), - stats->qual.updated & 2 ? '.' : ' ', -- stats->qual.noise, -+ ((__u8) stats->qual.noise), - stats->qual.updated & 4 ? '.' : ' ', - stats->discard.nwid, - stats->discard.code, -@@ -423,12 +473,14 @@ static inline int ioctl_standard_call(st - int ret = -EINVAL; - - /* Get the description of the IOCTL */ -+ if((cmd - SIOCIWFIRST) >= standard_ioctl_num) -+ return -EOPNOTSUPP; - descr = &(standard_ioctl[cmd - SIOCIWFIRST]); - - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "%s : Found standard handler for 0x%04X\n", -+ printk(KERN_DEBUG "%s (WE) : Found standard handler for 0x%04X\n", - ifr->ifr_name, cmd); -- 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); -+ 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); - #endif /* WE_IOCTL_DEBUG */ - - /* Prepare the call */ -@@ -437,8 +489,16 @@ static inline int ioctl_standard_call(st - - /* Check if we have a pointer to user space data or not */ - if(descr->header_type != IW_HEADER_TYPE_POINT) { -+ - /* No extra arguments. Trivial to handle */ - ret = handler(dev, &info, &(iwr->u), NULL); -+ -+#ifdef WE_SET_EVENT -+ /* Generate an event to notify listeners of the change */ -+ if((descr->flags & IW_DESCR_FLAG_EVENT) && -+ ((ret == 0) || (ret == -EIWCOMMIT))) -+ wireless_send_event(dev, cmd, &(iwr->u), NULL); -+#endif /* WE_SET_EVENT */ - } else { - char * extra; - int err; -@@ -466,8 +526,8 @@ static inline int ioctl_standard_call(st - } - - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Malloc %d bytes\n", -- descr->max_tokens * descr->token_size); -+ printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n", -+ dev->name, descr->max_tokens * descr->token_size); - #endif /* WE_IOCTL_DEBUG */ - - /* Always allocate for max space. Easier, and won't last -@@ -488,7 +548,8 @@ static inline int ioctl_standard_call(st - return -EFAULT; - } - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Got %d bytes\n", -+ printk(KERN_DEBUG "%s (WE) : Got %d bytes\n", -+ dev->name, - iwr->u.data.length * descr->token_size); - #endif /* WE_IOCTL_DEBUG */ - } -@@ -504,11 +565,26 @@ static inline int ioctl_standard_call(st - if (err) - ret = -EFAULT; - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Wrote %d bytes\n", -+ printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n", -+ dev->name, - iwr->u.data.length * descr->token_size); - #endif /* WE_IOCTL_DEBUG */ - } - -+#ifdef WE_SET_EVENT -+ /* Generate an event to notify listeners of the change */ -+ if((descr->flags & IW_DESCR_FLAG_EVENT) && -+ ((ret == 0) || (ret == -EIWCOMMIT))) { -+ if(descr->flags & IW_DESCR_FLAG_RESTRICT) -+ /* If the event is restricted, don't -+ * export the payload */ -+ wireless_send_event(dev, cmd, &(iwr->u), NULL); -+ else -+ wireless_send_event(dev, cmd, &(iwr->u), -+ extra); -+ } -+#endif /* WE_SET_EVENT */ -+ - /* Cleanup - I told you it wasn't that long ;-) */ - kfree(extra); - } -@@ -558,11 +634,12 @@ static inline int ioctl_private_call(str - } - - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "%s : Found private handler for 0x%04X\n", -+ printk(KERN_DEBUG "%s (WE) : Found private handler for 0x%04X\n", - ifr->ifr_name, cmd); - if(descr) { -- printk(KERN_DEBUG "Name %s, set %X, get %X\n", -- descr->name, descr->set_args, descr->get_args); -+ printk(KERN_DEBUG "%s (WE) : Name %s, set %X, get %X\n", -+ dev->name, descr->name, -+ descr->set_args, descr->get_args); - } - #endif /* WE_IOCTL_DEBUG */ - -@@ -617,7 +694,8 @@ static inline int ioctl_private_call(str - } - - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Malloc %d bytes\n", extra_size); -+ printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n", -+ dev->name, extra_size); - #endif /* WE_IOCTL_DEBUG */ - - /* Always allocate for max space. Easier, and won't last -@@ -636,7 +714,8 @@ static inline int ioctl_private_call(str - return -EFAULT; - } - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Got %d elem\n", iwr->u.data.length); -+ printk(KERN_DEBUG "%s (WE) : Got %d elem\n", -+ dev->name, iwr->u.data.length); - #endif /* WE_IOCTL_DEBUG */ - } - -@@ -650,8 +729,8 @@ static inline int ioctl_private_call(str - if (err) - ret = -EFAULT; - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Wrote %d elem\n", -- iwr->u.data.length); -+ printk(KERN_DEBUG "%s (WE) : Wrote %d elem\n", -+ dev->name, iwr->u.data.length); - #endif /* WE_IOCTL_DEBUG */ - } - -@@ -730,4 +809,178 @@ int wireless_process_ioctl(struct ifreq - } - /* Not reached */ - return -EINVAL; -+} -+ -+/************************* EVENT PROCESSING *************************/ -+/* -+ * Process events generated by the wireless layer or the driver. -+ * Most often, the event will be propagated through rtnetlink -+ */ -+ -+#ifdef WE_EVENT_NETLINK -+/* "rtnl" is defined in net/core/rtnetlink.c, but we need it here. -+ * It is declared in <linux/rtnetlink.h> */ -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Fill a rtnetlink message with our event data. -+ * Note that we propage only the specified event and don't dump the -+ * current wireless config. Dumping the wireless config is far too -+ * expensive (for each parameter, the driver need to query the hardware). -+ */ -+static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb, -+ struct net_device * dev, -+ int type, -+ char * event, -+ int event_len) -+{ -+ struct ifinfomsg *r; -+ struct nlmsghdr *nlh; -+ unsigned char *b = skb->tail; -+ -+ nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(*r)); -+ r = NLMSG_DATA(nlh); -+ r->ifi_family = AF_UNSPEC; -+ r->ifi_type = dev->type; -+ r->ifi_index = dev->ifindex; -+ r->ifi_flags = dev->flags; -+ r->ifi_change = 0; /* Wireless changes don't affect those flags */ -+ -+ /* Add the wireless events in the netlink packet */ -+ RTA_PUT(skb, IFLA_WIRELESS, -+ event_len, event); -+ -+ nlh->nlmsg_len = skb->tail - b; -+ return skb->len; -+ -+nlmsg_failure: -+rtattr_failure: -+ skb_trim(skb, b - skb->data); -+ return -1; -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Create and broadcast and send it on the standard rtnetlink socket -+ * This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c -+ * Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field -+ * within a RTM_NEWLINK event. -+ */ -+static inline void rtmsg_iwinfo(struct net_device * dev, -+ char * event, -+ int event_len) -+{ -+ struct sk_buff *skb; -+ int size = NLMSG_GOODSIZE; -+ -+ skb = alloc_skb(size, GFP_ATOMIC); -+ if (!skb) -+ return; -+ -+ if (rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK, -+ event, event_len) < 0) { -+ kfree_skb(skb); -+ return; -+ } -+ NETLINK_CB(skb).dst_groups = RTMGRP_LINK; -+ netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_ATOMIC); -+} -+#endif /* WE_EVENT_NETLINK */ -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Main event dispatcher. Called from other parts and drivers. -+ * Send the event on the apropriate channels. -+ * May be called from interrupt context. -+ */ -+void wireless_send_event(struct net_device * dev, -+ unsigned int cmd, -+ union iwreq_data * wrqu, -+ char * extra) -+{ -+ const struct iw_ioctl_description * descr = NULL; -+ int extra_len = 0; -+ struct iw_event *event; /* Mallocated whole event */ -+ int event_len; /* Its size */ -+ int hdr_len; /* Size of the event header */ -+ /* Don't "optimise" the following variable, it will crash */ -+ unsigned cmd_index; /* *MUST* be unsigned */ -+ -+ /* Get the description of the IOCTL */ -+ if(cmd <= SIOCIWLAST) { -+ cmd_index = cmd - SIOCIWFIRST; -+ if(cmd_index < standard_ioctl_num) -+ descr = &(standard_ioctl[cmd_index]); -+ } else { -+ cmd_index = cmd - IWEVFIRST; -+ if(cmd_index < standard_event_num) -+ descr = &(standard_event[cmd_index]); -+ } -+ /* Don't accept unknown events */ -+ if(descr == NULL) { -+ /* Note : we don't return an error to the driver, because -+ * the driver would not know what to do about it. It can't -+ * return an error to the user, because the event is not -+ * initiated by a user request. -+ * The best the driver could do is to log an error message. -+ * We will do it ourselves instead... -+ */ -+ printk(KERN_ERR "%s (WE) : Invalid Wireless Event (0x%04X)\n", -+ dev->name, cmd); -+ return; -+ } -+#ifdef WE_EVENT_DEBUG -+ printk(KERN_DEBUG "%s (WE) : Got event 0x%04X\n", -+ dev->name, cmd); -+ 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); -+#endif /* WE_EVENT_DEBUG */ -+ -+ /* Check extra parameters and set extra_len */ -+ if(descr->header_type == IW_HEADER_TYPE_POINT) { -+ /* Check if number of token fits within bounds */ -+ if(wrqu->data.length > descr->max_tokens) { -+ printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length); -+ return; -+ } -+ if(wrqu->data.length < descr->min_tokens) { -+ printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length); -+ return; -+ } -+ /* Calculate extra_len - extra is NULL for restricted events */ -+ if(extra != NULL) -+ extra_len = wrqu->data.length * descr->token_size; -+#ifdef WE_EVENT_DEBUG -+ printk(KERN_DEBUG "%s (WE) : Event 0x%04X, tokens %d, extra_len %d\n", dev->name, cmd, wrqu->data.length, extra_len); -+#endif /* WE_EVENT_DEBUG */ -+ } -+ -+ /* Total length of the event */ -+ hdr_len = event_type_size[descr->header_type]; -+ event_len = hdr_len + extra_len; -+ -+#ifdef WE_EVENT_DEBUG -+ printk(KERN_DEBUG "%s (WE) : Event 0x%04X, hdr_len %d, event_len %d\n", dev->name, cmd, hdr_len, event_len); -+#endif /* WE_EVENT_DEBUG */ -+ -+ /* Create temporary buffer to hold the event */ -+ event = kmalloc(event_len, GFP_ATOMIC); -+ if(event == NULL) -+ return; -+ -+ /* Fill event */ -+ event->len = event_len; -+ event->cmd = cmd; -+ memcpy(&event->u, wrqu, hdr_len - IW_EV_LCP_LEN); -+ if(extra != NULL) -+ memcpy(((char *) event) + hdr_len, extra, extra_len); -+ -+#ifdef WE_EVENT_NETLINK -+ /* rtnetlink event channel */ -+ rtmsg_iwinfo(dev, (char *) event, event_len); -+#endif /* WE_EVENT_NETLINK */ -+ -+ /* Cleanup */ -+ kfree(event); -+ -+ return; /* Always success, I guess ;-) */ - } |