summaryrefslogtreecommitdiff
path: root/packages/linux/files
diff options
context:
space:
mode:
authorMichael Lauer <mickey@vanille-media.de>2006-01-22 22:25:42 +0000
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>2006-01-22 22:25:42 +0000
commit9315156b42184f415934d6db0d9ac6dc3f23d139 (patch)
tree7690b088f28c46ad0934e999afe349f2ac4587cd /packages/linux/files
parent7349a5c048a4247a9b2c1bcccb0522472047a640 (diff)
openzaurus-sa: upgrade wireless extension API to V18
Diffstat (limited to 'packages/linux/files')
-rw-r--r--packages/linux/files/iw240_we18-5.diff421
-rw-r--r--packages/linux/files/iw249_we16-6.diff670
2 files changed, 1091 insertions, 0 deletions
diff --git a/packages/linux/files/iw240_we18-5.diff b/packages/linux/files/iw240_we18-5.diff
new file mode 100644
index 0000000000..f65987588d
--- /dev/null
+++ b/packages/linux/files/iw240_we18-5.diff
@@ -0,0 +1,421 @@
+diff -u -p linux/include/linux/wireless.we17.h linux/include/linux/wireless.h
+--- linux/include/linux/wireless.we17.h 2005-05-20 11:25:49.000000000 -0700
++++ linux/include/linux/wireless.h 2005-05-20 11:29:05.000000000 -0700
+@@ -1,10 +1,10 @@
+ /*
+ * This file define a set of standard wireless extensions
+ *
+- * Version : 17 21.6.04
++ * Version : 18 12.3.05
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+- * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
+ */
+
+ #ifndef _LINUX_WIRELESS_H
+@@ -82,7 +82,7 @@
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+-#define WIRELESS_EXT 17
++#define WIRELESS_EXT 18
+
+ /*
+ * Changes :
+@@ -182,6 +182,21 @@
+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
+ * - Wireless Event capability in struct iw_range
+ * - Add support for relative TxPower (yick !)
++ *
++ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
++ * ----------
++ * - Add support for WPA/WPA2
++ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
++ * SIOCGIWENCODEEXT)
++ * - Add SIOCSIWGENIE/SIOCGIWGENIE
++ * - Add SIOCSIWMLME
++ * - Add SIOCSIWPMKSA
++ * - Add struct iw_range bit field for supported encoding capabilities
++ * - Add optional scan request parameters for SIOCSIWSCAN
++ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
++ * related parameters (extensible up to 4096 parameter values)
++ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
++ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
+ */
+
+ /**************************** CONSTANTS ****************************/
+@@ -256,6 +271,30 @@
+ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
+ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
+
++/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
++ * This ioctl uses struct iw_point and data buffer that includes IE id and len
++ * fields. More than one IE may be included in the request. Setting the generic
++ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
++ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
++ * are required to report the used IE as a wireless event, e.g., when
++ * associating with an AP. */
++#define SIOCSIWGENIE 0x8B30 /* set generic IE */
++#define SIOCGIWGENIE 0x8B31 /* get generic IE */
++
++/* WPA : IEEE 802.11 MLME requests */
++#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
++ * struct iw_mlme */
++/* WPA : Authentication mode parameters */
++#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
++#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
++
++/* WPA : Extended version of encoding configuration */
++#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
++#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
++
++/* WPA2 : PMKSA cache management */
++#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
++
+ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+ /* These 32 ioctl are wireless device private, for 16 commands.
+@@ -297,6 +336,34 @@
+ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
+ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
+ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
++#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
++ * (scan results); This includes id and
++ * length fields. One IWEVGENIE may
++ * contain more than one IE. Scan
++ * results may contain one or more
++ * IWEVGENIE events. */
++#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
++ * (struct iw_michaelmicfailure)
++ */
++#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
++ * The data includes id and length
++ * fields and may contain more than one
++ * IE. This event is required in
++ * Managed mode if the driver
++ * generates its own WPA/RSN IE. This
++ * should be sent just before
++ * IWEVREGISTERED event for the
++ * association. */
++#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
++ * Response. The data includes id and
++ * length fields and may contain more
++ * than one IE. This may be sent
++ * between IWEVASSOCREQIE and
++ * IWEVREGISTERED events for the
++ * association. */
++#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
++ * pre-authentication
++ * (struct iw_pmkid_cand) */
+
+ #define IWEVFIRST 0x8C00
+
+@@ -432,12 +499,94 @@
+ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
+ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
+ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
++/* struct iw_scan_req scan_type */
++#define IW_SCAN_TYPE_ACTIVE 0
++#define IW_SCAN_TYPE_PASSIVE 1
+ /* Maximum size of returned data */
+ #define IW_SCAN_MAX_DATA 4096 /* In bytes */
+
+ /* Max number of char in custom event - use multiple of them if needed */
+ #define IW_CUSTOM_MAX 256 /* In bytes */
+
++/* Generic information element */
++#define IW_GENERIC_IE_MAX 1024
++
++/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
++#define IW_MLME_DEAUTH 0
++#define IW_MLME_DISASSOC 1
++
++/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
++#define IW_AUTH_INDEX 0x0FFF
++#define IW_AUTH_FLAGS 0xF000
++/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
++ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
++ * parameter that is being set/get to; value will be read/written to
++ * struct iw_param value field) */
++#define IW_AUTH_WPA_VERSION 0
++#define IW_AUTH_CIPHER_PAIRWISE 1
++#define IW_AUTH_CIPHER_GROUP 2
++#define IW_AUTH_KEY_MGMT 3
++#define IW_AUTH_TKIP_COUNTERMEASURES 4
++#define IW_AUTH_DROP_UNENCRYPTED 5
++#define IW_AUTH_80211_AUTH_ALG 6
++#define IW_AUTH_WPA_ENABLED 7
++#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
++#define IW_AUTH_ROAMING_CONTROL 9
++#define IW_AUTH_PRIVACY_INVOKED 10
++
++/* IW_AUTH_WPA_VERSION values (bit field) */
++#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
++#define IW_AUTH_WPA_VERSION_WPA 0x00000002
++#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
++
++/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
++#define IW_AUTH_CIPHER_NONE 0x00000001
++#define IW_AUTH_CIPHER_WEP40 0x00000002
++#define IW_AUTH_CIPHER_TKIP 0x00000004
++#define IW_AUTH_CIPHER_CCMP 0x00000008
++#define IW_AUTH_CIPHER_WEP104 0x00000010
++
++/* IW_AUTH_KEY_MGMT values (bit field) */
++#define IW_AUTH_KEY_MGMT_802_1X 1
++#define IW_AUTH_KEY_MGMT_PSK 2
++
++/* IW_AUTH_80211_AUTH_ALG values (bit field) */
++#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
++#define IW_AUTH_ALG_SHARED_KEY 0x00000002
++#define IW_AUTH_ALG_LEAP 0x00000004
++
++/* IW_AUTH_ROAMING_CONTROL values */
++#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
++#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
++ * control */
++
++/* SIOCSIWENCODEEXT definitions */
++#define IW_ENCODE_SEQ_MAX_SIZE 8
++/* struct iw_encode_ext ->alg */
++#define IW_ENCODE_ALG_NONE 0
++#define IW_ENCODE_ALG_WEP 1
++#define IW_ENCODE_ALG_TKIP 2
++#define IW_ENCODE_ALG_CCMP 3
++/* struct iw_encode_ext ->ext_flags */
++#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
++#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
++#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
++#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
++
++/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
++#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
++#define IW_MICFAILURE_GROUP 0x00000004
++#define IW_MICFAILURE_PAIRWISE 0x00000008
++#define IW_MICFAILURE_STAKEY 0x00000010
++#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
++ */
++
++/* Bit field values for enc_capa in struct iw_range */
++#define IW_ENC_CAPA_WPA 0x00000001
++#define IW_ENC_CAPA_WPA2 0x00000002
++#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
++#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
++
+ /* Event capability macros - in (struct iw_range *)->event_capa
+ * Because we have more than 32 possible events, we use an array of
+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
+@@ -546,6 +695,132 @@ struct iw_thrspy
+ struct iw_quality high; /* High threshold */
+ };
+
++/*
++ * Optional data for scan request
++ *
++ * Note: these optional parameters are controlling parameters for the
++ * scanning behavior, these do not apply to getting scan results
++ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
++ * provide a merged results with all BSSes even if the previous scan
++ * request limited scanning to a subset, e.g., by specifying an SSID.
++ * Especially, scan results are required to include an entry for the
++ * current BSS if the driver is in Managed mode and associated with an AP.
++ */
++struct iw_scan_req
++{
++ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
++ __u8 essid_len;
++ __u8 num_channels; /* num entries in channel_list;
++ * 0 = scan all allowed channels */
++ __u8 flags; /* reserved as padding; use zero, this may
++ * be used in the future for adding flags
++ * to request different scan behavior */
++ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
++ * individual address of a specific BSS */
++
++ /*
++ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
++ * the current ESSID. This allows scan requests for specific ESSID
++ * without having to change the current ESSID and potentially breaking
++ * the current association.
++ */
++ __u8 essid[IW_ESSID_MAX_SIZE];
++
++ /*
++ * Optional parameters for changing the default scanning behavior.
++ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
++ * TU is 1.024 ms. If these are set to 0, driver is expected to use
++ * reasonable default values. min_channel_time defines the time that
++ * will be used to wait for the first reply on each channel. If no
++ * replies are received, next channel will be scanned after this. If
++ * replies are received, total time waited on the channel is defined by
++ * max_channel_time.
++ */
++ __u32 min_channel_time; /* in TU */
++ __u32 max_channel_time; /* in TU */
++
++ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
++};
++
++/* ------------------------- WPA SUPPORT ------------------------- */
++
++/*
++ * Extended data structure for get/set encoding (this is used with
++ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
++ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
++ * only the data contents changes (key data -> this structure, including
++ * key data).
++ *
++ * If the new key is the first group key, it will be set as the default
++ * TX key. Otherwise, default TX key index is only changed if
++ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
++ *
++ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
++ * special "change TX key index" operation which is indicated by setting
++ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
++ *
++ * tx_seq/rx_seq are only used when respective
++ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
++ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
++ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
++ * used only by an Authenticator (AP or an IBSS station) to get the
++ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
++ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
++ * debugging/testing.
++ */
++struct iw_encode_ext
++{
++ __u32 ext_flags; /* IW_ENCODE_EXT_* */
++ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
++ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
++ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
++ * (group) keys or unicast address for
++ * individual keys */
++ __u16 alg; /* IW_ENCODE_ALG_* */
++ __u16 key_len;
++ __u8 key[0];
++};
++
++/* SIOCSIWMLME data */
++struct iw_mlme
++{
++ __u16 cmd; /* IW_MLME_* */
++ __u16 reason_code;
++ struct sockaddr addr;
++};
++
++/* SIOCSIWPMKSA data */
++#define IW_PMKSA_ADD 1
++#define IW_PMKSA_REMOVE 2
++#define IW_PMKSA_FLUSH 3
++
++#define IW_PMKID_LEN 16
++
++struct iw_pmksa
++{
++ __u32 cmd; /* IW_PMKSA_* */
++ struct sockaddr bssid;
++ __u8 pmkid[IW_PMKID_LEN];
++};
++
++/* IWEVMICHAELMICFAILURE data */
++struct iw_michaelmicfailure
++{
++ __u32 flags;
++ struct sockaddr src_addr;
++ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
++};
++
++/* IWEVPMKIDCAND data */
++#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
++struct iw_pmkid_cand
++{
++ __u32 flags; /* IW_PMKID_CAND_* */
++ __u32 index; /* the smaller the index, the higher the
++ * priority */
++ struct sockaddr bssid;
++};
++
+ /* ------------------------ WIRELESS STATS ------------------------ */
+ /*
+ * Wireless statistics (used for /proc/net/wireless)
+@@ -725,6 +1000,8 @@ struct iw_range
+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
+ /* Note : this frequency list doesn't need to fit channel numbers,
+ * because each entry contain its channel index */
++
++ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
+ };
+
+ /*
+diff -u -p linux/net/core/wireless.we17.c linux/net/core/wireless.c
+--- linux/net/core/wireless.we17.c 2005-05-20 11:26:11.000000000 -0700
++++ linux/net/core/wireless.c 2005-05-20 15:37:09.000000000 -0700
+@@ -2,7 +2,7 @@
+ * This file implement the Wireless Extensions APIs.
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+- * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
+ *
+ * (As all part of the Linux kernel, this file is GPL)
+ */
+@@ -137,12 +137,12 @@ static const struct iw_ioctl_description
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
+ /* SIOCGIWAP */
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
+- /* -- hole -- */
+- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
++ /* SIOCSIWMLME */
++ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_mlme), sizeof(struct iw_mlme), 0},
+ /* SIOCGIWAPLIST */
+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, IW_DESCR_FLAG_NOMAX},
+ /* SIOCSIWSCAN */
+- { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_scan_req), 0},
+ /* SIOCGIWSCAN */
+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, IW_DESCR_FLAG_NOMAX},
+ /* SIOCSIWESSID */
+@@ -185,6 +185,25 @@ static const struct iw_ioctl_description
+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
+ /* SIOCGIWPOWER */
+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
++ /* -- hole -- */
++ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
++ /* -- hole -- */
++ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
++ /* SIOCSIWGENIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* SIOCGIWGENIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* SIOCSIWAUTH */
++ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
++ /* SIOCGIWAUTH */
++ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
++ /* SIOCSIWENCODEEXT */
++ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0},
++ /* SIOCGIWENCODEEXT */
++ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0},
++ /* SIOCSIWPMKSA */
++ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_pmksa), sizeof(struct iw_pmksa), 0},
++ /* -- hole -- */
+ };
+ static const int standard_ioctl_num = (sizeof(standard_ioctl) /
+ sizeof(struct iw_ioctl_description));
+@@ -204,6 +223,16 @@ static const struct iw_ioctl_description
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
+ /* IWEVEXPIRED */
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
++ /* IWEVGENIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* IWEVMICHAELMICFAILURE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_michaelmicfailure), 0},
++ /* IWEVASSOCREQIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* IWEVASSOCRESPIE */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
++ /* IWEVPMKIDCAND */
++ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_pmkid_cand), 0},
+ };
+ static const int standard_event_num = (sizeof(standard_event) /
+ sizeof(struct iw_ioctl_description));
diff --git a/packages/linux/files/iw249_we16-6.diff b/packages/linux/files/iw249_we16-6.diff
new file mode 100644
index 0000000000..0a5aaab954
--- /dev/null
+++ b/packages/linux/files/iw249_we16-6.diff
@@ -0,0 +1,670 @@
+diff -u -p linux/include/linux/wireless.15.h linux/include/linux/wireless.h
+--- linux/include/linux/wireless.15.h 2004-11-05 14:59:33.000000000 -0800
++++ linux/include/linux/wireless.h 2004-11-05 15:00:42.000000000 -0800
+@@ -1,7 +1,7 @@
+ /*
+ * This file define a set of standard wireless extensions
+ *
+- * Version : 15 12.7.02
++ * Version : 16 2.4.03
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
+@@ -69,6 +69,8 @@
+
+ /***************************** INCLUDES *****************************/
+
++/* To minimise problems in user space, I might remove those headers
++ * at some point. Jean II */
+ #include <linux/types.h> /* for "caddr_t" et al */
+ #include <linux/socket.h> /* for "struct sockaddr" et al */
+ #include <linux/if.h> /* for IFNAMSIZ and co... */
+@@ -80,7 +82,7 @@
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+-#define WIRELESS_EXT 15
++#define WIRELESS_EXT 16
+
+ /*
+ * Changes :
+@@ -163,6 +165,16 @@
+ * - Add IW_TXPOW_RANGE for range of Tx Powers
+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+ * - Add IW_MODE_MONITOR for passive monitor
++ *
++ * V15 to V16
++ * ----------
++ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
++ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
++ * - Reshuffle struct iw_range for increases, add filler
++ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
++ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
++ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
++ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+ */
+
+ /**************************** CONSTANTS ****************************/
+@@ -196,9 +208,11 @@
+ /* SIOCGIWSTATS is strictly used between user space and the kernel, and
+ * is never passed to the driver (i.e. the driver will never see it). */
+
+-/* Mobile IP support (statistics per MAC address) */
++/* Spy support (statistics per MAC address - used for Mobile IP support) */
+ #define SIOCSIWSPY 0x8B10 /* set spy addresses */
+ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
++#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
++#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */
+
+ /* Access Point manipulation */
+ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
+@@ -294,7 +308,7 @@
+ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
+ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
+
+-#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */
++#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */
+
+ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
+
+@@ -306,13 +320,13 @@
+ /* ----------------------- OTHER CONSTANTS ----------------------- */
+
+ /* Maximum frequencies in the range struct */
+-#define IW_MAX_FREQUENCIES 16
++#define IW_MAX_FREQUENCIES 32
+ /* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+ /* Maximum bit rates in the range struct */
+-#define IW_MAX_BITRATES 8
++#define IW_MAX_BITRATES 32
+
+ /* Maximum tx powers in the range struct */
+ #define IW_MAX_TXPOWER 8
+@@ -320,8 +334,7 @@
+ * a few of them in the struct iw_range. */
+
+ /* Maximum of address that you may set with SPY */
+-#define IW_MAX_SPY 8 /* set */
+-#define IW_MAX_GET_SPY 64 /* get */
++#define IW_MAX_SPY 8
+
+ /* Maximum of address that you may get in the
+ list of access points in range */
+@@ -354,7 +367,8 @@
+ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
+ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
+ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
+-#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
++#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
++#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
+
+ /* Power management flags available (along with the value, if any) */
+ #define IW_POWER_ON 0x0000 /* No details... */
+@@ -482,6 +496,17 @@ struct iw_missed
+ __u32 beacon; /* Missed beacons/superframe */
+ };
+
++/*
++ * Quality range (for spy threshold)
++ */
++struct iw_thrspy
++{
++ struct sockaddr addr; /* Source address (hw/mac) */
++ struct iw_quality qual; /* Quality of the link */
++ struct iw_quality low; /* Low threshold */
++ struct iw_quality high; /* High threshold */
++};
++
+ /* ------------------------ WIRELESS STATS ------------------------ */
+ /*
+ * Wireless statistics (used for /proc/net/wireless)
+@@ -534,7 +559,7 @@ union iwreq_data
+ struct iw_quality qual; /* Quality part of statistics */
+
+ struct sockaddr ap_addr; /* Access point address */
+- struct sockaddr addr; /* Destination address (hw) */
++ struct sockaddr addr; /* Destination address (hw/mac) */
+
+ struct iw_param param; /* Other small parameters */
+ struct iw_point data; /* Other large parameters */
+@@ -582,17 +607,31 @@ struct iw_range
+ __u32 min_nwid; /* Minimal NWID we are able to set */
+ __u32 max_nwid; /* Maximal NWID we are able to set */
+
+- /* Frequency */
+- __u16 num_channels; /* Number of channels [0; num - 1] */
+- __u8 num_frequency; /* Number of entry in the list */
+- struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
+- /* Note : this frequency list doesn't need to fit channel numbers */
++ /* Old Frequency (backward compat - moved lower ) */
++ __u16 old_num_channels;
++ __u8 old_num_frequency;
++ /* Filler to keep "version" at the same offset */
++ __s32 old_freq[6];
+
+ /* signal level threshold range */
+ __s32 sensitivity;
+
+ /* Quality of link & SNR stuff */
++ /* Quality range (link, level, noise)
++ * If the quality is absolute, it will be in the range [0 ; max_qual],
++ * if the quality is dBm, it will be in the range [max_qual ; 0].
++ * Don't forget that we use 8 bit arithmetics... */
+ struct iw_quality max_qual; /* Quality of the link */
++ /* This should contain the average/typical values of the quality
++ * indicator. This should be the threshold between a "good" and
++ * a "bad" link (example : monitor going from green to orange).
++ * Currently, user space apps like quality monitors don't have any
++ * way to calibrate the measurement. With this, they can split
++ * the range between 0 and max_qual in different quality level
++ * (using a geometric subdivision centered on the average).
++ * I expect that people doing the user space apps will feedback
++ * us on which value we need to put in each driver... */
++ struct iw_quality avg_qual; /* Quality of the link */
+
+ /* Rates */
+ __u8 num_bitrates; /* Number of entries in the list */
+@@ -619,6 +658,8 @@ struct iw_range
+ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
+ __u8 num_encoding_sizes; /* Number of entry in the list */
+ __u8 max_encoding_tokens; /* Max number of tokens */
++ /* For drivers that need a "login/passwd" form */
++ __u8 encoding_login_index; /* token index for login token */
+
+ /* Transmit power */
+ __u16 txpower_capa; /* What options are supported */
+@@ -638,18 +679,12 @@ struct iw_range
+ __s32 min_r_time; /* Minimal retry lifetime */
+ __s32 max_r_time; /* Maximal retry lifetime */
+
+- /* Average quality of link & SNR */
+- struct iw_quality avg_qual; /* Quality of the link */
+- /* This should contain the average/typical values of the quality
+- * indicator. This should be the threshold between a "good" and
+- * a "bad" link (example : monitor going from green to orange).
+- * Currently, user space apps like quality monitors don't have any
+- * way to calibrate the measurement. With this, they can split
+- * the range between 0 and max_qual in different quality level
+- * (using a geometric subdivision centered on the average).
+- * I expect that people doing the user space apps will feedback
+- * us on which value we need to put in each driver...
+- */
++ /* Frequency */
++ __u16 num_channels; /* Number of channels [0; num - 1] */
++ __u8 num_frequency; /* Number of entry in the list */
++ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
++ /* Note : this frequency list doesn't need to fit channel numbers,
++ * because each entry contain its channel index */
+ };
+
+ /*
+diff -u -p linux/include/net/iw_handler.15.h linux/include/net/iw_handler.h
+--- linux/include/net/iw_handler.15.h 2004-11-05 14:59:47.000000000 -0800
++++ linux/include/net/iw_handler.h 2004-11-05 15:00:42.000000000 -0800
+@@ -1,7 +1,7 @@
+ /*
+ * This file define the new driver API for Wireless Extensions
+ *
+- * Version : 4 21.6.02
++ * Version : 5 4.12.02
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
+@@ -206,7 +206,7 @@
+ * will be needed...
+ * I just plan to increment with each new version.
+ */
+-#define IW_HANDLER_VERSION 4
++#define IW_HANDLER_VERSION 5
+
+ /*
+ * Changes :
+@@ -220,10 +220,18 @@
+ * V3 to V4
+ * --------
+ * - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
++ *
++ * V4 to V5
++ * --------
++ * - Add new spy support : struct iw_spy_data & prototypes
+ */
+
+ /**************************** CONSTANTS ****************************/
+
++/* Enable enhanced spy support. Disable to reduce footprint */
++#define IW_WIRELESS_SPY
++#define IW_WIRELESS_THRSPY
++
+ /* Special error message for the driver to indicate that we
+ * should do a commit after return from the iw_handler */
+ #define EIWCOMMIT EINPROGRESS
+@@ -315,6 +323,9 @@ struct iw_handler_def
+ * We will automatically export that to user space... */
+ struct iw_priv_args * private_args;
+
++ /* Driver enhanced spy support */
++ long spy_offset; /* Spy data offset */
++
+ /* In the long term, get_wireless_stats will move from
+ * 'struct net_device' to here, to minimise bloat. */
+ };
+@@ -350,6 +361,33 @@ struct iw_ioctl_description
+
+ /* Need to think of short header translation table. Later. */
+
++/* --------------------- ENHANCED SPY SUPPORT --------------------- */
++/*
++ * In the old days, the driver was handling spy support all by itself.
++ * Now, the driver can delegate this task to Wireless Extensions.
++ * It needs to include this struct in its private part and use the
++ * standard spy iw_handler.
++ */
++
++/*
++ * Instance specific spy data, i.e. addresses spied and quality for them.
++ */
++struct iw_spy_data
++{
++#ifdef IW_WIRELESS_SPY
++ /* --- Standard spy support --- */
++ int spy_number;
++ u_char spy_address[IW_MAX_SPY][ETH_ALEN];
++ struct iw_quality spy_stat[IW_MAX_SPY];
++#ifdef IW_WIRELESS_THRSPY
++ /* --- Enhanced spy support (event) */
++ struct iw_quality spy_thr_low; /* Low threshold */
++ struct iw_quality spy_thr_high; /* High threshold */
++ u_char spy_thr_under[IW_MAX_SPY];
++#endif /* IW_WIRELESS_THRSPY */
++#endif /* IW_WIRELESS_SPY */
++};
++
+ /**************************** PROTOTYPES ****************************/
+ /*
+ * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
+@@ -376,6 +414,31 @@ extern void wireless_send_event(struct n
+ /* We may need a function to send a stream of events to user space.
+ * More on that later... */
+
++/* Standard handler for SIOCSIWSPY */
++extern int iw_handler_set_spy(struct net_device * dev,
++ struct iw_request_info * info,
++ union iwreq_data * wrqu,
++ char * extra);
++/* Standard handler for SIOCGIWSPY */
++extern int iw_handler_get_spy(struct net_device * dev,
++ struct iw_request_info * info,
++ union iwreq_data * wrqu,
++ char * extra);
++/* Standard handler for SIOCSIWTHRSPY */
++extern int iw_handler_set_thrspy(struct net_device * dev,
++ struct iw_request_info *info,
++ union iwreq_data * wrqu,
++ char * extra);
++/* Standard handler for SIOCGIWTHRSPY */
++extern int iw_handler_get_thrspy(struct net_device * dev,
++ struct iw_request_info *info,
++ union iwreq_data * wrqu,
++ char * extra);
++/* Driver call to update spy records */
++extern void wireless_spy_update(struct net_device * dev,
++ unsigned char * address,
++ struct iw_quality * wstats);
++
+ /************************* INLINE FUNTIONS *************************/
+ /*
+ * Function that are so simple that it's more efficient inlining them
+diff -u -p linux/net/core/wireless.15.c linux/net/core/wireless.c
+--- linux/net/core/wireless.15.c 2004-11-05 15:00:11.000000000 -0800
++++ linux/net/core/wireless.c 2004-11-05 15:00:42.000000000 -0800
+@@ -2,7 +2,7 @@
+ * This file implement the Wireless Extensions APIs.
+ *
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
+ *
+ * (As all part of the Linux kernel, this file is GPL)
+ */
+@@ -43,6 +43,11 @@
+ * o Turn on WE_STRICT_WRITE by default + kernel warning
+ * o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
+ * o Fix off-by-one in test (extra_size <= IFNAMSIZ)
++ *
++ * v6 - 9.01.03 - Jean II
++ * o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
++ * o Add enhanced spy support : iw_handler_set_thrspy() and event.
++ * o Add WIRELESS_EXT version display in /proc/net/wireless
+ */
+
+ /***************************** INCLUDES *****************************/
+@@ -52,6 +57,7 @@
+ #include <linux/types.h> /* off_t */
+ #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
+ #include <linux/rtnetlink.h> /* rtnetlink stuff */
++#include <linux/if_arp.h> /* ARPHRD_ETHER */
+
+ #include <linux/wireless.h> /* Pretty obvious */
+ #include <net/iw_handler.h> /* New driver API */
+@@ -65,6 +71,7 @@
+ /* Debuging stuff */
+ #undef WE_IOCTL_DEBUG /* Debug IOCTL 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 */
+@@ -72,7 +79,7 @@
+
+ /************************* GLOBAL VARIABLES *************************/
+ /*
+- * You should not use global variables, because or re-entrancy.
++ * You should not use global variables, because of re-entrancy.
+ * On our case, it's only const, so it's OK...
+ */
+ /*
+@@ -115,11 +122,11 @@ static const struct iw_ioctl_description
+ /* SIOCSIWSPY */
+ { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
+ /* SIOCGIWSPY */
+- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0},
+- /* -- hole -- */
+- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
+- /* -- hole -- */
+- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
++ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
++ /* SIOCSIWTHRSPY */
++ { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
++ /* SIOCGIWTHRSPY */
++ { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
+ /* SIOCSIWAP */
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
+ /* SIOCGIWAP */
+@@ -377,9 +384,9 @@ int dev_get_wireless_info(char * buffer,
+ struct net_device * dev;
+
+ size = sprintf(buffer,
+- "Inter-| sta-| Quality | Discarded packets | Missed\n"
+- " face | tus | link level noise | nwid crypt frag retry misc | beacon\n"
+- );
++ "Inter-| sta-| Quality | Discarded packets | Missed | WE\n"
++ " face | tus | link level noise | nwid crypt frag retry misc | beacon | %d\n",
++ WIRELESS_EXT);
+
+ pos += size;
+ len += size;
+@@ -1024,3 +1031,252 @@ void wireless_send_event(struct net_devi
+
+ return; /* Always success, I guess ;-) */
+ }
++
++/********************** ENHANCED IWSPY SUPPORT **********************/
++/*
++ * In the old days, the driver was handling spy support all by itself.
++ * Now, the driver can delegate this task to Wireless Extensions.
++ * It needs to use those standard spy iw_handler in struct iw_handler_def,
++ * push data to us via XXX and include struct iw_spy_data in its
++ * private part.
++ * One of the main advantage of centralising spy support here is that
++ * it becomes much easier to improve and extend it without having to touch
++ * the drivers. One example is the addition of the Spy-Threshold events.
++ * Note : IW_WIRELESS_SPY is defined in iw_handler.h
++ */
++
++/*------------------------------------------------------------------*/
++/*
++ * Standard Wireless Handler : set Spy List
++ */
++int iw_handler_set_spy(struct net_device * dev,
++ struct iw_request_info * info,
++ union iwreq_data * wrqu,
++ char * extra)
++{
++#ifdef IW_WIRELESS_SPY
++ struct iw_spy_data * spydata = (dev->priv +
++ dev->wireless_handlers->spy_offset);
++ struct sockaddr * address = (struct sockaddr *) extra;
++
++ /* Disable spy collection while we copy the addresses.
++ * As we don't disable interrupts, we need to do this to avoid races.
++ * As we are the only writer, this is good enough. */
++ spydata->spy_number = 0;
++
++ /* Are there are addresses to copy? */
++ if(wrqu->data.length > 0) {
++ int i;
++
++ /* Copy addresses */
++ for(i = 0; i < wrqu->data.length; i++)
++ memcpy(spydata->spy_address[i], address[i].sa_data,
++ ETH_ALEN);
++ /* Reset stats */
++ memset(spydata->spy_stat, 0,
++ sizeof(struct iw_quality) * IW_MAX_SPY);
++
++#ifdef WE_SPY_DEBUG
++ printk(KERN_DEBUG "iw_handler_set_spy() : offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length);
++ for (i = 0; i < wrqu->data.length; i++)
++ printk(KERN_DEBUG
++ "%02X:%02X:%02X:%02X:%02X:%02X \n",
++ spydata->spy_address[i][0],
++ spydata->spy_address[i][1],
++ spydata->spy_address[i][2],
++ spydata->spy_address[i][3],
++ spydata->spy_address[i][4],
++ spydata->spy_address[i][5]);
++#endif /* WE_SPY_DEBUG */
++ }
++ /* Enable addresses */
++ spydata->spy_number = wrqu->data.length;
++
++ return 0;
++#else /* IW_WIRELESS_SPY */
++ return -EOPNOTSUPP;
++#endif /* IW_WIRELESS_SPY */
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Standard Wireless Handler : get Spy List
++ */
++int iw_handler_get_spy(struct net_device * dev,
++ struct iw_request_info * info,
++ union iwreq_data * wrqu,
++ char * extra)
++{
++#ifdef IW_WIRELESS_SPY
++ struct iw_spy_data * spydata = (dev->priv +
++ dev->wireless_handlers->spy_offset);
++ struct sockaddr * address = (struct sockaddr *) extra;
++ int i;
++
++ wrqu->data.length = spydata->spy_number;
++
++ /* Copy addresses. */
++ for(i = 0; i < spydata->spy_number; i++) {
++ memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
++ address[i].sa_family = AF_UNIX;
++ }
++ /* Copy stats to the user buffer (just after). */
++ if(spydata->spy_number > 0)
++ memcpy(extra + (sizeof(struct sockaddr) *spydata->spy_number),
++ spydata->spy_stat,
++ sizeof(struct iw_quality) * spydata->spy_number);
++ /* Reset updated flags. */
++ for(i = 0; i < spydata->spy_number; i++)
++ spydata->spy_stat[i].updated = 0;
++ return 0;
++#else /* IW_WIRELESS_SPY */
++ return -EOPNOTSUPP;
++#endif /* IW_WIRELESS_SPY */
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Standard Wireless Handler : set spy threshold
++ */
++int iw_handler_set_thrspy(struct net_device * dev,
++ struct iw_request_info *info,
++ union iwreq_data * wrqu,
++ char * extra)
++{
++#ifdef IW_WIRELESS_THRSPY
++ struct iw_spy_data * spydata = (dev->priv +
++ dev->wireless_handlers->spy_offset);
++ struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
++
++ /* Just do it */
++ memcpy(&(spydata->spy_thr_low), &(threshold->low),
++ 2 * sizeof(struct iw_quality));
++
++ /* Clear flag */
++ memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
++
++#ifdef WE_SPY_DEBUG
++ printk(KERN_DEBUG "iw_handler_set_thrspy() : low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level);
++#endif /* WE_SPY_DEBUG */
++
++ return 0;
++#else /* IW_WIRELESS_THRSPY */
++ return -EOPNOTSUPP;
++#endif /* IW_WIRELESS_THRSPY */
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Standard Wireless Handler : get spy threshold
++ */
++int iw_handler_get_thrspy(struct net_device * dev,
++ struct iw_request_info *info,
++ union iwreq_data * wrqu,
++ char * extra)
++{
++#ifdef IW_WIRELESS_THRSPY
++ struct iw_spy_data * spydata = (dev->priv +
++ dev->wireless_handlers->spy_offset);
++ struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
++
++ /* Just do it */
++ memcpy(&(threshold->low), &(spydata->spy_thr_low),
++ 2 * sizeof(struct iw_quality));
++
++ return 0;
++#else /* IW_WIRELESS_THRSPY */
++ return -EOPNOTSUPP;
++#endif /* IW_WIRELESS_THRSPY */
++}
++
++#ifdef IW_WIRELESS_THRSPY
++/*------------------------------------------------------------------*/
++/*
++ * Prepare and send a Spy Threshold event
++ */
++static void iw_send_thrspy_event(struct net_device * dev,
++ struct iw_spy_data * spydata,
++ unsigned char * address,
++ struct iw_quality * wstats)
++{
++ union iwreq_data wrqu;
++ struct iw_thrspy threshold;
++
++ /* Init */
++ wrqu.data.length = 1;
++ wrqu.data.flags = 0;
++ /* Copy address */
++ memcpy(threshold.addr.sa_data, address, ETH_ALEN);
++ threshold.addr.sa_family = ARPHRD_ETHER;
++ /* Copy stats */
++ memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
++ /* Copy also thresholds */
++ memcpy(&(threshold.low), &(spydata->spy_thr_low),
++ 2 * sizeof(struct iw_quality));
++
++#ifdef WE_SPY_DEBUG
++ printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n",
++ threshold.addr.sa_data[0],
++ threshold.addr.sa_data[1],
++ threshold.addr.sa_data[2],
++ threshold.addr.sa_data[3],
++ threshold.addr.sa_data[4],
++ threshold.addr.sa_data[5], threshold.qual.level);
++#endif /* WE_SPY_DEBUG */
++
++ /* Send event to user space */
++ wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
++}
++#endif /* IW_WIRELESS_THRSPY */
++
++/* ---------------------------------------------------------------- */
++/*
++ * Call for the driver to update the spy data.
++ * For now, the spy data is a simple array. As the size of the array is
++ * small, this is good enough. If we wanted to support larger number of
++ * spy addresses, we should use something more efficient...
++ */
++void wireless_spy_update(struct net_device * dev,
++ unsigned char * address,
++ struct iw_quality * wstats)
++{
++#ifdef IW_WIRELESS_SPY
++ struct iw_spy_data * spydata = (dev->priv +
++ dev->wireless_handlers->spy_offset);
++ int i;
++ int match = -1;
++
++#ifdef WE_SPY_DEBUG
++ printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
++#endif /* WE_SPY_DEBUG */
++
++ /* Update all records that match */
++ for(i = 0; i < spydata->spy_number; i++)
++ if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) {
++ memcpy(&(spydata->spy_stat[i]), wstats,
++ sizeof(struct iw_quality));
++ match = i;
++ }
++#ifdef IW_WIRELESS_THRSPY
++ /* Generate an event if we cross the spy threshold.
++ * To avoid event storms, we have a simple hysteresis : we generate
++ * event only when we go under the low threshold or above the
++ * high threshold. */
++ if(match >= 0) {
++ if(spydata->spy_thr_under[match]) {
++ if(wstats->level > spydata->spy_thr_high.level) {
++ spydata->spy_thr_under[match] = 0;
++ iw_send_thrspy_event(dev, spydata,
++ address, wstats);
++ }
++ } else {
++ if(wstats->level < spydata->spy_thr_low.level) {
++ spydata->spy_thr_under[match] = 1;
++ iw_send_thrspy_event(dev, spydata,
++ address, wstats);
++ }
++ }
++ }
++#endif /* IW_WIRELESS_THRSPY */
++#endif /* IW_WIRELESS_SPY */
++}
+diff -u -p linux/net/netsyms.15.c linux/net/netsyms.c
+--- linux/net/netsyms.15.c 2004-11-05 15:00:25.000000000 -0800
++++ linux/net/netsyms.c 2004-11-05 15:01:38.000000000 -0800
+@@ -589,9 +589,13 @@ EXPORT_SYMBOL(net_call_rx_atomic);
+ EXPORT_SYMBOL(softnet_data);
+
+ #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
+-/* Don't include the whole header mess for a single function */
+-extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, char *extra);
++#include <net/iw_handler.h>
+ EXPORT_SYMBOL(wireless_send_event);
++EXPORT_SYMBOL(iw_handler_set_spy);
++EXPORT_SYMBOL(iw_handler_get_spy);
++EXPORT_SYMBOL(iw_handler_set_thrspy);
++EXPORT_SYMBOL(iw_handler_get_thrspy);
++EXPORT_SYMBOL(wireless_spy_update);
+ #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
+
+ #endif /* CONFIG_NET */