diff options
Diffstat (limited to 'recipes/linux/files/iw249_we17-13.diff')
-rw-r--r-- | recipes/linux/files/iw249_we17-13.diff | 768 |
1 files changed, 0 insertions, 768 deletions
diff --git a/recipes/linux/files/iw249_we17-13.diff b/recipes/linux/files/iw249_we17-13.diff deleted file mode 100644 index 674f4ffbc0..0000000000 --- a/recipes/linux/files/iw249_we17-13.diff +++ /dev/null @@ -1,768 +0,0 @@ -diff -u -p linux/include/linux/netdevice.we16.h linux/include/linux/netdevice.h ---- linux/include/linux/netdevice.we16.h 2005-02-03 14:54:56.000000000 -0800 -+++ linux/include/linux/netdevice.h 2005-02-03 15:43:30.000000000 -0800 -@@ -295,7 +295,9 @@ struct net_device - - /* List of functions to handle Wireless Extensions (instead of ioctl). - * See <net/iw_handler.h> for details. Jean II */ -- struct iw_handler_def * wireless_handlers; -+ const struct iw_handler_def * wireless_handlers; -+ /* Instance data managed by the core of Wireless Extensions. */ -+ struct iw_public_data * wireless_data; - - struct ethtool_ops *ethtool_ops; - -diff -u -p linux/include/linux/wireless.we16.h linux/include/linux/wireless.h ---- linux/include/linux/wireless.we16.h 2005-02-03 14:55:04.000000000 -0800 -+++ linux/include/linux/wireless.h 2005-02-03 15:44:48.000000000 -0800 -@@ -1,10 +1,10 @@ - /* - * This file define a set of standard wireless extensions - * -- * Version : 16 2.4.03 -+ * Version : 17 21.6.04 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved. - */ - - #ifndef _LINUX_WIRELESS_H -@@ -47,12 +47,12 @@ - * # include/net/iw_handler.h - * - * Note as well that /proc/net/wireless implementation has now moved in : -- * # include/linux/wireless.c -+ * # net/core/wireless.c - * - * Wireless Events (2002 -> onward) : - * -------------------------------- - * Events are defined at the end of this file, and implemented in : -- * # include/linux/wireless.c -+ * # net/core/wireless.c - * - * Other comments : - * -------------- -@@ -82,7 +82,7 @@ - * (there is some stuff that will be added in the future...) - * I just plan to increment with each new version. - */ --#define WIRELESS_EXT 16 -+#define WIRELESS_EXT 17 - - /* - * Changes : -@@ -175,6 +175,13 @@ - * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support - * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" - * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index -+ * -+ * V16 to V17 -+ * ---------- -+ * - Add flags to frequency -> auto/fixed -+ * - Document (struct iw_quality *)->updated, add new flags (INVALID) -+ * - Wireless Event capability in struct iw_range -+ * - Add support for relative TxPower (yick !) - */ - - /**************************** CONSTANTS ****************************/ -@@ -251,7 +258,7 @@ - - /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ - --/* These 16 ioctl are wireless device private. -+/* These 32 ioctl are wireless device private, for 16 commands. - * Each driver is free to use them for whatever purpose it chooses, - * however the driver *must* export the description of those ioctls - * with SIOCGIWPRIV and *must* use arguments as defined below. -@@ -266,8 +273,8 @@ - * We now have 32 commands, so a bit more space ;-). - * Also, all 'odd' commands are only usable by root and don't return the - * content of ifr/iwr to user (but you are not obliged to use the set/get -- * convention, just use every other two command). -- * And I repeat : you are not obliged to use them with iwspy, but you -+ * convention, just use every other two command). More details in iwpriv.c. -+ * And I repeat : you are not forced to use them with iwpriv, but you - * must be compliant with it. - */ - -@@ -352,6 +359,18 @@ - #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ - #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ - -+/* Statistics flags (bitmask in updated) */ -+#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */ -+#define IW_QUAL_LEVEL_UPDATED 0x2 -+#define IW_QUAL_NOISE_UPDATED 0x4 -+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ -+#define IW_QUAL_LEVEL_INVALID 0x20 -+#define IW_QUAL_NOISE_INVALID 0x40 -+ -+/* Frequency flags */ -+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */ -+#define IW_FREQ_FIXED 0x01 /* Force a specific value */ -+ - /* Maximum number of size of encoding token available - * they are listed in the range structure */ - #define IW_MAX_ENCODING_SIZES 8 -@@ -390,6 +409,7 @@ - #define IW_TXPOW_TYPE 0x00FF /* Type of value */ - #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ - #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ -+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ - #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ - - /* Retry limits and lifetime flags available */ -@@ -418,6 +438,25 @@ - /* Max number of char in custom event - use multiple of them if needed */ - #define IW_CUSTOM_MAX 256 /* In bytes */ - -+/* Event capability macros - in (struct iw_range *)->event_capa -+ * Because we have more than 32 possible events, we use an array of -+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ -+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ -+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \ -+ (cmd - SIOCSIWCOMMIT)) -+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) -+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) -+/* Event capability constants - event autogenerated by the kernel -+ * This list is valid for most 802.11 devices, customise as needed... */ -+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ -+ IW_EVENT_CAPA_MASK(0x8B06) | \ -+ IW_EVENT_CAPA_MASK(0x8B1A)) -+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) -+/* "Easy" macro to set events in iw_range (less efficient) */ -+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) -+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } -+ -+ - /****************************** TYPES ******************************/ - - /* --------------------------- SUBTYPES --------------------------- */ -@@ -456,7 +495,7 @@ struct iw_freq - __s32 m; /* Mantissa */ - __s16 e; /* Exponent */ - __u8 i; /* List index (when in range struct) */ -- __u8 pad; /* Unused - just for alignement */ -+ __u8 flags; /* Flags (fixed/auto) */ - }; - - /* -@@ -610,11 +649,12 @@ struct iw_range - /* Old Frequency (backward compat - moved lower ) */ - __u16 old_num_channels; - __u8 old_num_frequency; -- /* Filler to keep "version" at the same offset */ -- __s32 old_freq[6]; -+ -+ /* Wireless event capability bitmasks */ -+ __u32 event_capa[6]; - - /* signal level threshold range */ -- __s32 sensitivity; -+ __s32 sensitivity; - - /* Quality of link & SNR stuff */ - /* Quality range (link, level, noise) -diff -u -p linux/include/net/iw_handler.we16.h linux/include/net/iw_handler.h ---- linux/include/net/iw_handler.we16.h 2005-02-03 14:55:26.000000000 -0800 -+++ linux/include/net/iw_handler.h 2005-02-03 15:47:04.000000000 -0800 -@@ -1,10 +1,10 @@ - /* - * This file define the new driver API for Wireless Extensions - * -- * Version : 5 4.12.02 -+ * Version : 6 21.6.04 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved. - */ - - #ifndef _IW_HANDLER_H -@@ -206,7 +206,7 @@ - * will be needed... - * I just plan to increment with each new version. - */ --#define IW_HANDLER_VERSION 5 -+#define IW_HANDLER_VERSION 6 - - /* - * Changes : -@@ -224,11 +224,18 @@ - * V4 to V5 - * -------- - * - Add new spy support : struct iw_spy_data & prototypes -+ * -+ * V5 to V6 -+ * -------- -+ * - Change the way we get to spy_data method for added safety -+ * - Remove spy #ifdef, they are always on -> cleaner code -+ * - Add IW_DESCR_FLAG_NOMAX flag for very large requests -+ * - Start migrating get_wireless_stats to struct iw_handler_def - */ - - /**************************** CONSTANTS ****************************/ - --/* Enable enhanced spy support. Disable to reduce footprint */ -+/* Enhanced spy support available */ - #define IW_WIRELESS_SPY - #define IW_WIRELESS_THRSPY - -@@ -258,6 +265,7 @@ - #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */ - #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */ - /* SET : Omit payload from generated iwevent */ -+#define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */ - /* Driver level flags */ - #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */ - -@@ -311,23 +319,25 @@ struct iw_handler_def - /* Array of handlers for standard ioctls - * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME] - */ -- iw_handler * standard; -+ const iw_handler * standard; - - /* Array of handlers for private ioctls - * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV] - */ -- iw_handler * private; -+ const iw_handler * private; - - /* Arguments of private handler. This one is just a list, so you - * can put it in any order you want and should not leave holes... - * We will automatically export that to user space... */ -- struct iw_priv_args * private_args; -+ const struct iw_priv_args * private_args; - -- /* Driver enhanced spy support */ -- long spy_offset; /* Spy data offset */ -+ /* This field will be *removed* in the next version of WE */ -+ long spy_offset; /* DO NOT USE */ - -- /* In the long term, get_wireless_stats will move from -- * 'struct net_device' to here, to minimise bloat. */ -+ /* New location of get_wireless_stats, to de-bloat struct net_device. -+ * The old pointer in struct net_device will be gradually phased -+ * out, and drivers are encouraged to use this one... */ -+ struct iw_statistics* (*get_wireless_stats)(struct net_device *dev); - }; - - /* ---------------------- IOCTL DESCRIPTION ---------------------- */ -@@ -374,18 +384,29 @@ struct iw_ioctl_description - */ - struct iw_spy_data - { --#ifdef IW_WIRELESS_SPY - /* --- Standard spy support --- */ - int spy_number; - u_char spy_address[IW_MAX_SPY][ETH_ALEN]; - struct iw_quality spy_stat[IW_MAX_SPY]; --#ifdef IW_WIRELESS_THRSPY - /* --- Enhanced spy support (event) */ - struct iw_quality spy_thr_low; /* Low threshold */ - struct iw_quality spy_thr_high; /* High threshold */ - u_char spy_thr_under[IW_MAX_SPY]; --#endif /* IW_WIRELESS_THRSPY */ --#endif /* IW_WIRELESS_SPY */ -+}; -+ -+/* --------------------- DEVICE WIRELESS DATA --------------------- */ -+/* -+ * This is all the wireless data specific to a device instance that -+ * is managed by the core of Wireless Extensions. -+ * We only keep pointer to those structures, so that a driver is free -+ * to share them between instances. -+ * This structure should be initialised before registering the device. -+ * Access to this data follow the same rules as any other struct net_device -+ * data (i.e. valid as long as struct net_device exist, same locking rules). -+ */ -+struct iw_public_data { -+ /* Driver enhanced spy support */ -+ struct iw_spy_data * spy_data; - }; - - /**************************** PROTOTYPES ****************************/ -diff -u -p linux/net/core/dev.we16.c linux/net/core/dev.c ---- linux/net/core/dev.we16.c 2005-02-03 14:55:56.000000000 -0800 -+++ linux/net/core/dev.c 2005-02-03 15:28:48.000000000 -0800 -@@ -2426,7 +2426,7 @@ int dev_ioctl(unsigned int cmd, void *ar - /* Follow me in net/core/wireless.c */ - ret = wireless_process_ioctl(&ifr, cmd); - rtnl_unlock(); -- if (!ret && IW_IS_GET(cmd) && -+ if (IW_IS_GET(cmd) && - copy_to_user(arg, &ifr, sizeof(struct ifreq))) - return -EFAULT; - return ret; -diff -u -p linux/net/core/wireless.we16.c linux/net/core/wireless.c ---- linux/net/core/wireless.we16.c 2005-02-03 14:56:09.000000000 -0800 -+++ linux/net/core/wireless.c 2005-02-03 16:33:22.000000000 -0800 -@@ -2,7 +2,7 @@ - * This file implement the Wireless Extensions APIs. - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved. - * - * (As all part of the Linux kernel, this file is GPL) - */ -@@ -48,6 +48,16 @@ - * o Add common spy support : iw_handler_set_spy(), wireless_spy_update() - * o Add enhanced spy support : iw_handler_set_thrspy() and event. - * o Add WIRELESS_EXT version display in /proc/net/wireless -+ * -+ * v6 - 18.06.04 - Jean II -+ * o Change get_spydata() method for added safety -+ * o Remove spy #ifdef, they are always on -> cleaner code -+ * o Allow any size GET request if user specifies length > max -+ * and if request has IW_DESCR_FLAG_NOMAX flag or is SIOCGIWPRIV -+ * o Start migrating get_wireless_stats to struct iw_handler_def -+ * o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus -+ * Based on patch from Pavel Roskin <proski@gnu.org> : -+ * o Fix kernel data leak to user space in private handler handling - */ - - /***************************** INCLUDES *****************************/ -@@ -64,11 +74,7 @@ - - /**************************** CONSTANTS ****************************/ - --/* Enough lenience, let's make sure things are proper... */ --#define WE_STRICT_WRITE /* Check write buffer size */ --/* I'll probably drop both the define and kernel message in the next version */ -- --/* Debuging stuff */ -+/* Debugging stuff */ - #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ - #undef WE_EVENT_DEBUG /* Debug Event dispatcher */ - #undef WE_SPY_DEBUG /* Debug enhanced spy support */ -@@ -134,11 +140,11 @@ static const struct iw_ioctl_description - /* -- hole -- */ - { 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}, -+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, IW_DESCR_FLAG_NOMAX}, - /* SIOCSIWSCAN */ - { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, - /* SIOCGIWSCAN */ -- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, IW_DESCR_FLAG_NOMAX}, - /* SIOCSIWESSID */ - { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT}, - /* SIOCGIWESSID */ -@@ -203,7 +209,7 @@ static const int standard_event_num = (s - sizeof(struct iw_ioctl_description)); - - /* Size (in bytes) of the various private data types */ --static const char priv_type_size[] = { -+static const char iw_priv_type_size[] = { - 0, /* IW_PRIV_TYPE_NONE */ - 1, /* IW_PRIV_TYPE_BYTE */ - 1, /* IW_PRIV_TYPE_CHAR */ -@@ -270,12 +276,15 @@ static inline iw_handler get_handler(str - */ - static inline struct iw_statistics *get_wireless_stats(struct net_device *dev) - { -+ /* New location */ -+ if((dev->wireless_handlers != NULL) && -+ (dev->wireless_handlers->get_wireless_stats != NULL)) -+ return dev->wireless_handlers->get_wireless_stats(dev); -+ -+ /* Old location, will be phased out in next WE */ - return (dev->get_wireless_stats ? - dev->get_wireless_stats(dev) : - (struct iw_statistics *) NULL); -- /* In the future, get_wireless_stats may move from 'struct net_device' -- * to 'struct iw_handler_def', to de-bloat struct net_device. -- * Definitely worse a thought... */ - } - - /* ---------------------------------------------------------------- */ -@@ -310,14 +319,32 @@ static inline int call_commit_handler(st - - /* ---------------------------------------------------------------- */ - /* -- * Number of private arguments -+ * Calculate size of private arguments - */ - static inline int get_priv_size(__u16 args) - { - int num = args & IW_PRIV_SIZE_MASK; - int type = (args & IW_PRIV_TYPE_MASK) >> 12; - -- return num * priv_type_size[type]; -+ return num * iw_priv_type_size[type]; -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Re-calculate the size of private arguments -+ */ -+static inline int adjust_priv_size(__u16 args, -+ union iwreq_data * wrqu) -+{ -+ int num = wrqu->data.length; -+ int max = args & IW_PRIV_SIZE_MASK; -+ int type = (args & IW_PRIV_TYPE_MASK) >> 12; -+ -+ /* Make sure the driver doesn't goof up */ -+ if (max < num) -+ num = max; -+ -+ return num * iw_priv_type_size[type]; - } - - -@@ -350,11 +377,14 @@ static inline int sprintf_wireless_stats - dev->name, - stats->status, - stats->qual.qual, -- stats->qual.updated & 1 ? '.' : ' ', -+ stats->qual.updated & IW_QUAL_QUAL_UPDATED -+ ? '.' : ' ', - ((__u8) stats->qual.level), -- stats->qual.updated & 2 ? '.' : ' ', -+ stats->qual.updated & IW_QUAL_LEVEL_UPDATED -+ ? '.' : ' ', - ((__u8) stats->qual.noise), -- stats->qual.updated & 4 ? '.' : ' ', -+ stats->qual.updated & IW_QUAL_NOISE_UPDATED -+ ? '.' : ' ', - stats->discard.nwid, - stats->discard.code, - stats->discard.fragment, -@@ -470,13 +500,15 @@ static inline int ioctl_export_private(s - /* Check NULL pointer */ - if(iwr->u.data.pointer == NULL) - return -EFAULT; --#ifdef WE_STRICT_WRITE -+ - /* Check if there is enough buffer up there */ - if(iwr->u.data.length < dev->wireless_handlers->num_private_args) { -- printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.data.length, dev->wireless_handlers->num_private_args); -+ /* User space can't know in advance how large the buffer -+ * needs to be. Give it a hint, so that we can support -+ * any size buffer we want somewhat efficiently... */ -+ iwr->u.data.length = dev->wireless_handlers->num_private_args; - return -E2BIG; - } --#endif /* WE_STRICT_WRITE */ - - /* Set the number of available ioctls. */ - iwr->u.data.length = dev->wireless_handlers->num_private_args; -@@ -505,7 +537,6 @@ static inline int ioctl_standard_call(st - const struct iw_ioctl_description * descr; - struct iw_request_info info; - int ret = -EINVAL; -- int user_size = 0; - - /* Get the description of the IOCTL */ - if((cmd - SIOCIWFIRST) >= standard_ioctl_num) -@@ -536,8 +567,14 @@ static inline int ioctl_standard_call(st - #endif /* WE_SET_EVENT */ - } else { - char * extra; -+ int extra_size; -+ int user_length = 0; - int err; - -+ /* Calculate space needed by arguments. Always allocate -+ * for max space. Easier, and won't last long... */ -+ extra_size = descr->max_tokens * descr->token_size; -+ - /* Check what user space is giving us */ - if(IW_IS_SET(cmd)) { - /* Check NULL pointer */ -@@ -554,18 +591,33 @@ static inline int ioctl_standard_call(st - if(iwr->u.data.pointer == NULL) - return -EFAULT; - /* Save user space buffer size for checking */ -- user_size = iwr->u.data.length; -+ user_length = iwr->u.data.length; -+ -+ /* Don't check if user_length > max to allow forward -+ * compatibility. The test user_length < min is -+ * implied by the test at the end. */ -+ -+ /* Support for very large requests */ -+ if((descr->flags & IW_DESCR_FLAG_NOMAX) && -+ (user_length > descr->max_tokens)) { -+ /* Allow userspace to GET more than max so -+ * we can support any size GET requests. -+ * There is still a limit : -ENOMEM. */ -+ extra_size = user_length * descr->token_size; -+ /* Note : user_length is originally a __u16, -+ * and token_size is controlled by us, -+ * so extra_size won't get negative and -+ * won't overflow... */ -+ } - } - - #ifdef WE_IOCTL_DEBUG - printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n", -- dev->name, descr->max_tokens * descr->token_size); -+ dev->name, extra_size); - #endif /* WE_IOCTL_DEBUG */ - -- /* Always allocate for max space. Easier, and won't last -- * long... */ -- extra = kmalloc(descr->max_tokens * descr->token_size, -- GFP_KERNEL); -+ /* Create the kernel buffer */ -+ extra = kmalloc(extra_size, GFP_KERNEL); - if (extra == NULL) { - return -ENOMEM; - } -@@ -591,14 +643,11 @@ static inline int ioctl_standard_call(st - - /* If we have something to return to the user */ - if (!ret && IW_IS_GET(cmd)) { --#ifdef WE_STRICT_WRITE - /* Check if there is enough buffer up there */ -- if(user_size < iwr->u.data.length) { -- printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length); -+ if(user_length < iwr->u.data.length) { - kfree(extra); - return -E2BIG; - } --#endif /* WE_STRICT_WRITE */ - - err = copy_to_user(iwr->u.data.pointer, extra, - iwr->u.data.length * -@@ -661,7 +710,7 @@ static inline int ioctl_private_call(str - iw_handler handler) - { - struct iwreq * iwr = (struct iwreq *) ifr; -- struct iw_priv_args * descr = NULL; -+ const struct iw_priv_args * descr = NULL; - struct iw_request_info info; - int extra_size = 0; - int i; -@@ -701,7 +750,7 @@ static inline int ioctl_private_call(str - ((extra_size + offset) <= IFNAMSIZ)) - extra_size = 0; - } else { -- /* Size of set arguments */ -+ /* Size of get arguments */ - extra_size = get_priv_size(descr->get_args); - - /* Does it fits in iwr ? */ -@@ -771,6 +820,14 @@ static inline int ioctl_private_call(str - - /* If we have something to return to the user */ - if (!ret && IW_IS_GET(cmd)) { -+ -+ /* Adjust for the actual length if it's variable, -+ * avoid leaking kernel bits outside. */ -+ if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) { -+ extra_size = adjust_priv_size(descr->get_args, -+ &(iwr->u)); -+ } -+ - err = copy_to_user(iwr->u.data.pointer, extra, - extra_size); - if (err) -@@ -1042,9 +1099,25 @@ void wireless_send_event(struct net_devi - * One of the main advantage of centralising spy support here is that - * it becomes much easier to improve and extend it without having to touch - * the drivers. One example is the addition of the Spy-Threshold events. -- * Note : IW_WIRELESS_SPY is defined in iw_handler.h - */ - -+/* ---------------------------------------------------------------- */ -+/* -+ * Return the pointer to the spy data in the driver. -+ * Because this is called on the Rx path via wireless_spy_update(), -+ * we want it to be efficient... -+ */ -+static inline struct iw_spy_data * get_spydata(struct net_device *dev) -+{ -+ /* This is the new way */ -+ if(dev->wireless_data) -+ return(dev->wireless_data->spy_data); -+ -+ /* This is the old way. Doesn't work for multi-headed drivers. -+ * It will be removed in the next version of WE. */ -+ return (dev->priv + dev->wireless_handlers->spy_offset); -+} -+ - /*------------------------------------------------------------------*/ - /* - * Standard Wireless Handler : set Spy List -@@ -1054,16 +1127,26 @@ int iw_handler_set_spy(struct net_device - union iwreq_data * wrqu, - char * extra) - { --#ifdef IW_WIRELESS_SPY -- struct iw_spy_data * spydata = (dev->priv + -- dev->wireless_handlers->spy_offset); -+ struct iw_spy_data * spydata = get_spydata(dev); - struct sockaddr * address = (struct sockaddr *) extra; - -+ /* Make sure driver is not buggy or using the old API */ -+ if(!spydata) -+ return -EOPNOTSUPP; -+ - /* Disable spy collection while we copy the addresses. -- * As we don't disable interrupts, we need to do this to avoid races. -- * As we are the only writer, this is good enough. */ -+ * While we copy addresses, any call to wireless_spy_update() -+ * will NOP. This is OK, as anyway the addresses are changing. */ - spydata->spy_number = 0; - -+ /* We want to operate without locking, because wireless_spy_update() -+ * most likely will happen in the interrupt handler, and therefore -+ * have its own locking constraints and needs performance. -+ * The rtnl_lock() make sure we don't race with the other iw_handlers. -+ * This make sure wireless_spy_update() "see" that the spy list -+ * is temporarily disabled. */ -+ wmb(); -+ - /* Are there are addresses to copy? */ - if(wrqu->data.length > 0) { - int i; -@@ -1089,13 +1172,14 @@ int iw_handler_set_spy(struct net_device - spydata->spy_address[i][5]); - #endif /* WE_SPY_DEBUG */ - } -+ -+ /* Make sure above is updated before re-enabling */ -+ wmb(); -+ - /* Enable addresses */ - spydata->spy_number = wrqu->data.length; - - return 0; --#else /* IW_WIRELESS_SPY */ -- return -EOPNOTSUPP; --#endif /* IW_WIRELESS_SPY */ - } - - /*------------------------------------------------------------------*/ -@@ -1107,12 +1191,14 @@ int iw_handler_get_spy(struct net_device - union iwreq_data * wrqu, - char * extra) - { --#ifdef IW_WIRELESS_SPY -- struct iw_spy_data * spydata = (dev->priv + -- dev->wireless_handlers->spy_offset); -+ struct iw_spy_data * spydata = get_spydata(dev); - struct sockaddr * address = (struct sockaddr *) extra; - int i; - -+ /* Make sure driver is not buggy or using the old API */ -+ if(!spydata) -+ return -EOPNOTSUPP; -+ - wrqu->data.length = spydata->spy_number; - - /* Copy addresses. */ -@@ -1129,9 +1215,6 @@ int iw_handler_get_spy(struct net_device - for(i = 0; i < spydata->spy_number; i++) - spydata->spy_stat[i].updated = 0; - return 0; --#else /* IW_WIRELESS_SPY */ -- return -EOPNOTSUPP; --#endif /* IW_WIRELESS_SPY */ - } - - /*------------------------------------------------------------------*/ -@@ -1143,11 +1226,13 @@ int iw_handler_set_thrspy(struct net_dev - union iwreq_data * wrqu, - char * extra) - { --#ifdef IW_WIRELESS_THRSPY -- struct iw_spy_data * spydata = (dev->priv + -- dev->wireless_handlers->spy_offset); -+ struct iw_spy_data * spydata = get_spydata(dev); - struct iw_thrspy * threshold = (struct iw_thrspy *) extra; - -+ /* Make sure driver is not buggy or using the old API */ -+ if(!spydata) -+ return -EOPNOTSUPP; -+ - /* Just do it */ - memcpy(&(spydata->spy_thr_low), &(threshold->low), - 2 * sizeof(struct iw_quality)); -@@ -1160,9 +1245,6 @@ int iw_handler_set_thrspy(struct net_dev - #endif /* WE_SPY_DEBUG */ - - return 0; --#else /* IW_WIRELESS_THRSPY */ -- return -EOPNOTSUPP; --#endif /* IW_WIRELESS_THRSPY */ - } - - /*------------------------------------------------------------------*/ -@@ -1174,22 +1256,20 @@ int iw_handler_get_thrspy(struct net_dev - union iwreq_data * wrqu, - char * extra) - { --#ifdef IW_WIRELESS_THRSPY -- struct iw_spy_data * spydata = (dev->priv + -- dev->wireless_handlers->spy_offset); -+ struct iw_spy_data * spydata = get_spydata(dev); - struct iw_thrspy * threshold = (struct iw_thrspy *) extra; - -+ /* Make sure driver is not buggy or using the old API */ -+ if(!spydata) -+ return -EOPNOTSUPP; -+ - /* Just do it */ - memcpy(&(threshold->low), &(spydata->spy_thr_low), - 2 * sizeof(struct iw_quality)); - - return 0; --#else /* IW_WIRELESS_THRSPY */ -- return -EOPNOTSUPP; --#endif /* IW_WIRELESS_THRSPY */ - } - --#ifdef IW_WIRELESS_THRSPY - /*------------------------------------------------------------------*/ - /* - * Prepare and send a Spy Threshold event -@@ -1227,7 +1307,6 @@ static void iw_send_thrspy_event(struct - /* Send event to user space */ - wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold); - } --#endif /* IW_WIRELESS_THRSPY */ - - /* ---------------------------------------------------------------- */ - /* -@@ -1240,12 +1319,14 @@ void wireless_spy_update(struct net_devi - unsigned char * address, - struct iw_quality * wstats) - { --#ifdef IW_WIRELESS_SPY -- struct iw_spy_data * spydata = (dev->priv + -- dev->wireless_handlers->spy_offset); -+ struct iw_spy_data * spydata = get_spydata(dev); - int i; - int match = -1; - -+ /* Make sure driver is not buggy or using the old API */ -+ if(!spydata) -+ return; -+ - #ifdef WE_SPY_DEBUG - printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]); - #endif /* WE_SPY_DEBUG */ -@@ -1257,7 +1338,7 @@ void wireless_spy_update(struct net_devi - sizeof(struct iw_quality)); - match = i; - } --#ifdef IW_WIRELESS_THRSPY -+ - /* Generate an event if we cross the spy threshold. - * To avoid event storms, we have a simple hysteresis : we generate - * event only when we go under the low threshold or above the -@@ -1277,6 +1358,4 @@ void wireless_spy_update(struct net_devi - } - } - } --#endif /* IW_WIRELESS_THRSPY */ --#endif /* IW_WIRELESS_SPY */ - } |