SOURCES (LINUX_2_6_16): linux-2.6.16-we20-6.patch (NEW) -add wirel...

wolvverine wolvverine at pld-linux.org
Thu Aug 10 15:06:24 CEST 2006


Author: wolvverine                   Date: Thu Aug 10 13:06:24 2006 GMT
Module: SOURCES                       Tag: LINUX_2_6_16
---- Log message:
-add wireless extension http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html#wext

---- Files affected:
SOURCES:
   linux-2.6.16-we20-6.patch (NONE -> 1.1.2.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/linux-2.6.16-we20-6.patch
diff -u /dev/null SOURCES/linux-2.6.16-we20-6.patch:1.1.2.1
--- /dev/null	Thu Aug 10 15:06:24 2006
+++ SOURCES/linux-2.6.16-we20-6.patch	Thu Aug 10 15:06:19 2006
@@ -0,0 +1,1233 @@
+diff -u -p linux/include/linux/wireless.19.h linux/include/linux/wireless.h
+--- linux/include/linux/wireless.19.h	2006-02-17 10:49:04.000000000 -0800
++++ linux/include/linux/wireless.h	2006-02-17 17:58:10.000000000 -0800
+@@ -1,10 +1,10 @@
+ /*
+  * This file define a set of standard wireless extensions
+  *
+- * Version :	19	18.3.05
++ * Version :	20	17.2.06
+  *
+  * Authors :	Jean Tourrilhes - HPL - <jt at hpl.hp.com>
+- * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
+  */
+ 
+ #ifndef _LINUX_WIRELESS_H
+@@ -80,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	19
++#define WIRELESS_EXT	20
+ 
+ /*
+  * Changes :
+@@ -204,6 +204,10 @@
+  *	- Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
+  *	- Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
+  *	- Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
++ *
++ * V19 to V20
++ * ----------
++ *	- RtNetlink requests support (SET/GET)
+  */
+ 
+ /**************************** CONSTANTS ****************************/
+diff -u -p linux/include/net/iw_handler.19.h linux/include/net/iw_handler.h
+--- linux/include/net/iw_handler.19.h	2006-02-17 10:49:15.000000000 -0800
++++ linux/include/net/iw_handler.h	2006-02-17 18:01:36.000000000 -0800
+@@ -4,7 +4,7 @@
+  * Version :	7	18.3.05
+  *
+  * Authors :	Jean Tourrilhes - HPL - <jt at hpl.hp.com>
+- * Copyright (c) 2001-2005 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 2001-2006 Jean Tourrilhes, All Rights Reserved.
+  */
+ 
+ #ifndef _IW_HANDLER_H
+@@ -436,6 +436,16 @@ extern int dev_get_wireless_info(char * 
+ /* Handle IOCTLs, called in net/core/dev.c */
+ extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
+ 
++/* Handle RtNetlink requests, called in net/core/rtnetlink.c */
++extern int wireless_rtnetlink_set(struct net_device *	dev,
++				  char *		data,
++				  int			len);
++extern int wireless_rtnetlink_get(struct net_device *	dev,
++				  char *		data,
++				  int			len,
++				  char **		p_buf,
++				  int *			p_len);
++
+ /* Second : functions that may be called by driver modules */
+ 
+ /* Send a single event to user space */
+diff -u -p linux/drivers/net/wireless/Kconfig.19 linux/drivers/net/wireless/Kconfig
+--- linux/drivers/net/wireless/Kconfig.19	2006-02-21 13:11:34.000000000 -0800
++++ linux/drivers/net/wireless/Kconfig	2006-02-22 11:48:27.000000000 -0800
+@@ -24,6 +24,15 @@ config NET_RADIO
+ 	  the tools from
+ 	  <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+ 
++config NET_WIRELESS_RTNETLINK
++	bool "Wireless Extension API over RtNetlink"
++	---help---
++	  Support the Wireless Extension API over the RtNetlink socket
++	  in addition to the traditional ioctl interface (selected above).
++
++	  For now, few tools use this facility, but it might grow in the
++	  future. The only downside is that it adds 4.5 kB to your kernel.
++
+ # Note : the cards are obsolete (can't buy them anymore), but the drivers
+ # are not, as people are still using them...
+ comment "Obsolete Wireless cards support (pre-802.11)"
+diff -u -p linux/net/core/rtnetlink.19.c linux/net/core/rtnetlink.c
+--- linux/net/core/rtnetlink.19.c	2006-02-17 10:49:26.000000000 -0800
++++ linux/net/core/rtnetlink.c	2006-02-21 12:57:07.000000000 -0800
+@@ -50,6 +50,10 @@
+ #include <net/sock.h>
+ #include <net/pkt_sched.h>
+ #include <net/netlink.h>
++#ifdef CONFIG_NET_WIRELESS_RTNETLINK
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */
+ 
+ DECLARE_MUTEX(rtnl_sem);
+ 
+@@ -410,6 +414,17 @@ static int do_setlink(struct sk_buff *sk
+ 			goto out;
+ 	}
+ 
++#ifdef CONFIG_NET_WIRELESS_RTNETLINK
++	if (ida[IFLA_WIRELESS - 1]) {
++
++		/* Call Wireless Extensions.
++		 * Various stuff checked in there... */
++		err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
++		if (err)
++			goto out;
++	}
++#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */
++
+ 	err = 0;
+ 
+ out:
+@@ -420,6 +435,83 @@ out:
+ 	return err;
+ }
+ 
++#ifdef CONFIG_NET_WIRELESS_RTNETLINK
++static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
++{
++	struct ifinfomsg  *ifm = NLMSG_DATA(in_nlh);
++	struct rtattr    **ida = arg;
++	struct net_device *dev;
++	struct ifinfomsg *r;
++	struct nlmsghdr  *nlh;
++	int err = -ENOBUFS;
++	struct sk_buff *skb;
++	unsigned char	 *b;
++	char *iw_buf = NULL;
++	int iw_buf_len = 0;
++
++	if (ifm->ifi_index >= 0)
++		dev = dev_get_by_index(ifm->ifi_index);
++	else
++		return -EINVAL;
++	if (!dev)
++		return -ENODEV;
++
++#ifdef CONFIG_NET_WIRELESS_RTNETLINK
++	if (ida[IFLA_WIRELESS - 1]) {
++
++		/* Call Wireless Extensions. We need to know the size before
++		 * we can alloc. Various stuff checked in there... */
++		err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
++		if (err)
++			goto out;
++	}
++#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */
++
++	/* Create a skb big enough to include all the data.
++	 * Some requests are way bigger than 4k... Jean II */
++	skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
++			GFP_KERNEL);
++	if (!skb)
++		goto out;
++	b = skb->tail;
++
++	/* Put in the message the usual good stuff */
++	nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
++			RTM_NEWLINK, sizeof(*r));
++	r = NLMSG_DATA(nlh);
++	r->ifi_family = AF_UNSPEC;
++	r->__ifi_pad = 0;
++	r->ifi_type = dev->type;
++	r->ifi_index = dev->ifindex;
++	r->ifi_flags = dev->flags;
++	r->ifi_change = 0;
++
++	/* Put the wireless payload if it exist */
++	if(iw_buf != NULL)
++		RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
++			iw_buf + IW_EV_POINT_OFF);
++
++	nlh->nlmsg_len = skb->tail - b;
++
++	/* Needed ? */
++	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
++
++	err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
++	if (err > 0)
++		err = 0;
++out:
++	if(iw_buf != NULL)
++		kfree(iw_buf);
++	dev_put(dev);
++	return err;
++
++rtattr_failure:
++nlmsg_failure:
++	kfree_skb(skb);
++	goto out;
++}
++#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */
++
+ static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+ 	int idx;
+@@ -585,7 +677,11 @@ static void rtnetlink_rcv(struct sock *s
+ 
+ static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
+ {
+-	[RTM_GETLINK     - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
++	[RTM_GETLINK     - RTM_BASE] = {
++#ifdef CONFIG_NET_WIRELESS_RTNETLINK
++					 .doit   = do_getlink,
++#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */
++					 .dumpit = rtnetlink_dump_ifinfo },
+ 	[RTM_SETLINK     - RTM_BASE] = { .doit   = do_setlink		 },
+ 	[RTM_GETADDR     - RTM_BASE] = { .dumpit = rtnetlink_dump_all	 },
+ 	[RTM_GETROUTE    - RTM_BASE] = { .dumpit = rtnetlink_dump_all	 },
+diff -u -p linux/net/core/wireless.19.c linux/net/core/wireless.c
+--- linux/net/core/wireless.19.c	2006-02-17 10:49:37.000000000 -0800
++++ linux/net/core/wireless.c	2006-02-22 11:46:52.000000000 -0800
+@@ -2,7 +2,7 @@
+  * This file implement the Wireless Extensions APIs.
+  *
+  * Authors :	Jean Tourrilhes - HPL - <jt at hpl.hp.com>
+- * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
+  *
+  * (As all part of the Linux kernel, this file is GPL)
+  */
+@@ -65,6 +65,9 @@
+  *	o Start deprecating dev->get_wireless_stats, output a warning
+  *	o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless
+  *	o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats)
++ *
++ * v8 - 17.02.06 - Jean II
++ *	o RtNetlink requests support (SET/GET)
+  */
+ 
+ /***************************** INCLUDES *****************************/
+@@ -89,11 +92,13 @@
+ 
+ /* Debugging stuff */
+ #undef WE_IOCTL_DEBUG		/* Debug IOCTL API */
++#undef WE_RTNETLINK_DEBUG	/* Debug RtNetlink API */
+ #undef WE_EVENT_DEBUG		/* Debug Event dispatcher */
+ #undef WE_SPY_DEBUG		/* Debug enhanced spy support */
+ 
+ /* Options */
+-#define WE_EVENT_NETLINK	/* Propagate events using rtnetlink */
++//CONFIG_NET_WIRELESS_RTNETLINK	/* Wireless requests over RtNetlink */
++#define WE_EVENT_RTNETLINK	/* Propagate events using RtNetlink */
+ #define WE_SET_EVENT		/* Generate an event on some set commands */
+ 
+ /************************* GLOBAL VARIABLES *************************/
+@@ -156,13 +161,18 @@ static const struct iw_ioctl_description
+ 		.header_type	= IW_HEADER_TYPE_NULL,
+ 	},
+ 	[SIOCGIWPRIV	- SIOCIWFIRST] = { /* (handled directly by us) */
+-		.header_type	= IW_HEADER_TYPE_NULL,
++		.header_type	= IW_HEADER_TYPE_POINT,
++		.token_size	= sizeof(struct iw_priv_args),
++		.max_tokens	= 16,
++		.flags		= IW_DESCR_FLAG_NOMAX,
+ 	},
+ 	[SIOCSIWSTATS	- SIOCIWFIRST] = {
+ 		.header_type	= IW_HEADER_TYPE_NULL,
+ 	},
+ 	[SIOCGIWSTATS	- SIOCIWFIRST] = { /* (handled directly by us) */
+-		.header_type	= IW_HEADER_TYPE_NULL,
++		.header_type	= IW_HEADER_TYPE_POINT,
++		.token_size	= 1,
++		.max_tokens	= sizeof(struct iw_statistics),
+ 		.flags		= IW_DESCR_FLAG_DUMP,
+ 	},
+ 	[SIOCSIWSPY	- SIOCIWFIRST] = {
+@@ -529,6 +539,70 @@ static inline int adjust_priv_size(__u16
+ 	return num * iw_priv_type_size[type];
+ }
+ 
++/* ---------------------------------------------------------------- */
++/*
++ * Standard Wireless Handler : get wireless stats
++ *	Allow programatic access to /proc/net/wireless even if /proc
++ *	doesn't exist... Also more efficient...
++ */
++static int iw_handler_get_iwstats(struct net_device *		dev,
++				  struct iw_request_info *	info,
++				  union iwreq_data *		wrqu,
++				  char *			extra)
++{
++	/* Get stats from the driver */
++	struct iw_statistics *stats;
++
++	stats = get_wireless_stats(dev);
++	if (stats != (struct iw_statistics *) NULL) {
++
++		/* Copy statistics to extra */
++		memcpy(extra, stats, sizeof(struct iw_statistics));
++		wrqu->data.length = sizeof(struct iw_statistics);
++
++		/* Check if we need to clear the updated flag */
++		if(wrqu->data.flags != 0)
++			stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
++		return 0;
++	} else
++		return -EOPNOTSUPP;
++}
++
++/* ---------------------------------------------------------------- */
++/*
++ * Standard Wireless Handler : get iwpriv definitions
++ * Export the driver private handler definition
++ * They will be picked up by tools like iwpriv...
++ */
++static int iw_handler_get_private(struct net_device *		dev,
++				  struct iw_request_info *	info,
++				  union iwreq_data *		wrqu,
++				  char *			extra)
++{
++	/* Check if the driver has something to export */
++	if((dev->wireless_handlers->num_private_args == 0) ||
++	   (dev->wireless_handlers->private_args == NULL))
++		return -EOPNOTSUPP;
++
++	/* Check if there is enough buffer up there */
++	if(wrqu->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... */
++		wrqu->data.length = dev->wireless_handlers->num_private_args;
++		return -E2BIG;
++	}
++
++	/* Set the number of available ioctls. */
++	wrqu->data.length = dev->wireless_handlers->num_private_args;
++
++	/* Copy structure to the user buffer. */
++	memcpy(extra, dev->wireless_handlers->private_args,
++	       sizeof(struct iw_priv_args) * wrqu->data.length);
++
++	return 0;
++}
++
+ 
+ /******************** /proc/net/wireless SUPPORT ********************/
+ /*
+@@ -630,81 +704,14 @@ int __init wireless_proc_init(void)
+ 
+ /* ---------------------------------------------------------------- */
+ /*
+- *	Allow programatic access to /proc/net/wireless even if /proc
+- *	doesn't exist... Also more efficient...
+- */
+-static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
+-{
+-	/* Get stats from the driver */
+-	struct iw_statistics *stats;
+-
+-	stats = get_wireless_stats(dev);
+-	if (stats != (struct iw_statistics *) NULL) {
+-		struct iwreq *	wrq = (struct iwreq *)ifr;
+-
+-		/* Copy statistics to the user buffer */
+-		if(copy_to_user(wrq->u.data.pointer, stats,
+-				sizeof(struct iw_statistics)))
+-			return -EFAULT;
+-
+-		/* Check if we need to clear the updated flag */
+-		if(wrq->u.data.flags != 0)
+-			stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
+-		return 0;
+-	} else
+-		return -EOPNOTSUPP;
+-}
+-
+-/* ---------------------------------------------------------------- */
+-/*
+- * Export the driver private handler definition
+- * They will be picked up by tools like iwpriv...
+- */
+-static inline int ioctl_export_private(struct net_device *	dev,
+-				       struct ifreq *		ifr)
+-{
+-	struct iwreq *				iwr = (struct iwreq *) ifr;
+-
+-	/* Check if the driver has something to export */
+-	if((dev->wireless_handlers->num_private_args == 0) ||
+-	   (dev->wireless_handlers->private_args == NULL))
+-		return -EOPNOTSUPP;
+-
+-	/* Check NULL pointer */
+-	if(iwr->u.data.pointer == NULL)
+-		return -EFAULT;
+-
+-	/* Check if there is enough buffer up there */
+-	if(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;
+-	}
+-
+-	/* Set the number of available ioctls. */
+-	iwr->u.data.length = dev->wireless_handlers->num_private_args;
+-
+-	/* Copy structure to the user buffer. */
+-	if (copy_to_user(iwr->u.data.pointer,
+-			 dev->wireless_handlers->private_args,
+-			 sizeof(struct iw_priv_args) * iwr->u.data.length))
+-		return -EFAULT;
+-
+-	return 0;
+-}
+-
+-/* ---------------------------------------------------------------- */
+-/*
+  * Wrapper to call a standard Wireless Extension handler.
+  * We do various checks and also take care of moving data between
+  * user space and kernel space.
+  */
+-static inline int ioctl_standard_call(struct net_device *	dev,
+-				      struct ifreq *		ifr,
+-				      unsigned int		cmd,
+-				      iw_handler		handler)
++static int ioctl_standard_call(struct net_device *	dev,
++			       struct ifreq *		ifr,
++			       unsigned int		cmd,
++			       iw_handler		handler)
+ {
+ 	struct iwreq *				iwr = (struct iwreq *) ifr;
+ 	const struct iw_ioctl_description *	descr;
+@@ -1048,14 +1055,20 @@ int wireless_process_ioctl(struct ifreq 
+ 	{
+ 		case SIOCGIWSTATS:
+ 			/* Get Wireless Stats */
+-			return dev_iwstats(dev, ifr);
++			return ioctl_standard_call(dev,
++						   ifr,
++						   cmd,
++						   &iw_handler_get_iwstats);
+ 
+ 		case SIOCGIWPRIV:
+ 			/* Check if we have some wireless handlers defined */
+ 			if(dev->wireless_handlers != NULL) {
+ 				/* We export to user space the definition of
+ 				 * the private handler ourselves */
+-				return ioctl_export_private(dev, ifr);
++				return ioctl_standard_call(dev,
++							   ifr,
++							   cmd,
++							   &iw_handler_get_private);
+ 			}
+ 			// ## Fall-through for old API ##
+ 		default:
+@@ -1088,16 +1101,739 @@ int wireless_process_ioctl(struct ifreq 
+ 	return -EINVAL;
+ }
+ 
++/********************** RTNETLINK REQUEST API **********************/
++/*
++ * The alternate user space API to configure all those Wireless Extensions
++ * is through RtNetlink.
++ * This API support only the new driver API (iw_handler).
++ *
++ * This RtNetlink API use the same query/reply model as the ioctl API.
++ * Maximum effort has been done to fit in the RtNetlink model, and
++ * we support both RtNetlink Set and RtNelink Get operations.
++ * On the other hand, we don't offer Dump operations because of the
++ * following reasons :
++ *	o Large number of parameters, most optional
++ *	o Large size of some parameters (> 100 bytes)
++ *	o Each parameters need to be extracted from hardware
++ *	o Scan requests can take seconds and disable network activity.
++ * Because of this high cost/overhead, we want to return only the
++ * parameters the user application is really interested in.
++ * We could offer partial Dump using the IW_DESCR_FLAG_DUMP flag.
++ *
++ * The API uses the standard RtNetlink socket. When the RtNetlink code
++ * find a IFLA_WIRELESS field in a RtNetlink SET_LINK request,
++ * it calls here.
++ */
++
++#ifdef CONFIG_NET_WIRELESS_RTNETLINK
++/* ---------------------------------------------------------------- */
++/*
++ * Wrapper to call a standard Wireless Extension GET handler.
++ * We do various checks and call the handler with the proper args.
++ */
++static int rtnetlink_standard_get(struct net_device *	dev,
++				  struct iw_event *	request,
++				  int			request_len,
++				  iw_handler		handler,
++				  char **		p_buf,
++				  int *			p_len)
++{
++	const struct iw_ioctl_description *	descr = NULL;
++	unsigned int				cmd;
++	union iwreq_data *			wrqu;
++	int					hdr_len;
++	struct iw_request_info			info;
++	char *					buffer = NULL;
++	int					buffer_size = 0;
++	int					ret = -EINVAL;
++
++	/* Get the description of the Request */
++	cmd = request->cmd;
++	if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
++		return -EOPNOTSUPP;
++	descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
++
++#ifdef WE_RTNETLINK_DEBUG
++	printk(KERN_DEBUG "%s (WE.r) : Found standard handler for 0x%04X\n",
++	       dev->name, cmd);
++	printk(KERN_DEBUG "%s (WE.r) : 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_RTNETLINK_DEBUG */
++
++	/* Check if wrqu is complete */
++	hdr_len = event_type_size[descr->header_type];
++	if(request_len < hdr_len) {
++#ifdef WE_RTNETLINK_DEBUG
++		printk(KERN_DEBUG
++		       "%s (WE.r) : Wireless request too short (%d)\n",
++		       dev->name, request_len);
++#endif	/* WE_RTNETLINK_DEBUG */
++		return -EINVAL;
++	}
++
++	/* Prepare the call */
++	info.cmd = cmd;
++	info.flags = 0;
++
++	/* Check if we have extra data in the reply or not */
++	if(descr->header_type != IW_HEADER_TYPE_POINT) {
++
++		/* Create the kernel buffer that we will return.
++		 * It's at an offset to match the TYPE_POINT case... */
++		buffer_size = request_len + IW_EV_POINT_OFF;
++		buffer = kmalloc(buffer_size, GFP_KERNEL);
++		if (buffer == NULL) {
++			return -ENOMEM;
++		}
++		/* Copy event data */
++		memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
++		/* Use our own copy of wrqu */
++		wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
++					     + IW_EV_LCP_LEN);
++
++		/* No extra arguments. Trivial to handle */
++		ret = handler(dev, &info, wrqu, NULL);
++
++	} else {
++		union iwreq_data	wrqu_point;
++		char *			extra = NULL;
++		int			extra_size = 0;
++
++		/* Get a temp copy of wrqu (skip pointer) */
++		memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
++		       ((char *) request) + IW_EV_LCP_LEN,
++		       IW_EV_POINT_LEN - IW_EV_LCP_LEN);
++
++		/* Calculate space needed by arguments. Always allocate
++		 * for max space. Easier, and won't last long... */
++		extra_size = descr->max_tokens * descr->token_size;
++		/* Support for very large requests */
++		if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
++		   (wrqu_point.data.length > descr->max_tokens))
++			extra_size = (wrqu_point.data.length
++				      * descr->token_size);
++		buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF;
++#ifdef WE_RTNETLINK_DEBUG
++		printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
++		       dev->name, extra_size, buffer_size);
++#endif	/* WE_RTNETLINK_DEBUG */
++
++		/* Create the kernel buffer that we will return */
++		buffer = kmalloc(buffer_size, GFP_KERNEL);
++		if (buffer == NULL) {
++			return -ENOMEM;
++		}
++
++		/* Put wrqu in the right place (just before extra).
++		 * Leave space for IWE header and dummy pointer...
++		 * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
++		 */
++		memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
++		       ((char *) &wrqu_point) + IW_EV_POINT_OFF,
++		       IW_EV_POINT_LEN - IW_EV_LCP_LEN);
++		wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN);
++
++		/* Extra comes logically after that. Offset +12 bytes. */
++		extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN;
++
++		/* Call the handler */
++		ret = handler(dev, &info, wrqu, extra);
<<Diff was trimmed, longer than 597 lines>>


More information about the pld-cvs-commit mailing list