Commit 72f70c37 authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by Linus Torvalds

[PATCH] Wireless Extension 16

        This patch for 2.5.68-bk11 will update Wireless Extension to
version 16 :
        o increase bitrate and frequency number for 802.11g/802.11a
        o enhanced iwspy support
        o minor tweaks and cleanups

        This patch is only for the core of WE. The patches for the
individual drivers have been sent to their respective maintainers.
	Compared to the previous version I sent you a few weeks ago,
I've just updated to the latest kernel.
parent 5e556524
/* /*
* This file define a set of standard wireless extensions * 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> * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
...@@ -69,6 +69,8 @@ ...@@ -69,6 +69,8 @@
/***************************** INCLUDES *****************************/ /***************************** 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/types.h> /* for "caddr_t" et al */
#include <linux/socket.h> /* for "struct sockaddr" et al */ #include <linux/socket.h> /* for "struct sockaddr" et al */
#include <linux/if.h> /* for IFNAMSIZ and co... */ #include <linux/if.h> /* for IFNAMSIZ and co... */
...@@ -80,7 +82,7 @@ ...@@ -80,7 +82,7 @@
* (there is some stuff that will be added in the future...) * (there is some stuff that will be added in the future...)
* I just plan to increment with each new version. * I just plan to increment with each new version.
*/ */
#define WIRELESS_EXT 15 #define WIRELESS_EXT 16
/* /*
* Changes : * Changes :
...@@ -163,6 +165,16 @@ ...@@ -163,6 +165,16 @@
* - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IW_TXPOW_RANGE for range of Tx Powers
* - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
* - Add IW_MODE_MONITOR for passive monitor * - 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 ****************************/ /**************************** CONSTANTS ****************************/
...@@ -196,9 +208,11 @@ ...@@ -196,9 +208,11 @@
/* SIOCGIWSTATS is strictly used between user space and the kernel, and /* 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). */ * 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 SIOCSIWSPY 0x8B10 /* set spy addresses */
#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ #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 */ /* Access Point manipulation */
#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
...@@ -306,13 +320,13 @@ ...@@ -306,13 +320,13 @@
/* ----------------------- OTHER CONSTANTS ----------------------- */ /* ----------------------- OTHER CONSTANTS ----------------------- */
/* Maximum frequencies in the range struct */ /* Maximum frequencies in the range struct */
#define IW_MAX_FREQUENCIES 16 #define IW_MAX_FREQUENCIES 32
/* Note : if you have something like 80 frequencies, /* Note : if you have something like 80 frequencies,
* don't increase this constant and don't fill the frequency list. * don't increase this constant and don't fill the frequency list.
* The user will be able to set by channel anyway... */ * The user will be able to set by channel anyway... */
/* Maximum bit rates in the range struct */ /* Maximum bit rates in the range struct */
#define IW_MAX_BITRATES 8 #define IW_MAX_BITRATES 32
/* Maximum tx powers in the range struct */ /* Maximum tx powers in the range struct */
#define IW_MAX_TXPOWER 8 #define IW_MAX_TXPOWER 8
...@@ -320,12 +334,11 @@ ...@@ -320,12 +334,11 @@
* a few of them in the struct iw_range. */ * a few of them in the struct iw_range. */
/* Maximum of address that you may set with SPY */ /* Maximum of address that you may set with SPY */
#define IW_MAX_SPY 8 /* set */ #define IW_MAX_SPY 8
#define IW_MAX_GET_SPY 64 /* get */
/* Maximum of address that you may get in the /* Maximum of address that you may get in the
list of access points in range */ list of access points in range */
#define IW_MAX_AP 8 #define IW_MAX_AP 64
/* Maximum size of the ESSID and NICKN strings */ /* Maximum size of the ESSID and NICKN strings */
#define IW_ESSID_MAX_SIZE 32 #define IW_ESSID_MAX_SIZE 32
...@@ -355,6 +368,7 @@ ...@@ -355,6 +368,7 @@
#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
#define IW_ENCODE_OPEN 0x2000 /* Accept 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) */ /* Power management flags available (along with the value, if any) */
#define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_ON 0x0000 /* No details... */
...@@ -482,6 +496,17 @@ struct iw_missed ...@@ -482,6 +496,17 @@ struct iw_missed
__u32 beacon; /* Missed beacons/superframe */ __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 STATS ------------------------ */
/* /*
* Wireless statistics (used for /proc/net/wireless) * Wireless statistics (used for /proc/net/wireless)
...@@ -534,7 +559,7 @@ union iwreq_data ...@@ -534,7 +559,7 @@ union iwreq_data
struct iw_quality qual; /* Quality part of statistics */ struct iw_quality qual; /* Quality part of statistics */
struct sockaddr ap_addr; /* Access point address */ 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_param param; /* Other small parameters */
struct iw_point data; /* Other large parameters */ struct iw_point data; /* Other large parameters */
...@@ -582,17 +607,31 @@ struct iw_range ...@@ -582,17 +607,31 @@ struct iw_range
__u32 min_nwid; /* Minimal NWID we are able to set */ __u32 min_nwid; /* Minimal NWID we are able to set */
__u32 max_nwid; /* Maximal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */
/* Frequency */ /* Old Frequency (backward compat - moved lower ) */
__u16 num_channels; /* Number of channels [0; num - 1] */ __u16 old_num_channels;
__u8 num_frequency; /* Number of entry in the list */ __u8 old_num_frequency;
struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Filler to keep "version" at the same offset */
/* Note : this frequency list doesn't need to fit channel numbers */ __s32 old_freq[6];
/* signal level threshold range */ /* signal level threshold range */
__s32 sensitivity; __s32 sensitivity;
/* Quality of link & SNR stuff */ /* 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 */ 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 */ /* Rates */
__u8 num_bitrates; /* Number of entries in the list */ __u8 num_bitrates; /* Number of entries in the list */
...@@ -619,6 +658,8 @@ struct iw_range ...@@ -619,6 +658,8 @@ struct iw_range
__u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
__u8 num_encoding_sizes; /* Number of entry in the list */ __u8 num_encoding_sizes; /* Number of entry in the list */
__u8 max_encoding_tokens; /* Max number of tokens */ __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 */ /* Transmit power */
__u16 txpower_capa; /* What options are supported */ __u16 txpower_capa; /* What options are supported */
...@@ -638,18 +679,12 @@ struct iw_range ...@@ -638,18 +679,12 @@ struct iw_range
__s32 min_r_time; /* Minimal retry lifetime */ __s32 min_r_time; /* Minimal retry lifetime */
__s32 max_r_time; /* Maximal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */
/* Average quality of link & SNR */ /* Frequency */
struct iw_quality avg_qual; /* Quality of the link */ __u16 num_channels; /* Number of channels [0; num - 1] */
/* This should contain the average/typical values of the quality __u8 num_frequency; /* Number of entry in the list */
* indicator. This should be the threshold between a "good" and struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
* a "bad" link (example : monitor going from green to orange). /* Note : this frequency list doesn't need to fit channel numbers,
* Currently, user space apps like quality monitors don't have any * because each entry contain its channel index */
* 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...
*/
}; };
/* /*
......
/* /*
* This file define the new driver API for Wireless Extensions * 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> * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved. * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
...@@ -206,7 +206,7 @@ ...@@ -206,7 +206,7 @@
* will be needed... * will be needed...
* I just plan to increment with each new version. * I just plan to increment with each new version.
*/ */
#define IW_HANDLER_VERSION 4 #define IW_HANDLER_VERSION 5
/* /*
* Changes : * Changes :
...@@ -220,10 +220,18 @@ ...@@ -220,10 +220,18 @@
* V3 to V4 * V3 to V4
* -------- * --------
* - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes * - 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 ****************************/ /**************************** 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 /* Special error message for the driver to indicate that we
* should do a commit after return from the iw_handler */ * should do a commit after return from the iw_handler */
#define EIWCOMMIT EINPROGRESS #define EIWCOMMIT EINPROGRESS
...@@ -315,6 +323,9 @@ struct iw_handler_def ...@@ -315,6 +323,9 @@ struct iw_handler_def
* We will automatically export that to user space... */ * We will automatically export that to user space... */
struct iw_priv_args * private_args; 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 /* In the long term, get_wireless_stats will move from
* 'struct net_device' to here, to minimise bloat. */ * 'struct net_device' to here, to minimise bloat. */
}; };
...@@ -350,6 +361,33 @@ struct iw_ioctl_description ...@@ -350,6 +361,33 @@ struct iw_ioctl_description
/* Need to think of short header translation table. Later. */ /* 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 ****************************/ /**************************** PROTOTYPES ****************************/
/* /*
* Functions part of the Wireless Extensions (defined in net/core/wireless.c). * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
...@@ -376,6 +414,31 @@ extern void wireless_send_event(struct net_device * dev, ...@@ -376,6 +414,31 @@ extern void wireless_send_event(struct net_device * dev,
/* We may need a function to send a stream of events to user space. /* We may need a function to send a stream of events to user space.
* More on that later... */ * 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 *************************/ /************************* INLINE FUNTIONS *************************/
/* /*
* Function that are so simple that it's more efficient inlining them * Function that are so simple that it's more efficient inlining them
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* This file implement the Wireless Extensions APIs. * This file implement the Wireless Extensions APIs.
* *
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> * 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) * (As all part of the Linux kernel, this file is GPL)
*/ */
...@@ -43,6 +43,11 @@ ...@@ -43,6 +43,11 @@
* o Turn on WE_STRICT_WRITE by default + kernel warning * o Turn on WE_STRICT_WRITE by default + kernel warning
* o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num) * o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
* o Fix off-by-one in test (extra_size <= IFNAMSIZ) * 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 *****************************/ /***************************** INCLUDES *****************************/
...@@ -53,9 +58,10 @@ ...@@ -53,9 +58,10 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/rtnetlink.h> /* rtnetlink stuff */ #include <linux/rtnetlink.h> /* rtnetlink stuff */
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/wireless.h> /* Pretty obvious */
#include <linux/init.h> /* for __init */ #include <linux/init.h> /* for __init */
#include <linux/if_arp.h> /* ARPHRD_ETHER */
#include <linux/wireless.h> /* Pretty obvious */
#include <net/iw_handler.h> /* New driver API */ #include <net/iw_handler.h> /* New driver API */
#include <asm/uaccess.h> /* copy_to_user() */ #include <asm/uaccess.h> /* copy_to_user() */
...@@ -69,6 +75,7 @@ ...@@ -69,6 +75,7 @@
/* Debugging stuff */ /* Debugging stuff */
#undef WE_IOCTL_DEBUG /* Debug IOCTL API */ #undef WE_IOCTL_DEBUG /* Debug IOCTL API */
#undef WE_EVENT_DEBUG /* Debug Event dispatcher */ #undef WE_EVENT_DEBUG /* Debug Event dispatcher */
#undef WE_SPY_DEBUG /* Debug enhanced spy support */
/* Options */ /* Options */
#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */ #define WE_EVENT_NETLINK /* Propagate events using rtnetlink */
...@@ -76,7 +83,7 @@ ...@@ -76,7 +83,7 @@
/************************* GLOBAL VARIABLES *************************/ /************************* 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... * On our case, it's only const, so it's OK...
*/ */
/* /*
...@@ -152,7 +159,19 @@ static const struct iw_ioctl_description standard_ioctl[] = { ...@@ -152,7 +159,19 @@ static const struct iw_ioctl_description standard_ioctl[] = {
.header_type = IW_HEADER_TYPE_POINT, .header_type = IW_HEADER_TYPE_POINT,
.token_size = sizeof(struct sockaddr) + .token_size = sizeof(struct sockaddr) +
sizeof(struct iw_quality), sizeof(struct iw_quality),
.max_tokens = IW_MAX_GET_SPY, .max_tokens = IW_MAX_SPY,
},
[SIOCSIWTHRSPY - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = sizeof(struct iw_thrspy),
.min_tokens = 1,
.max_tokens = 1,
},
[SIOCGIWTHRSPY - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = sizeof(struct iw_thrspy),
.min_tokens = 1,
.max_tokens = 1,
}, },
[SIOCSIWAP - SIOCIWFIRST] = { [SIOCSIWAP - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_ADDR, .header_type = IW_HEADER_TYPE_ADDR,
...@@ -440,9 +459,10 @@ static int wireless_seq_show(struct seq_file *seq, void *v) ...@@ -440,9 +459,10 @@ static int wireless_seq_show(struct seq_file *seq, void *v)
{ {
if (v == (void *)1) if (v == (void *)1)
seq_printf(seq, "Inter-| sta-| Quality | Discarded " seq_printf(seq, "Inter-| sta-| Quality | Discarded "
"packets | Missed\n" "packets | Missed | WE\n"
" face | tus | link level noise | nwid " " face | tus | link level noise | nwid "
"crypt frag retry misc | beacon\n"); "crypt frag retry misc | beacon | %d\n",
WIRELESS_EXT);
else else
wireless_seq_printf_stats(seq, v); wireless_seq_printf_stats(seq, v);
return 0; return 0;
...@@ -1100,3 +1120,252 @@ void wireless_send_event(struct net_device * dev, ...@@ -1100,3 +1120,252 @@ void wireless_send_event(struct net_device * dev,
return; /* Always success, I guess ;-) */ 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 wireless_spy_update() and include struct iw_spy_data
* in its private part (and advertise it in iw_handler_def->spy_offset).
* 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 */
}
...@@ -666,10 +666,13 @@ EXPORT_SYMBOL(register_gifconf); ...@@ -666,10 +666,13 @@ EXPORT_SYMBOL(register_gifconf);
EXPORT_SYMBOL(softnet_data); EXPORT_SYMBOL(softnet_data);
#ifdef CONFIG_NET_RADIO #ifdef CONFIG_NET_RADIO
/* Don't include the whole header mess for a single function */ #include <net/iw_handler.h> /* Wireless Extensions driver API */
union iwreq_data;
extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, char *extra);
EXPORT_SYMBOL(wireless_send_event); 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 */ #endif /* CONFIG_NET_RADIO */
EXPORT_SYMBOL(linkwatch_fire_event); EXPORT_SYMBOL(linkwatch_fire_event);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment