Netdev List
 help / color / mirror / Atom feed
From: Masakazu Mokuno <mokuno-DfbDroY8Xu1L9jVzuh4AOg@public.gmane.org>
To: David Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: : Emit event stream compat iw_point objects correctly.
Date: Fri, 11 Jan 2008 13:16:29 +0900	[thread overview]
Message-ID: <20080111112248.610C.40F06B3A@sm.sony.co.jp> (raw)
In-Reply-To: <20080110.011602.74511551.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 12627 bytes --]

	Hi

Thank you for updating the patch.

On Thu, 10 Jan 2008 01:16:02 -0800 (PST)
David Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org> wrote:

> From: Masakazu Mokuno <mokuno-DfbDroY8Xu1L9jVzuh4AOg@public.gmane.org>
> Date: Thu, 27 Dec 2007 18:24:40 +0900
> 
> > On ppc64 (PS3), IW_EV_LCP_LEN is 8, not 4.
> > 
> > include/linux/wireless.h:
> > 
> > #define IW_EV_LCP_LEN   (sizeof(struct iw_event) - sizeof(union iwreq_data))
> > 
> > where sizeof(struct iw_event) == 24, sizeof(union iwreq_data) == 16 on
> > PS3.
> 
> Here is a new version of the last patch (#12), it should handle
> all of these cases properly now.
> 
> Let me know if you spot any more errors.
> 
> Thanks!
> 
> [WEXT]: Emit event stream entries correctly when compat.
> 
> Three major portions to this change:
> 
> 1) Add IW_EV_COMPAT_LCP_LEN, IW_EV_COMPAT_POINT_OFF,
>    and IW_EV_COMPAT_POINT_LEN helper defines.
> 
> 2) Delete iw_stream_check_add_*(), they are unused.
> 
> 3) Add iw_request_info argument to iwe_stream_add_*(), and use it to
>    size the event and pointer lengths correctly depending upon whether
>    IW_REQUEST_FLAG_COMPAT is set or not.
> 
> 4) The mechanical transformations to the drivers and wireless stack
>    bits to get the iw_request_info passed down into the routines
>    modified in #3.
> 
> With help from Masakazu Mokuno
> 
> Signed-off-by: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
> ---
>  drivers/net/wireless/airo.c                |   39 +++++---
>  drivers/net/wireless/atmel.c               |   24 ++++-
>  drivers/net/wireless/hostap/hostap.h       |    3 +-
>  drivers/net/wireless/hostap/hostap_ap.c    |   32 +++---
>  drivers/net/wireless/hostap/hostap_ioctl.c |   54 ++++++-----
>  drivers/net/wireless/libertas/scan.c       |   35 ++++---
>  drivers/net/wireless/orinoco.c             |   30 ++++--
>  drivers/net/wireless/prism54/isl_ioctl.c   |   45 +++++----
>  drivers/net/wireless/wl3501_cs.c           |   10 +-
>  drivers/net/wireless/zd1201.c              |   21 +++--
>  include/linux/wireless.h                   |   16 +++
>  include/net/iw_handler.h                   |  150 ++++++++--------------------
>  net/ieee80211/ieee80211_wx.c               |   44 +++++----
>  net/mac80211/ieee80211_i.h                 |    5 +-
>  net/mac80211/ieee80211_ioctl.c             |    2 +-
>  net/mac80211/ieee80211_sta.c               |   59 ++++++-----
>  16 files changed, 293 insertions(+), 276 deletions(-)

[snip]

> diff --git a/include/linux/wireless.h b/include/linux/wireless.h
> index 2088524..bec73df 100644
> --- a/include/linux/wireless.h
> +++ b/include/linux/wireless.h
> @@ -1098,6 +1098,22 @@ struct iw_event
>  #define IW_EV_POINT_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_point) - \
>  			 IW_EV_POINT_OFF)
>  
> +#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
> +struct __compat_iw_event {
> +	__u16		len;			/* Real lenght of this stuff */
                                                         ~~~~~
length?

> +	__u16		cmd;			/* Wireless IOCTL */
> +	compat_caddr_t	pointer;
> +};
> +#define IW_EV_COMPAT_LCP_LEN \
> +	(sizeof(struct __compat_iw_event) - sizeof(compat_caddr_t))
> +#define IW_EV_COMPAT_POINT_OFF (((char *) \
> +			  &(((struct compat_iw_point *) NULL)->length)) - \
> +			  (char *) NULL)

How about the followings?

#define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer)
#define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length)

> +#define IW_EV_COMPAT_POINT_LEN	\
> +	(IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \
> +	 IW_EV_COMPAT_POINT_OFF)
> +#endif
> +
>  /* Size of the Event prefix when packed in stream */
>  #define IW_EV_LCP_PK_LEN	(4)
>  /* Size of the various events when packed in stream */
> diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
> index c99a8ee..d6f0c51 100644
> --- a/include/net/iw_handler.h
> +++ b/include/net/iw_handler.h
> @@ -483,19 +483,26 @@ extern void wireless_spy_update(struct net_device *	dev,
>   * 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 */
> +iwe_stream_add_event(struct iw_request_info *info, char *stream, char *ends,
> +		     struct iw_event *iwe, int event_len)
>  {
> +	int lcp_len = IW_EV_LCP_LEN;
> +
> +#ifdef CONFIG_COMPAT
> +	if (info->flags & IW_REQUEST_FLAG_COMPAT) {
> +		event_len -= IW_EV_LCP_LEN;
> +		event_len += IW_EV_COMPAT_LCP_LEN;
> +		lcp_len = IW_EV_COMPAT_LCP_LEN;
> +	}
> +#endif
>  	/* Check if it's possible */
>  	if(likely((stream + event_len) < ends)) {
>  		iwe->len = event_len;
>  		/* Beware of alignement issues on 64 bits */
>  		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
> -		memcpy(stream + IW_EV_LCP_LEN,
> -		       ((char *) iwe) + IW_EV_LCP_LEN,
> -		       event_len - IW_EV_LCP_LEN);
> +		memcpy(stream + lcp_len,
> +		       ((char *) iwe) + lcp_len,

The source address does not have to be adjusted.  I think it should be
		       ((char *) iwe) + IW_EV_LCP_LEN,
or just
		       &iwe->u
I think it is more readable what we want to do here.


> +		       event_len - lcp_len);

The length of the real payload does not need to take account of the
destination offset change.  So we can keep the original code like:

		       org_event_len - IW_EV_LCP_LEN);

>  		stream += event_len;
>  	}
>  	return stream;
> @@ -507,104 +514,33 @@ iwe_stream_add_event(char *	stream,		/* Stream of events */
>   * 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 length + flags */
> -		     char *	extra)		/* More payload */
> +iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends,
> +		     struct iw_event *iwe, char *extra)
>  {
> -	int	event_len = IW_EV_POINT_LEN + iwe->u.data.length;
> -	/* Check if it's possible */
> -	if(likely((stream + event_len) < ends)) {
> -		iwe->len = event_len;
> -		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
> -		memcpy(stream + IW_EV_LCP_LEN,
> -		       ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
> -		       IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
> -		memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
> -		stream += event_len;
> +	int event_len = IW_EV_POINT_LEN + iwe->u.data.length;
> +	int point_len = IW_EV_POINT_LEN;
> +	int lcp_len = IW_EV_LCP_LEN;
> +	int point_off = IW_EV_POINT_OFF;
> +
> +#ifdef CONFIG_COMPAT
> +	if (info->flags & IW_REQUEST_FLAG_COMPAT) {
> +		event_len = IW_EV_COMPAT_POINT_LEN + iwe->u.data.length;
> +		point_len = IW_EV_COMPAT_POINT_LEN;
> +		lcp_len = IW_EV_COMPAT_LCP_LEN;
> +		point_off = IW_EV_COMPAT_POINT_OFF;
>  	}
> -	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;
> +#endif
>  
>  	/* Check if it's possible */
> -	if(likely((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;
> -}
> -
> -/*------------------------------------------------------------------*/
> -/*
> - * Wrapper to add an Wireless Event to a stream of events.
> - * Same as above, with explicit error check...
> - */
> -static inline char *
> -iwe_stream_check_add_event(char *	stream,		/* Stream of events */
> -			   char *	ends,		/* End of stream */
> -			   struct iw_event *iwe,	/* Payload */
> -			   int		event_len,	/* Size of payload */
> -			   int *	perr)		/* Error report */
> -{
> -	/* Check if it's possible, set error if not */
>  	if(likely((stream + event_len) < ends)) {
>  		iwe->len = event_len;
> -		/* Beware of alignement issues on 64 bits */
>  		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
> -		memcpy(stream + IW_EV_LCP_LEN,
> -		       ((char *) iwe) + IW_EV_LCP_LEN,
> -		       event_len - IW_EV_LCP_LEN);
> -		stream += event_len;
> -	} else
> -		*perr = -E2BIG;
> -	return stream;
> -}
> -
> -/*------------------------------------------------------------------*/
> -/*
> - * Wrapper to add an short Wireless Event containing a pointer to a
> - * stream of events.
> - * Same as above, with explicit error check...
> - */
> -static inline char *
> -iwe_stream_check_add_point(char *	stream,		/* Stream of events */
> -			   char *	ends,		/* End of stream */
> -			   struct iw_event *iwe,	/* Payload length + flags */
> -			   char *	extra,		/* More payload */
> -			   int *	perr)		/* Error report */
> -{
> -	int	event_len = IW_EV_POINT_LEN + iwe->u.data.length;
> -	/* Check if it's possible */
> -	if(likely((stream + event_len) < ends)) {
> -		iwe->len = event_len;
> -		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
> -		memcpy(stream + IW_EV_LCP_LEN,
> -		       ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
> +		memcpy(stream + lcp_len,
> +		       ((char *) iwe) + lcp_len + point_off,

Same as iwe_stream_add_event().  Source address does not need to be
fixed.

>  		       IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
> -		memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
> +		memcpy(stream + point_len, extra, iwe->u.data.length);
>  		stream += event_len;
> -	} else
> -		*perr = -E2BIG;
> +	}
>  	return stream;
>  }
>  
> @@ -613,29 +549,29 @@ iwe_stream_check_add_point(char *	stream,		/* Stream of events */
>   * 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).
> - * Same as above, with explicit error check...
>   */
>  static inline char *
> -iwe_stream_check_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,	/* Size of payload */
> -			   int *	perr)		/* Error report */
> +iwe_stream_add_value(struct iw_request_info *info, char *event, char *value,
> +		     char *ends, struct iw_event *iwe, int event_len)
>  {
> +	int lcp_len = IW_EV_LCP_LEN;
> +
> +#ifdef CONFIG_COMPAT
> +	if (info->flags & IW_REQUEST_FLAG_COMPAT)
> +		lcp_len = IW_EV_COMPAT_LCP_LEN;
> +#endif
>  	/* Don't duplicate LCP */
>  	event_len -= IW_EV_LCP_LEN;
>  
>  	/* Check if it's possible */
>  	if(likely((value + event_len) < ends)) {
>  		/* Add new value */
> -		memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
> +		memcpy(value, (char *) iwe + lcp_len, event_len);

Same as iwe_stream_add_event(). We can keep the original code.

>  		value += event_len;
>  		/* Patch LCP */
>  		iwe->len = value - event;
> -		memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
> -	} else
> -		*perr = -E2BIG;
> +		memcpy(event, (char *) iwe, lcp_len);
> +	}
>  	return value;
>  }


iwe_stream_add_value() is a bit tricky, so callers of this function
should do some adjusting work.  For example,
ieee80211_translate_scan():ieee80211_wx.c needs like:

 	/* Add basic and extended rates */
 	/* Rate : stuffing multiple values in a single event require a bit
 	 * more of magic - Jean II */
+#ifdef CONFIG_COMPAT
+	if (info->flags & IW_REQUEST_FLAG_COMPAT)
+		current_val = start + IW_EV_COMPAT_LCP_LEN;
+	else
+		current_val = start + IW_EV_LCP_LEN;
+#else
 	current_val = start + IW_EV_LCP_LEN;
+#endif
 	iwe.cmd = SIOCGIWRATE;
 	/* Those two flags are ignored... */
 	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;


I tried to make the patch that was incorporated with my comments above and
tested it with zd1211 based USB wireless adapter on my PS3.  It seemed
that the scan result prints from iwlist was OK.  The attached is the
patch. 
But wpa_supplicant did not work properly with it.  Although I did not
look it closely, it seemed that wpa_supplicant got a NULL IWAP event
when associated.


-- 
Masakazu MOKUNO

[-- Attachment #2: davem-12-modified.patch --]
[-- Type: application/octet-stream, Size: 58860 bytes --]

Here is a new version of the last patch (#12), it should handle
all of these cases properly now.

Let me know if you spot any more errors.

Thanks!

[WEXT]: Emit event stream entries correctly when compat.

Three major portions to this change:

1) Add IW_EV_COMPAT_LCP_LEN, IW_EV_COMPAT_POINT_OFF,
   and IW_EV_COMPAT_POINT_LEN helper defines.

2) Delete iw_stream_check_add_*(), they are unused.

3) Add iw_request_info argument to iwe_stream_add_*(), and use it to
   size the event and pointer lengths correctly depending upon whether
   IW_REQUEST_FLAG_COMPAT is set or not.

4) The mechanical transformations to the drivers and wireless stack
   bits to get the iw_request_info passed down into the routines
   modified in #3.

With help from Masakazu Mokuno

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/wireless/airo.c                |   46 +++++---
 drivers/net/wireless/atmel.c               |   24 +++-
 drivers/net/wireless/hostap/hostap.h       |    3 
 drivers/net/wireless/hostap/hostap_ap.c    |   32 ++---
 drivers/net/wireless/hostap/hostap_ioctl.c |   61 ++++++----
 drivers/net/wireless/libertas/scan.c       |   42 ++++---
 drivers/net/wireless/orinoco.c             |   41 ++++---
 drivers/net/wireless/prism54/isl_ioctl.c   |   55 ++++++---
 drivers/net/wireless/wl3501_cs.c           |   10 -
 drivers/net/wireless/zd1201.c              |   21 ++-
 include/linux/wireless.h                   |   13 ++
 include/net/iw_handler.h                   |  164 +++++++++--------------------
 net/ieee80211/ieee80211_wx.c               |   51 +++++----
 net/mac80211/ieee80211_i.h                 |    5 
 net/mac80211/ieee80211_ioctl.c             |    2 
 net/mac80211/ieee80211_sta.c               |   59 +++++-----
 16 files changed, 346 insertions(+), 283 deletions(-)

--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -7234,6 +7234,7 @@ out:
  * format that the Wireless Tools will understand - Jean II
  */
 static inline char *airo_translate_scan(struct net_device *dev,
+					struct iw_request_info *info,
 					char *current_ev,
 					char *end_buf,
 					BSSListRid *bss)
@@ -7249,7 +7250,8 @@ static inline char *airo_translate_scan(
 	iwe.cmd = SIOCGIWAP;
 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 	memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_ADDR_LEN);
 
 	/* Other entries will be displayed in the order we give them */
 
@@ -7259,7 +7261,8 @@ static inline char *airo_translate_scan(
 		iwe.u.data.length = 32;
 	iwe.cmd = SIOCGIWESSID;
 	iwe.u.data.flags = 1;
-	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
+	current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+					  &iwe, bss->ssid);
 
 	/* Add mode */
 	iwe.cmd = SIOCGIWMODE;
@@ -7269,7 +7272,8 @@ static inline char *airo_translate_scan(
 			iwe.u.mode = IW_MODE_MASTER;
 		else
 			iwe.u.mode = IW_MODE_ADHOC;
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_UINT_LEN);
 	}
 
 	/* Add frequency */
@@ -7280,7 +7284,8 @@ static inline char *airo_translate_scan(
 	 */
 	iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
 	iwe.u.freq.e = 1;
-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_FREQ_LEN);
 
 	/* Add quality statistics */
 	iwe.cmd = IWEVQUAL;
@@ -7298,7 +7303,8 @@ static inline char *airo_translate_scan(
 				| IW_QUAL_DBM;
 	}
 	iwe.u.qual.noise = ai->wstats.qual.noise;
-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_QUAL_LEN);
 
 	/* Add encryption capability */
 	iwe.cmd = SIOCGIWENCODE;
@@ -7307,11 +7313,19 @@ static inline char *airo_translate_scan(
 	else
 		iwe.u.data.flags = IW_ENCODE_DISABLED;
 	iwe.u.data.length = 0;
-	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
+	current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+					  &iwe, bss->ssid);
 
 	/* Rate : stuffing multiple values in a single event require a bit
 	 * more of magic - Jean II */
+#ifdef CONFIG_COMPAT
+	if (info->flags & IW_REQUEST_FLAG_COMPAT)
+		current_val = current_ev + IW_EV_COMPAT_LCP_LEN;
+	else
+		current_val = current_ev + IW_EV_LCP_LEN;
+#else
 	current_val = current_ev + IW_EV_LCP_LEN;
+#endif
 
 	iwe.cmd = SIOCGIWRATE;
 	/* Those two flags are ignored... */
@@ -7324,7 +7338,9 @@ static inline char *airo_translate_scan(
 		/* Bit rate given in 500 kb/s units (+ 0x80) */
 		iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000);
 		/* Add new value to event */
-		current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
+		current_val = iwe_stream_add_value(info, current_ev,
+						   current_val, end_buf,
+						   &iwe, IW_EV_PARAM_LEN);
 	}
 	/* Check if we added any event */
 	if((current_val - current_ev) > IW_EV_LCP_LEN)
@@ -7336,7 +7352,8 @@ static inline char *airo_translate_scan(
 		iwe.cmd = IWEVCUSTOM;
 		sprintf(buf, "bcn_int=%d", bss->beaconInterval);
 		iwe.u.data.length = strlen(buf);
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, buf);
 		kfree(buf);
 	}
 
@@ -7370,8 +7387,10 @@ static inline char *airo_translate_scan(
 					iwe.cmd = IWEVGENIE;
 					iwe.u.data.length = min(info_element->len + 2,
 								  MAX_WPA_IE_LEN);
-					current_ev = iwe_stream_add_point(current_ev, end_buf,
-							&iwe, (char *) info_element);
+					current_ev = iwe_stream_add_point(
+							info, current_ev,
+							end_buf, &iwe,
+							(char *) info_element);
 				}
 				break;
 
@@ -7379,8 +7398,9 @@ static inline char *airo_translate_scan(
 				iwe.cmd = IWEVGENIE;
 				iwe.u.data.length = min(info_element->len + 2,
 							  MAX_WPA_IE_LEN);
-				current_ev = iwe_stream_add_point(current_ev, end_buf,
-						&iwe, (char *) info_element);
+				current_ev = iwe_stream_add_point(
+					info, current_ev, end_buf,
+					&iwe, (char *) info_element);
 				break;
 
 			default:
@@ -7419,7 +7439,7 @@ static int airo_get_scan(struct net_devi
 
 	list_for_each_entry (net, &ai->network_list, list) {
 		/* Translate to WE format this entry */
-		current_ev = airo_translate_scan(dev, current_ev,
+		current_ev = airo_translate_scan(dev, info, current_ev,
 						 extra + dwrq->length,
 						 &net->bss);
 
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -2320,30 +2320,40 @@ static int atmel_get_scan(struct net_dev
 		iwe.cmd = SIOCGIWAP;
 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 		memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6);
-		current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev,
+						  extra + IW_SCAN_MAX_DATA,
+						  &iwe, IW_EV_ADDR_LEN);
 
 		iwe.u.data.length =  priv->BSSinfo[i].SSIDsize;
 		if (iwe.u.data.length > 32)
 			iwe.u.data.length = 32;
 		iwe.cmd = SIOCGIWESSID;
 		iwe.u.data.flags = 1;
-		current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, priv->BSSinfo[i].SSID);
+		current_ev = iwe_stream_add_point(info, current_ev,
+						  extra + IW_SCAN_MAX_DATA,
+						  &iwe, priv->BSSinfo[i].SSID);
 
 		iwe.cmd = SIOCGIWMODE;
 		iwe.u.mode = priv->BSSinfo[i].BSStype;
-		current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev,
+						  extra + IW_SCAN_MAX_DATA,
+						  &iwe, IW_EV_UINT_LEN);
 
 		iwe.cmd = SIOCGIWFREQ;
 		iwe.u.freq.m = priv->BSSinfo[i].channel;
 		iwe.u.freq.e = 0;
-		current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev,
+						  extra + IW_SCAN_MAX_DATA,
+						  &iwe, IW_EV_FREQ_LEN);
 
 		/* Add quality statistics */
 		iwe.cmd = IWEVQUAL;
 		iwe.u.qual.level = priv->BSSinfo[i].RSSI;
 		iwe.u.qual.qual  = iwe.u.qual.level;
 		/* iwe.u.qual.noise  = SOMETHING */
-		current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA , &iwe, IW_EV_QUAL_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev,
+						  extra + IW_SCAN_MAX_DATA,
+						  &iwe, IW_EV_QUAL_LEN);
 
 
 		iwe.cmd = SIOCGIWENCODE;
@@ -2352,7 +2362,9 @@ static int atmel_get_scan(struct net_dev
 		else
 			iwe.u.data.flags = IW_ENCODE_DISABLED;
 		iwe.u.data.length = 0;
-		current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL);
+		current_ev = iwe_stream_add_point(info, current_ev,
+						  extra + IW_SCAN_MAX_DATA,
+						  &iwe, NULL);
 	}
 
 	/* Length of data */
--- a/drivers/net/wireless/hostap/hostap.h
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -67,7 +67,8 @@ void * ap_crypt_get_ptrs(struct ap_data 
 int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
 			   struct iw_quality qual[], int buf_size,
 			   int aplist);
-int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
+int prism2_ap_translate_scan(struct net_device *dev,
+			     struct iw_request_info *info, char *buffer);
 int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param);
 
 
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -2381,7 +2381,8 @@ int prism2_ap_get_sta_qual(local_info_t 
 
 /* Translate our list of Access Points & Stations to a card independant
  * format that the Wireless Tools will understand - Jean II */
-int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
+int prism2_ap_translate_scan(struct net_device *dev,
+			     struct iw_request_info *info, char *buffer)
 {
 	struct hostap_interface *iface;
 	local_info_t *local;
@@ -2410,8 +2411,8 @@ int prism2_ap_translate_scan(struct net_
 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 		memcpy(iwe.u.ap_addr.sa_data, sta->addr, ETH_ALEN);
 		iwe.len = IW_EV_ADDR_LEN;
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-						  IW_EV_ADDR_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_ADDR_LEN);
 
 		/* Use the mode to indicate if it's a station or
 		 * an Access Point */
@@ -2422,8 +2423,8 @@ int prism2_ap_translate_scan(struct net_
 		else
 			iwe.u.mode = IW_MODE_INFRA;
 		iwe.len = IW_EV_UINT_LEN;
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-						  IW_EV_UINT_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_UINT_LEN);
 
 		/* Some quality */
 		memset(&iwe, 0, sizeof(iwe));
@@ -2438,8 +2439,8 @@ int prism2_ap_translate_scan(struct net_
 		iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
 		iwe.u.qual.updated = sta->last_rx_updated;
 		iwe.len = IW_EV_QUAL_LEN;
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-						  IW_EV_QUAL_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_QUAL_LEN);
 
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
 		if (sta->ap) {
@@ -2447,8 +2448,8 @@ int prism2_ap_translate_scan(struct net_
 			iwe.cmd = SIOCGIWESSID;
 			iwe.u.data.length = sta->u.ap.ssid_len;
 			iwe.u.data.flags = 1;
-			current_ev = iwe_stream_add_point(current_ev, end_buf,
-							  &iwe,
+			current_ev = iwe_stream_add_point(info, current_ev,
+							  end_buf, &iwe,
 							  sta->u.ap.ssid);
 
 			memset(&iwe, 0, sizeof(iwe));
@@ -2458,10 +2459,9 @@ int prism2_ap_translate_scan(struct net_
 					IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 			else
 				iwe.u.data.flags = IW_ENCODE_DISABLED;
-			current_ev = iwe_stream_add_point(current_ev, end_buf,
-							  &iwe,
-							  sta->u.ap.ssid
-							  /* 0 byte memcpy */);
+			current_ev = iwe_stream_add_point(info, current_ev,
+							  end_buf, &iwe,
+							  sta->u.ap.ssid);
 
 			if (sta->u.ap.channel > 0 &&
 			    sta->u.ap.channel <= FREQ_COUNT) {
@@ -2471,7 +2471,7 @@ int prism2_ap_translate_scan(struct net_
 					* 100000;
 				iwe.u.freq.e = 1;
 				current_ev = iwe_stream_add_event(
-					current_ev, end_buf, &iwe,
+					info, current_ev, end_buf, &iwe,
 					IW_EV_FREQ_LEN);
 			}
 
@@ -2480,8 +2480,8 @@ int prism2_ap_translate_scan(struct net_
 			sprintf(buf, "beacon_interval=%d",
 				sta->listen_interval);
 			iwe.u.data.length = strlen(buf);
-			current_ev = iwe_stream_add_point(current_ev, end_buf,
-							  &iwe, buf);
+			current_ev = iwe_stream_add_point(info, current_ev,
+							  end_buf, &iwe, buf);
 		}
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1794,6 +1794,7 @@ static int prism2_ioctl_siwscan(struct n
 
 #ifndef PRISM2_NO_STATION_MODES
 static char * __prism2_translate_scan(local_info_t *local,
+				      struct iw_request_info *info,
 				      struct hfa384x_hostscan_result *scan,
 				      struct hostap_bss_info *bss,
 				      char *current_ev, char *end_buf)
@@ -1824,7 +1825,7 @@ static char * __prism2_translate_scan(lo
 	iwe.cmd = SIOCGIWAP;
 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 	memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
 					  IW_EV_ADDR_LEN);
 
 	/* Other entries will be displayed in the order we give them */
@@ -1833,7 +1834,8 @@ static char * __prism2_translate_scan(lo
 	iwe.cmd = SIOCGIWESSID;
 	iwe.u.data.length = ssid_len;
 	iwe.u.data.flags = 1;
-	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid);
+	current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+					  &iwe, ssid);
 
 	memset(&iwe, 0, sizeof(iwe));
 	iwe.cmd = SIOCGIWMODE;
@@ -1848,8 +1850,8 @@ static char * __prism2_translate_scan(lo
 			iwe.u.mode = IW_MODE_MASTER;
 		else
 			iwe.u.mode = IW_MODE_ADHOC;
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-						  IW_EV_UINT_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_UINT_LEN);
 	}
 
 	memset(&iwe, 0, sizeof(iwe));
@@ -1865,8 +1867,8 @@ static char * __prism2_translate_scan(lo
 	if (chan > 0) {
 		iwe.u.freq.m = freq_list[chan - 1] * 100000;
 		iwe.u.freq.e = 1;
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-						  IW_EV_FREQ_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_FREQ_LEN);
 	}
 
 	if (scan) {
@@ -1885,8 +1887,8 @@ static char * __prism2_translate_scan(lo
 			| IW_QUAL_NOISE_UPDATED
 			| IW_QUAL_QUAL_INVALID
 			| IW_QUAL_DBM;
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-						  IW_EV_QUAL_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_QUAL_LEN);
 	}
 
 	memset(&iwe, 0, sizeof(iwe));
@@ -1896,13 +1898,20 @@ static char * __prism2_translate_scan(lo
 	else
 		iwe.u.data.flags = IW_ENCODE_DISABLED;
 	iwe.u.data.length = 0;
-	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
+	current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, "");
 
 	/* TODO: add SuppRates into BSS table */
 	if (scan) {
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = SIOCGIWRATE;
+#ifdef CONFIG_COMPAT
+		if (info->flags & IW_REQUEST_FLAG_COMPAT)
+			current_val = current_ev + IW_EV_COMPAT_LCP_LEN;
+		else
+			current_val = current_ev + IW_EV_LCP_LEN;
+#else
 		current_val = current_ev + IW_EV_LCP_LEN;
+#endif
 		pos = scan->sup_rates;
 		for (i = 0; i < sizeof(scan->sup_rates); i++) {
 			if (pos[i] == 0)
@@ -1910,7 +1919,7 @@ static char * __prism2_translate_scan(lo
 			/* Bit rate given in 500 kb/s units (+ 0x80) */
 			iwe.u.bitrate.value = ((pos[i] & 0x7f) * 500000);
 			current_val = iwe_stream_add_value(
-				current_ev, current_val, end_buf, &iwe,
+				info, current_ev, current_val, end_buf, &iwe,
 				IW_EV_PARAM_LEN);
 		}
 		/* Check if we added any event */
@@ -1925,15 +1934,15 @@ static char * __prism2_translate_scan(lo
 		iwe.cmd = IWEVCUSTOM;
 		sprintf(buf, "bcn_int=%d", le16_to_cpu(scan->beacon_interval));
 		iwe.u.data.length = strlen(buf);
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-						  buf);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, buf);
 
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = IWEVCUSTOM;
 		sprintf(buf, "resp_rate=%d", le16_to_cpu(scan->rate));
 		iwe.u.data.length = strlen(buf);
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-						  buf);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, buf);
 
 		if (local->last_scan_type == PRISM2_HOSTSCAN &&
 		    (capabilities & WLAN_CAPABILITY_IBSS)) {
@@ -1941,8 +1950,8 @@ static char * __prism2_translate_scan(lo
 			iwe.cmd = IWEVCUSTOM;
 			sprintf(buf, "atim=%d", le16_to_cpu(scan->atim));
 			iwe.u.data.length = strlen(buf);
-			current_ev = iwe_stream_add_point(current_ev, end_buf,
-							  &iwe, buf);
+			current_ev = iwe_stream_add_point(info, current_ev,
+							  end_buf, &iwe, buf);
 		}
 	}
 	kfree(buf);
@@ -1951,16 +1960,16 @@ static char * __prism2_translate_scan(lo
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = bss->wpa_ie_len;
-		current_ev = iwe_stream_add_point(
-			current_ev, end_buf, &iwe, bss->wpa_ie);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, bss->wpa_ie);
 	}
 
 	if (bss && bss->rsn_ie_len > 0 && bss->rsn_ie_len <= MAX_WPA_IE_LEN) {
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = bss->rsn_ie_len;
-		current_ev = iwe_stream_add_point(
-			current_ev, end_buf, &iwe, bss->rsn_ie);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, bss->rsn_ie);
 	}
 
 	return current_ev;
@@ -1970,6 +1979,7 @@ static char * __prism2_translate_scan(lo
 /* Translate scan data returned from the card to a card independant
  * format that the Wireless Tools will understand - Jean II */
 static inline int prism2_translate_scan(local_info_t *local,
+					struct iw_request_info *info,
 					char *buffer, int buflen)
 {
 	struct hfa384x_hostscan_result *scan;
@@ -2000,13 +2010,14 @@ static inline int prism2_translate_scan(
 			if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) {
 				bss->included = 1;
 				current_ev = __prism2_translate_scan(
-					local, scan, bss, current_ev, end_buf);
+					local, info, scan, bss, current_ev,
+					end_buf);
 				found++;
 			}
 		}
 		if (!found) {
 			current_ev = __prism2_translate_scan(
-				local, scan, NULL, current_ev, end_buf);
+				local, info, scan, NULL, current_ev, end_buf);
 		}
 		/* Check if there is space for one more entry */
 		if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) {
@@ -2024,7 +2035,7 @@ static inline int prism2_translate_scan(
 		bss = list_entry(ptr, struct hostap_bss_info, list);
 		if (bss->included)
 			continue;
-		current_ev = __prism2_translate_scan(local, NULL, bss,
+		current_ev = __prism2_translate_scan(local, info, NULL, bss,
 						     current_ev, end_buf);
 		/* Check if there is space for one more entry */
 		if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) {
@@ -2071,7 +2082,7 @@ static inline int prism2_ioctl_giwscan_s
 	}
 	local->scan_timestamp = 0;
 
-	res = prism2_translate_scan(local, extra, data->length);
+	res = prism2_translate_scan(local, info, extra, data->length);
 
 	if (res >= 0) {
 		data->length = res;
@@ -2104,7 +2115,7 @@ static int prism2_ioctl_giwscan(struct n
 		 * Jean II */
 
 		/* Translate to WE format */
-		res = prism2_ap_translate_scan(dev, extra);
+		res = prism2_ap_translate_scan(dev, info, extra);
 		if (res >= 0) {
 			printk(KERN_DEBUG "Scan result translation succeeded "
 			       "(length=%d)\n", res);
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -1444,8 +1444,9 @@ out:
 #define MAX_CUSTOM_LEN 64
 
 static inline char *libertas_translate_scan(wlan_private *priv,
-					char *start, char *stop,
-					struct bss_descriptor *bss)
+					    struct iw_request_info *info,
+					    char *start, char *stop,
+					    struct bss_descriptor *bss)
 {
 	wlan_adapter *adapter = priv->adapter;
 	struct chan_freq_power *cfp;
@@ -1470,24 +1471,24 @@ static inline char *libertas_translate_s
 	iwe.cmd = SIOCGIWAP;
 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 	memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
+	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
 
 	/* SSID */
 	iwe.cmd = SIOCGIWESSID;
 	iwe.u.data.flags = 1;
 	iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE);
-	start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
+	start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
 
 	/* Mode */
 	iwe.cmd = SIOCGIWMODE;
 	iwe.u.mode = bss->mode;
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
+	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
 
 	/* Frequency */
 	iwe.cmd = SIOCGIWFREQ;
 	iwe.u.freq.m = (long)cfp->freq * 100000;
 	iwe.u.freq.e = 1;
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
+	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
 
 	/* Add quality statistics */
 	iwe.cmd = IWEVQUAL;
@@ -1523,7 +1524,7 @@ static inline char *libertas_translate_s
 		nf = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
 		iwe.u.qual.level = CAL_RSSI(snr, nf);
 	}
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
+	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
 
 	/* Add encryption capability */
 	iwe.cmd = SIOCGIWENCODE;
@@ -1533,9 +1534,16 @@ static inline char *libertas_translate_s
 		iwe.u.data.flags = IW_ENCODE_DISABLED;
 	}
 	iwe.u.data.length = 0;
-	start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
+	start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
 
+#ifdef CONFIG_COMPAT
+	if (info->flags & IW_REQUEST_FLAG_COMPAT)
+		current_val = start + IW_EV_COMAT_LCP_LEN;
+	else
+		current_val = start + IW_EV_LCP_LEN;
+#else
 	current_val = start + IW_EV_LCP_LEN;
+#endif
 
 	iwe.cmd = SIOCGIWRATE;
 	iwe.u.bitrate.fixed = 0;
@@ -1545,8 +1553,8 @@ static inline char *libertas_translate_s
 	for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {
 		/* Bit rate given in 500 kb/s units */
 		iwe.u.bitrate.value = bss->rates[j] * 500000;
-		current_val = iwe_stream_add_value(start, current_val,
-					 stop, &iwe, IW_EV_PARAM_LEN);
+		current_val = iwe_stream_add_value(info, start, current_val,
+						   stop, &iwe, IW_EV_PARAM_LEN);
 	}
 	if ((bss->mode == IW_MODE_ADHOC)
 	    && !libertas_ssid_cmp(adapter->curbssparams.ssid,
@@ -1554,8 +1562,8 @@ static inline char *libertas_translate_s
 	                          bss->ssid, bss->ssid_len)
 	    && adapter->adhoccreate) {
 		iwe.u.bitrate.value = 22 * 500000;
-		current_val = iwe_stream_add_value(start, current_val,
-					 stop, &iwe, IW_EV_PARAM_LEN);
+		current_val = iwe_stream_add_value(info, start, current_val,
+						   stop, &iwe, IW_EV_PARAM_LEN);
 	}
 	/* Check if we added any event */
 	if((current_val - start) > IW_EV_LCP_LEN)
@@ -1567,7 +1575,7 @@ static inline char *libertas_translate_s
 		memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = bss->wpa_ie_len;
-		start = iwe_stream_add_point(start, stop, &iwe, buf);
+		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 	}
 
 	memset(&iwe, 0, sizeof(iwe));
@@ -1576,7 +1584,7 @@ static inline char *libertas_translate_s
 		memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = bss->rsn_ie_len;
-		start = iwe_stream_add_point(start, stop, &iwe, buf);
+		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 	}
 
 	if (bss->mesh) {
@@ -1588,7 +1596,8 @@ static inline char *libertas_translate_s
 		              "mesh-type: olpc");
 		iwe.u.data.length = p - custom;
 		if (iwe.u.data.length)
-			start = iwe_stream_add_point(start, stop, &iwe, custom);
+			start = iwe_stream_add_point(info, start, stop,
+						     &iwe, custom);
 	}
 
 out:
@@ -1650,7 +1659,8 @@ int libertas_get_scan(struct net_device 
 		}
 
 		/* Translate to WE format this entry */
-		next_ev = libertas_translate_scan(priv, ev, stop, iter_bss);
+		next_ev = libertas_translate_scan(priv, info, ev, stop,
+						  iter_bss);
 		if (next_ev == NULL)
 			continue;
 		ev = next_ev;
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -3909,6 +3909,7 @@ static int orinoco_ioctl_setscan(struct 
  * format that the Wireless Tools will understand - Jean II
  * Return message length or -errno for fatal errors */
 static inline int orinoco_translate_scan(struct net_device *dev,
+					 struct iw_request_info *info,
 					 char *buffer,
 					 char *scan,
 					 int scan_len)
@@ -3979,7 +3980,8 @@ static inline int orinoco_translate_scan
 		iwe.cmd = SIOCGIWAP;
 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 		memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN);
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_ADDR_LEN);
 
 		/* Other entries will be displayed in the order we give them */
 
@@ -3989,7 +3991,8 @@ static inline int orinoco_translate_scan
 			iwe.u.data.length = 32;
 		iwe.cmd = SIOCGIWESSID;
 		iwe.u.data.flags = 1;
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, atom->a.essid);
 
 		/* Add mode */
 		iwe.cmd = SIOCGIWMODE;
@@ -3999,7 +4002,9 @@ static inline int orinoco_translate_scan
 				iwe.u.mode = IW_MODE_MASTER;
 			else
 				iwe.u.mode = IW_MODE_ADHOC;
-			current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
+			current_ev = iwe_stream_add_event(info, current_ev,
+							  end_buf, &iwe,
+							  IW_EV_UINT_LEN);
 		}
 
 		channel = atom->s.channel;
@@ -4008,8 +4013,9 @@ static inline int orinoco_translate_scan
 			iwe.cmd = SIOCGIWFREQ;
 			iwe.u.freq.m = channel_frequency[channel-1] * 100000;
 			iwe.u.freq.e = 1;
-			current_ev = iwe_stream_add_event(current_ev, end_buf,
-							  &iwe, IW_EV_FREQ_LEN);
+			current_ev = iwe_stream_add_event(info, current_ev,
+							  end_buf, &iwe,
+							  IW_EV_FREQ_LEN);
 		}
 
 		/* Add quality statistics */
@@ -4023,7 +4029,8 @@ static inline int orinoco_translate_scan
 			iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
 		else
 			iwe.u.qual.qual = 0;
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_QUAL_LEN);
 
 		/* Add encryption capability */
 		iwe.cmd = SIOCGIWENCODE;
@@ -4032,14 +4039,22 @@ static inline int orinoco_translate_scan
 		else
 			iwe.u.data.flags = IW_ENCODE_DISABLED;
 		iwe.u.data.length = 0;
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, atom->a.essid);
 
 		/* Bit rate is not available in Lucent/Agere firmwares */
 		if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
-			char *	current_val = current_ev + IW_EV_LCP_LEN;
+			char *current_val;
 			int	i;
 			int	step;
-
+#ifdef CONFIG_COMPAT
+			if (info->flags & IW_REQUEST_FLAG_COMPAT)
+				current_val = current_ev + IW_EV_COMPAT_LCP_LEN;
+			else
+				current_val = current_ev + IW_EV_LCP_LEN;
+#else
+			current_val = current_ev + IW_EV_LCP_LEN;
+#endif
 			if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
 				step = 2;
 			else
@@ -4055,9 +4070,9 @@ static inline int orinoco_translate_scan
 					break;
 				/* Bit rate given in 500 kb/s units (+ 0x80) */
 				iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000);
-				current_val = iwe_stream_add_value(current_ev, current_val,
-								   end_buf, &iwe,
-								   IW_EV_PARAM_LEN);
+				current_val = iwe_stream_add_value(
+					info, current_ev, current_val,
+					end_buf, &iwe, IW_EV_PARAM_LEN);
 			}
 			/* Check if we added any event */
 			if ((current_val - current_ev) > IW_EV_LCP_LEN)
@@ -4102,7 +4117,7 @@ static int orinoco_ioctl_getscan(struct 
 		/* We have some results to push back to user space */
 
 		/* Translate to WE format */
-		int ret = orinoco_translate_scan(dev, extra,
+		int ret = orinoco_translate_scan(dev, info, extra,
 						 priv->scan_result,
 						 priv->scan_len);
 
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -572,8 +572,9 @@ prism54_set_scan(struct net_device *dev,
  */
 
 static char *
-prism54_translate_bss(struct net_device *ndev, char *current_ev,
-		      char *end_buf, struct obj_bss *bss, char noise)
+prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info,
+		      char *current_ev, char *end_buf, struct obj_bss *bss,
+		      char noise)
 {
 	struct iw_event iwe;	/* Temporary buffer */
 	short cap;
@@ -585,8 +586,8 @@ prism54_translate_bss(struct net_device 
 	memcpy(iwe.u.ap_addr.sa_data, bss->address, 6);
 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 	iwe.cmd = SIOCGIWAP;
-	current_ev =
-	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_ADDR_LEN);
 
 	/* The following entries will be displayed in the same order we give them */
 
@@ -594,7 +595,7 @@ prism54_translate_bss(struct net_device 
 	iwe.u.data.length = bss->ssid.length;
 	iwe.u.data.flags = 1;
 	iwe.cmd = SIOCGIWESSID;
-	current_ev = iwe_stream_add_point(current_ev, end_buf,
+	current_ev = iwe_stream_add_point(info, current_ev, end_buf,
 					  &iwe, bss->ssid.octets);
 
 	/* Capabilities */
@@ -611,9 +612,8 @@ prism54_translate_bss(struct net_device 
 		iwe.u.mode = IW_MODE_ADHOC;
 	iwe.cmd = SIOCGIWMODE;
 	if (iwe.u.mode)
-		current_ev =
-		    iwe_stream_add_event(current_ev, end_buf, &iwe,
-					 IW_EV_UINT_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_UINT_LEN);
 
 	/* Encryption capability */
 	if (cap & CAP_CRYPT)
@@ -622,14 +622,15 @@ prism54_translate_bss(struct net_device 
 		iwe.u.data.flags = IW_ENCODE_DISABLED;
 	iwe.u.data.length = 0;
 	iwe.cmd = SIOCGIWENCODE;
-	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL);
+	current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+					  &iwe, NULL);
 
 	/* Add frequency. (short) bss->channel is the frequency in MHz */
 	iwe.u.freq.m = bss->channel;
 	iwe.u.freq.e = 6;
 	iwe.cmd = SIOCGIWFREQ;
-	current_ev =
-	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_FREQ_LEN);
 
 	/* Add quality statistics */
 	iwe.u.qual.level = bss->rssi;
@@ -637,24 +638,32 @@ prism54_translate_bss(struct net_device 
 	/* do a simple SNR for quality */
 	iwe.u.qual.qual = bss->rssi - noise;
 	iwe.cmd = IWEVQUAL;
-	current_ev =
-	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_QUAL_LEN);
 
 	/* Add WPA/RSN Information Element, if any */
 	wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie);
 	if (wpa_ie_len > 0) {
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN);
-		current_ev = iwe_stream_add_point(current_ev, end_buf,
-				&iwe, wpa_ie);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, wpa_ie);
 	}
 	/* Do the bitrates */
 	{
-		char *	current_val = current_ev + IW_EV_LCP_LEN;
+		char *current_val;
 		int i;
 		int mask;
 
 		iwe.cmd = SIOCGIWRATE;
+#ifdef CONFIG_COMPAT
+		if (info->flags & IW_REQUEST_FLAG_COMPAT)
+			current_val = current_ev + IW_EV_COMPAT_LCP_LEN;
+		else
+			current_val = current_ev + IW_EV_LCP_LEN;
+#else
+		current_val = current_ev + IW_EV_LCP_LEN;
+#endif
 		/* Those two flags are ignored... */
 		iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
 
@@ -663,9 +672,9 @@ prism54_translate_bss(struct net_device 
 		for(i = 0; i < sizeof(scan_rate_list); i++) {
 			if(bss->rates & mask) {
 				iwe.u.bitrate.value = (scan_rate_list[i] * 500000);
-				current_val = iwe_stream_add_value(current_ev, current_val,
-								   end_buf, &iwe,
-								   IW_EV_PARAM_LEN);
+				current_val = iwe_stream_add_value(
+					info, current_ev, current_val,
+					end_buf, &iwe, IW_EV_PARAM_LEN);
 			}
 			mask <<= 1;
 		}
@@ -711,7 +720,7 @@ prism54_get_scan(struct net_device *ndev
 
 	/* ok now, scan the list and translate its info */
 	for (i = 0; i < (int) bsslist->nr; i++) {
-		current_ev = prism54_translate_bss(ndev, current_ev,
+		current_ev = prism54_translate_bss(ndev, info, current_ev,
 						   extra + dwrq->length,
 						   &(bsslist->bsslist[i]),
 						   noise);
@@ -2705,6 +2714,7 @@ prism2_ioctl_scan_req(struct net_device 
                      struct prism2_hostapd_param *param)
 {
 	islpci_private *priv = netdev_priv(ndev);
+	struct iw_request_info info;
 	int i, rvalue;
 	struct obj_bsslist *bsslist;
 	u32 noise = 0;
@@ -2728,9 +2738,12 @@ prism2_ioctl_scan_req(struct net_device 
 	rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r);
 	bsslist = r.ptr;
 
+	info.cmd = PRISM54_HOSTAPD;
+	info.flags = 0;
+
 	/* ok now, scan the list and translate its info */
 	for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++)
-		current_ev = prism54_translate_bss(ndev, current_ev,
+		current_ev = prism54_translate_bss(ndev, current_ev, &info,
 						   extra + IW_SCAN_MAX_DATA,
 						   &(bsslist->bsslist[i]),
 						   noise);
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1624,25 +1624,25 @@ static int wl3501_get_scan(struct net_de
 		iwe.cmd			= SIOCGIWAP;
 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 		memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN);
-		current_ev = iwe_stream_add_event(current_ev,
+		current_ev = iwe_stream_add_event(info, current_ev,
 						  extra + IW_SCAN_MAX_DATA,
 						  &iwe, IW_EV_ADDR_LEN);
 		iwe.cmd		  = SIOCGIWESSID;
 		iwe.u.data.flags  = 1;
 		iwe.u.data.length = this->bss_set[i].ssid.el.len;
-		current_ev = iwe_stream_add_point(current_ev,
+		current_ev = iwe_stream_add_point(info, current_ev,
 						  extra + IW_SCAN_MAX_DATA,
 						  &iwe,
 						  this->bss_set[i].ssid.essid);
 		iwe.cmd	   = SIOCGIWMODE;
 		iwe.u.mode = this->bss_set[i].bss_type;
-		current_ev = iwe_stream_add_event(current_ev,
+		current_ev = iwe_stream_add_event(info, current_ev,
 						  extra + IW_SCAN_MAX_DATA,
 						  &iwe, IW_EV_UINT_LEN);
 		iwe.cmd = SIOCGIWFREQ;
 		iwe.u.freq.m = this->bss_set[i].ds_pset.chan;
 		iwe.u.freq.e = 0;
-		current_ev = iwe_stream_add_event(current_ev,
+		current_ev = iwe_stream_add_event(info, current_ev,
 						  extra + IW_SCAN_MAX_DATA,
 						  &iwe, IW_EV_FREQ_LEN);
 		iwe.cmd = SIOCGIWENCODE;
@@ -1651,7 +1651,7 @@ static int wl3501_get_scan(struct net_de
 		else
 			iwe.u.data.flags = IW_ENCODE_DISABLED;
 		iwe.u.data.length = 0;
-		current_ev = iwe_stream_add_point(current_ev,
+		current_ev = iwe_stream_add_point(info, current_ev,
 						  extra + IW_SCAN_MAX_DATA,
 						  &iwe, NULL);
 	}
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -1152,32 +1152,36 @@ static int zd1201_get_scan(struct net_de
 		iwe.cmd = SIOCGIWAP;
 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 		memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6);
-		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
+		cev = iwe_stream_add_event(info, cev, end_buf,
+					   &iwe, IW_EV_ADDR_LEN);
 
 		iwe.cmd = SIOCGIWESSID;
 		iwe.u.data.length = zd->rxdata[i+16];
 		iwe.u.data.flags = 1;
-		cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18);
+		cev = iwe_stream_add_point(info, cev, end_buf,
+					   &iwe, zd->rxdata+i+18);
 
 		iwe.cmd = SIOCGIWMODE;
 		if (zd->rxdata[i+14]&0x01)
 			iwe.u.mode = IW_MODE_MASTER;
 		else
 			iwe.u.mode = IW_MODE_ADHOC;
-		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
+		cev = iwe_stream_add_event(info, cev, end_buf,
+					   &iwe, IW_EV_UINT_LEN);
 		
 		iwe.cmd = SIOCGIWFREQ;
 		iwe.u.freq.m = zd->rxdata[i+0];
 		iwe.u.freq.e = 0;
-		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
+		cev = iwe_stream_add_event(info, cev, end_buf,
+					   &iwe, IW_EV_FREQ_LEN);
 		
 		iwe.cmd = SIOCGIWRATE;
 		iwe.u.bitrate.fixed = 0;
 		iwe.u.bitrate.disabled = 0;
 		for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) {
 			iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000;
-			cev=iwe_stream_add_event(cev, end_buf, &iwe,
-			    IW_EV_PARAM_LEN);
+			cev=iwe_stream_add_event(info, cev, end_buf,
+						 &iwe, IW_EV_PARAM_LEN);
 		}
 		
 		iwe.cmd = SIOCGIWENCODE;
@@ -1186,14 +1190,15 @@ static int zd1201_get_scan(struct net_de
 			iwe.u.data.flags = IW_ENCODE_ENABLED;
 		else
 			iwe.u.data.flags = IW_ENCODE_DISABLED;
-		cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
+		cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL);
 		
 		iwe.cmd = IWEVQUAL;
 		iwe.u.qual.qual = zd->rxdata[i+4];
 		iwe.u.qual.noise= zd->rxdata[i+2]/10-100;
 		iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100;
 		iwe.u.qual.updated = 7;
-		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
+		cev = iwe_stream_add_event(info, cev, end_buf,
+					   &iwe, IW_EV_QUAL_LEN);
 	}
 
 	if (!enabled_save)
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -1098,6 +1098,19 @@ struct iw_event
 #define IW_EV_POINT_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_point) - \
 			 IW_EV_POINT_OFF)
 
+#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+struct __compat_iw_event {
+	__u16		len;			/* Real length of this stuff */
+	__u16		cmd;			/* Wireless IOCTL */
+	compat_caddr_t	pointer;
+};
+#define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer)
+#define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length)
+#define IW_EV_COMPAT_POINT_LEN	\
+	(IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \
+	 IW_EV_COMPAT_POINT_OFF)
+#endif
+
 /* Size of the Event prefix when packed in stream */
 #define IW_EV_LCP_PK_LEN	(4)
 /* Size of the various events when packed in stream */
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -483,19 +483,26 @@ extern void wireless_spy_update(struct n
  * 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 */
+iwe_stream_add_event(struct iw_request_info *info, char *stream, char *ends,
+		     struct iw_event *iwe, int event_len)
 {
+	int lcp_len = IW_EV_LCP_LEN;
+	int org_event_len = event_len;
+
+#ifdef CONFIG_COMPAT
+	if (info->flags & IW_REQUEST_FLAG_COMPAT) {
+		event_len -= IW_EV_LCP_LEN;
+		event_len += IW_EV_COMPAT_LCP_LEN;
+		lcp_len = IW_EV_COMPAT_LCP_LEN;
+	}
+#endif
 	/* Check if it's possible */
 	if(likely((stream + event_len) < ends)) {
 		iwe->len = event_len;
 		/* Beware of alignement issues on 64 bits */
 		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
-		memcpy(stream + IW_EV_LCP_LEN,
-		       ((char *) iwe) + IW_EV_LCP_LEN,
-		       event_len - IW_EV_LCP_LEN);
+		memcpy(stream + lcp_len, &iwe->u,
+		       org_event_len - IW_EV_LCP_LEN);
 		stream += event_len;
 	}
 	return stream;
@@ -507,104 +514,31 @@ iwe_stream_add_event(char *	stream,		/* 
  * 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 length + flags */
-		     char *	extra)		/* More payload */
-{
-	int	event_len = IW_EV_POINT_LEN + iwe->u.data.length;
-	/* Check if it's possible */
-	if(likely((stream + event_len) < ends)) {
-		iwe->len = event_len;
-		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
-		memcpy(stream + IW_EV_LCP_LEN,
-		       ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
-		       IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_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 */
+iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends,
+		     struct iw_event *iwe, char *extra)
 {
-	/* Don't duplicate LCP */
-	event_len -= IW_EV_LCP_LEN;
-
-	/* Check if it's possible */
-	if(likely((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);
+	int event_len = IW_EV_POINT_LEN + iwe->u.data.length;
+	int point_len = IW_EV_POINT_LEN;
+	int lcp_len = IW_EV_LCP_LEN;
+
+#ifdef CONFIG_COMPAT
+	if (info->flags & IW_REQUEST_FLAG_COMPAT) {
+		event_len = IW_EV_COMPAT_POINT_LEN + iwe->u.data.length;
+		point_len = IW_EV_COMPAT_POINT_LEN;
+		lcp_len = IW_EV_COMPAT_LCP_LEN;
 	}
-	return value;
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Wrapper to add an Wireless Event to a stream of events.
- * Same as above, with explicit error check...
- */
-static inline char *
-iwe_stream_check_add_event(char *	stream,		/* Stream of events */
-			   char *	ends,		/* End of stream */
-			   struct iw_event *iwe,	/* Payload */
-			   int		event_len,	/* Size of payload */
-			   int *	perr)		/* Error report */
-{
-	/* Check if it's possible, set error if not */
-	if(likely((stream + event_len) < ends)) {
-		iwe->len = event_len;
-		/* Beware of alignement issues on 64 bits */
-		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
-		memcpy(stream + IW_EV_LCP_LEN,
-		       ((char *) iwe) + IW_EV_LCP_LEN,
-		       event_len - IW_EV_LCP_LEN);
-		stream += event_len;
-	} else
-		*perr = -E2BIG;
-	return stream;
-}
+#endif
 
-/*------------------------------------------------------------------*/
-/*
- * Wrapper to add an short Wireless Event containing a pointer to a
- * stream of events.
- * Same as above, with explicit error check...
- */
-static inline char *
-iwe_stream_check_add_point(char *	stream,		/* Stream of events */
-			   char *	ends,		/* End of stream */
-			   struct iw_event *iwe,	/* Payload length + flags */
-			   char *	extra,		/* More payload */
-			   int *	perr)		/* Error report */
-{
-	int	event_len = IW_EV_POINT_LEN + iwe->u.data.length;
 	/* Check if it's possible */
 	if(likely((stream + event_len) < ends)) {
 		iwe->len = event_len;
 		memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN);
-		memcpy(stream + IW_EV_LCP_LEN,
-		       ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
+		memcpy(stream + lcp_len,
+		       &iwe->u.data.length,
 		       IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
-		memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
+		memcpy(stream + point_len, extra, iwe->u.data.length);
 		stream += event_len;
-	} else
-		*perr = -E2BIG;
+	}
 	return stream;
 }
 
@@ -612,30 +546,38 @@ iwe_stream_check_add_point(char *	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).
- * Same as above, with explicit error check...
- */
-static inline char *
-iwe_stream_check_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,	/* Size of payload */
-			   int *	perr)		/* Error report */
-{
+ * At the first run, you need to have the code like:
+ * #ifdef CONFIG_COMPAT
+ * if (info->flags & IW_REQUEST_FLAG_COMPAT)
+ * 	value = ev + IW_EV_COMPAT_LCP_LEN;
+ * else
+ * 	value = ev + IW_EV_COMPAT_LEN;
+ * #else
+ * value = ev + IW_EV_COMPAT_LEN;
+ * #endif
+ */
+static inline char *
+iwe_stream_add_value(struct iw_request_info *info, char *event, char *value,
+		     char *ends, struct iw_event *iwe, int event_len)
+{
+	int lcp_len = IW_EV_LCP_LEN;
+
+#ifdef CONFIG_COMPAT
+	if (info->flags & IW_REQUEST_FLAG_COMPAT)
+		lcp_len = IW_EV_COMPAT_LCP_LEN;
+#endif
 	/* Don't duplicate LCP */
 	event_len -= IW_EV_LCP_LEN;
 
 	/* Check if it's possible */
 	if(likely((value + event_len) < ends)) {
 		/* Add new value */
-		memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
+		memcpy(value, &iwe->u, event_len);
 		value += event_len;
 		/* Patch LCP */
 		iwe->len = value - event;
-		memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
-	} else
-		*perr = -E2BIG;
+		memcpy(event, (char *) iwe, lcp_len);
+	}
 	return value;
 }
 
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -43,8 +43,9 @@ static const char *ieee80211_modes[] = {
 
 #define MAX_CUSTOM_LEN 64
 static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
-					   char *start, char *stop,
-					   struct ieee80211_network *network)
+				      char *start, char *stop,
+				      struct ieee80211_network *network,
+				      struct iw_request_info *info)
 {
 	char custom[MAX_CUSTOM_LEN];
 	char *p;
@@ -57,7 +58,7 @@ static char *ieee80211_translate_scan(st
 	iwe.cmd = SIOCGIWAP;
 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 	memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
+	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
 
 	/* Remaining entries will be displayed in the order we provide them */
 
@@ -66,17 +67,19 @@ static char *ieee80211_translate_scan(st
 	iwe.u.data.flags = 1;
 	if (network->flags & NETWORK_EMPTY_ESSID) {
 		iwe.u.data.length = sizeof("<hidden>");
-		start = iwe_stream_add_point(start, stop, &iwe, "<hidden>");
+		start = iwe_stream_add_point(info, start, stop,
+					     &iwe, "<hidden>");
 	} else {
 		iwe.u.data.length = min(network->ssid_len, (u8) 32);
-		start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
+		start = iwe_stream_add_point(info, start, stop,
+					     &iwe, network->ssid);
 	}
 
 	/* Add the protocol name */
 	iwe.cmd = SIOCGIWNAME;
 	snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
 		 ieee80211_modes[network->mode]);
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN);
+	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
 
 	/* Add mode */
 	iwe.cmd = SIOCGIWMODE;
@@ -86,7 +89,8 @@ static char *ieee80211_translate_scan(st
 		else
 			iwe.u.mode = IW_MODE_ADHOC;
 
-		start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
+		start = iwe_stream_add_event(info, start, stop,
+					     &iwe, IW_EV_UINT_LEN);
 	}
 
 	/* Add channel and frequency */
@@ -95,7 +99,7 @@ static char *ieee80211_translate_scan(st
 	iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
 	iwe.u.freq.e = 6;
 	iwe.u.freq.i = 0;
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
+	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
 
 	/* Add encryption capability */
 	iwe.cmd = SIOCGIWENCODE;
@@ -104,12 +108,20 @@ static char *ieee80211_translate_scan(st
 	else
 		iwe.u.data.flags = IW_ENCODE_DISABLED;
 	iwe.u.data.length = 0;
-	start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
+	start = iwe_stream_add_point(info, start, stop,
+				     &iwe, network->ssid);
 
 	/* Add basic and extended rates */
 	/* Rate : stuffing multiple values in a single event require a bit
 	 * more of magic - Jean II */
+#ifdef CONFIG_COMPAT
+	if (info->flags & IW_REQUEST_FLAG_COMPAT)
+		current_val = start + IW_EV_COMPAT_LCP_LEN;
+	else
+		current_val = start + IW_EV_LCP_LEN;
+#else
 	current_val = start + IW_EV_LCP_LEN;
+#endif
 	iwe.cmd = SIOCGIWRATE;
 	/* Those two flags are ignored... */
 	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
@@ -124,14 +136,16 @@ static char *ieee80211_translate_scan(st
 		/* Bit rate given in 500 kb/s units (+ 0x80) */
 		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
 		/* Add new value to event */
-		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
+		current_val = iwe_stream_add_value(info, start, current_val,
+						   stop, &iwe, IW_EV_PARAM_LEN);
 	}
 	for (; j < network->rates_ex_len; j++) {
 		rate = network->rates_ex[j] & 0x7F;
 		/* Bit rate given in 500 kb/s units (+ 0x80) */
 		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
 		/* Add new value to event */
-		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
+		current_val = iwe_stream_add_value(info, start, current_val,
+						   stop, &iwe, IW_EV_PARAM_LEN);
 	}
 	/* Check if we added any rate */
 	if((current_val - start) > IW_EV_LCP_LEN)
@@ -181,14 +195,14 @@ static char *ieee80211_translate_scan(st
 		iwe.u.qual.level = network->stats.signal;
 	}
 
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
+	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
 
 	iwe.cmd = IWEVCUSTOM;
 	p = custom;
 
 	iwe.u.data.length = p - custom;
 	if (iwe.u.data.length)
-		start = iwe_stream_add_point(start, stop, &iwe, custom);
+		start = iwe_stream_add_point(info, start, stop, &iwe, custom);
 
 	memset(&iwe, 0, sizeof(iwe));
 	if (network->wpa_ie_len) {
@@ -196,7 +210,7 @@ static char *ieee80211_translate_scan(st
 		memcpy(buf, network->wpa_ie, network->wpa_ie_len);
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = network->wpa_ie_len;
-		start = iwe_stream_add_point(start, stop, &iwe, buf);
+		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 	}
 
 	memset(&iwe, 0, sizeof(iwe));
@@ -205,7 +219,7 @@ static char *ieee80211_translate_scan(st
 		memcpy(buf, network->rsn_ie, network->rsn_ie_len);
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = network->rsn_ie_len;
-		start = iwe_stream_add_point(start, stop, &iwe, buf);
+		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
 	}
 
 	/* Add EXTRA: Age to display seconds since last beacon/probe response
@@ -217,7 +231,7 @@ static char *ieee80211_translate_scan(st
 		      jiffies_to_msecs(jiffies - network->last_scanned));
 	iwe.u.data.length = p - custom;
 	if (iwe.u.data.length)
-		start = iwe_stream_add_point(start, stop, &iwe, custom);
+		start = iwe_stream_add_point(info, start, stop, &iwe, custom);
 
 	/* Add spectrum management information */
 	iwe.cmd = -1;
@@ -238,7 +252,7 @@ static char *ieee80211_translate_scan(st
 
 	if (iwe.cmd == IWEVCUSTOM) {
 		iwe.u.data.length = p - custom;
-		start = iwe_stream_add_point(start, stop, &iwe, custom);
+		start = iwe_stream_add_point(info, start, stop, &iwe, custom);
 	}
 
 	return start;
@@ -272,7 +286,8 @@ int ieee80211_wx_get_scan(struct ieee802
 
 		if (ieee->scan_age == 0 ||
 		    time_after(network->last_scanned + ieee->scan_age, jiffies))
-			ev = ieee80211_translate_scan(ieee, ev, stop, network);
+			ev = ieee80211_translate_scan(ieee, ev, stop, network,
+						      info);
 		else
 			IEEE80211_DEBUG_SCAN("Not showing network '%s ("
 					     "%s)' due to age (%dms).\n",
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -23,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/etherdevice.h>
 #include <net/wireless.h>
+#include <net/iw_handler.h>
 #include "ieee80211_key.h"
 #include "sta_info.h"
 
@@ -748,7 +749,9 @@ int ieee80211_sta_set_bssid(struct net_d
 int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len);
 void ieee80211_sta_req_auth(struct net_device *dev,
 			    struct ieee80211_if_sta *ifsta);
-int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len);
+int ieee80211_sta_scan_results(struct net_device *dev,
+			       struct iw_request_info *info,
+			       char *buf, size_t len);
 void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
 			   struct ieee80211_rx_status *rx_status);
 void ieee80211_rx_bss_list_init(struct net_device *dev);
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -560,7 +560,7 @@ static int ieee80211_ioctl_giwscan(struc
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	if (local->sta_scanning)
 		return -EAGAIN;
-	res = ieee80211_sta_scan_results(dev, extra, data->length);
+	res = ieee80211_sta_scan_results(dev, info, extra, data->length);
 	if (res >= 0) {
 		data->length = res;
 		return 0;
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -2881,6 +2881,7 @@ int ieee80211_sta_req_scan(struct net_de
 
 static char *
 ieee80211_sta_scan_result(struct net_device *dev,
+			  struct iw_request_info *info,
 			  struct ieee80211_sta_bss *bss,
 			  char *current_ev, char *end_buf)
 {
@@ -2907,15 +2908,15 @@ ieee80211_sta_scan_result(struct net_dev
 	iwe.cmd = SIOCGIWAP;
 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 	memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-					  IW_EV_ADDR_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_ADDR_LEN);
 
 	memset(&iwe, 0, sizeof(iwe));
 	iwe.cmd = SIOCGIWESSID;
 	iwe.u.data.length = bss->ssid_len;
 	iwe.u.data.flags = 1;
-	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-					  bss->ssid);
+	current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+					  &iwe, bss->ssid);
 
 	if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
 		memset(&iwe, 0, sizeof(iwe));
@@ -2924,20 +2925,20 @@ ieee80211_sta_scan_result(struct net_dev
 			iwe.u.mode = IW_MODE_MASTER;
 		else
 			iwe.u.mode = IW_MODE_ADHOC;
-		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-						  IW_EV_UINT_LEN);
+		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+						  &iwe, IW_EV_UINT_LEN);
 	}
 
 	memset(&iwe, 0, sizeof(iwe));
 	iwe.cmd = SIOCGIWFREQ;
 	iwe.u.freq.m = bss->channel;
 	iwe.u.freq.e = 0;
-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-					  IW_EV_FREQ_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_FREQ_LEN);
 	iwe.u.freq.m = bss->freq * 100000;
 	iwe.u.freq.e = 1;
-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-					  IW_EV_FREQ_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_FREQ_LEN);
 
 	memset(&iwe, 0, sizeof(iwe));
 	iwe.cmd = IWEVQUAL;
@@ -2945,8 +2946,8 @@ ieee80211_sta_scan_result(struct net_dev
 	iwe.u.qual.level = bss->rssi;
 	iwe.u.qual.noise = bss->noise;
 	iwe.u.qual.updated = local->wstats_flags;
-	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-					  IW_EV_QUAL_LEN);
+	current_ev = iwe_stream_add_event(info, current_ev, end_buf,
+					  &iwe, IW_EV_QUAL_LEN);
 
 	memset(&iwe, 0, sizeof(iwe));
 	iwe.cmd = SIOCGIWENCODE;
@@ -2955,22 +2956,22 @@ ieee80211_sta_scan_result(struct net_dev
 	else
 		iwe.u.data.flags = IW_ENCODE_DISABLED;
 	iwe.u.data.length = 0;
-	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
+	current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, "");
 
 	if (bss && bss->wpa_ie) {
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = bss->wpa_ie_len;
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-						  bss->wpa_ie);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, bss->wpa_ie);
 	}
 
 	if (bss && bss->rsn_ie) {
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = IWEVGENIE;
 		iwe.u.data.length = bss->rsn_ie_len;
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-						  bss->rsn_ie);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, bss->rsn_ie);
 	}
 
 	if (bss && bss->supp_rates_len > 0) {
@@ -2986,8 +2987,8 @@ ieee80211_sta_scan_result(struct net_dev
 		for (i = 0; i < bss->supp_rates_len; i++) {
 			iwe.u.bitrate.value = ((bss->supp_rates[i] &
 							0x7f) * 500000);
-			p = iwe_stream_add_value(current_ev, p,
-					end_buf, &iwe, IW_EV_PARAM_LEN);
+			p = iwe_stream_add_value(info, current_ev, p, end_buf,
+						 &iwe, IW_EV_PARAM_LEN);
 		}
 		current_ev = p;
 	}
@@ -3000,8 +3001,8 @@ ieee80211_sta_scan_result(struct net_dev
 			iwe.cmd = IWEVCUSTOM;
 			sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp));
 			iwe.u.data.length = strlen(buf);
-			current_ev = iwe_stream_add_point(current_ev, end_buf,
-							  &iwe, buf);
+			current_ev = iwe_stream_add_point(info, current_ev,
+							  end_buf, &iwe, buf);
 			kfree(buf);
 		}
 	}
@@ -3020,15 +3021,15 @@ ieee80211_sta_scan_result(struct net_dev
 		iwe.cmd = IWEVCUSTOM;
 		sprintf(buf, "bcn_int=%d", bss->beacon_int);
 		iwe.u.data.length = strlen(buf);
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-						  buf);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, buf);
 
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = IWEVCUSTOM;
 		sprintf(buf, "capab=0x%04x", bss->capability);
 		iwe.u.data.length = strlen(buf);
-		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-						  buf);
+		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
+						  &iwe, buf);
 
 		kfree(buf);
 		break;
@@ -3038,7 +3039,9 @@ ieee80211_sta_scan_result(struct net_dev
 }
 
 
-int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
+int ieee80211_sta_scan_results(struct net_device *dev,
+			       struct iw_request_info *info,
+			       char *buf, size_t len)
 {
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	char *current_ev = buf;
@@ -3051,8 +3054,8 @@ int ieee80211_sta_scan_results(struct ne
 			spin_unlock_bh(&local->sta_bss_lock);
 			return -E2BIG;
 		}
-		current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
-						       end_buf);
+		current_ev = ieee80211_sta_scan_result(dev, info, bss,
+						       current_ev, end_buf);
 	}
 	spin_unlock_bh(&local->sta_bss_lock);
 	return current_ev - buf;

  parent reply	other threads:[~2008-01-11  4:16 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-22  4:58 [WEXT 12/12]: Emit event stream compat iw_point objects correctly David Miller
     [not found] ` <20071221.205808.213484078.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
2007-12-27  8:51   ` : " Masakazu Mokuno
2007-12-27  8:57     ` David Miller
     [not found]       ` <20071227.005725.144782426.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
2007-12-27  9:24         ` Masakazu Mokuno
     [not found]           ` <20071227181439.6F59.40F06B3A-DfbDroY8Xu1L9jVzuh4AOg@public.gmane.org>
2007-12-27  9:26             ` David Miller
2008-01-10  9:16           ` David Miller
     [not found]             ` <20080110.011602.74511551.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
2008-01-11  4:16               ` Masakazu Mokuno [this message]
2008-06-03 16:57                 ` David Miller
     [not found]                   ` <20080603.095750.120470495.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
2008-06-03 17:37                     ` David Miller
2008-01-21 11:23               ` Masakazu Mokuno
     [not found]                 ` <20080121194942.613C.40F06B3A-DfbDroY8Xu1L9jVzuh4AOg@public.gmane.org>
2008-01-21 11:37                   ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080111112248.610C.40F06B3A@sm.sony.co.jp \
    --to=mokuno-dfbdroy8xu1l9jvzuh4aog@public.gmane.org \
    --cc=davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org \
    --cc=linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox