aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Tourrilhes <jt@hpl.hp.com>2005-09-02 14:32:28 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-09-06 22:40:24 -0400
commit6582c164f2b3b6e58d1f13c1c031b19ee691eb14 (patch)
tree492043111300ee6e1341a6e679a13983893c438c
parent054034dbf5b1a6aef800af4eb22d421d1c7d4b6d (diff)
[PATCH] WE-19 for kernel 2.6.13
Hi Jeff, This is version 19 of the Wireless Extensions. It was supposed to be the fallback of the WPA API changes, but people seem quite happy about it (especially Jouni), so the patch is rather small. The patch has been fully tested with 2.6.13 and various wireless drivers, and is in its final version. Would you mind pushing that into Linus's kernel so that the driver and the apps can take advantage ot it ? It includes : o iwstat improvement (explicit dBm). This is the result of long discussions with Dan Williams, the authors of NetworkManager. Thanks to him for all the fruitful feedback. o remove pointer from event stream. I was not totally sure if this pointer was 32-64 bits clean, so I'd rather remove it and be at peace with it. o remove linux header from wireless.h. This has long been requested by people writting user space apps, now it's done, and it was not even painful. o final deprecation of spy_offset. You did not like it, it's now gone for good. o Start deprecating dev->get_wireless_stats -> debloat netdev o Add "check" version of event macros for ieee802.11 stack. Jiri Benc doesn't like the current macros, we aim to please ;-) All those changes, except the last one, have been bit-roting on my web pages for a while... Patches for most kernel drivers will follow. Patches for the Orinoco and the HostAP drivers have been sent to their respective maintainers. Have fun... Jean Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r--include/linux/wireless.h47
-rw-r--r--include/net/iw_handler.h123
-rw-r--r--net/core/wireless.c58
3 files changed, 175 insertions, 53 deletions
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index ae485f9c916e..dab5afdaf71c 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file define a set of standard wireless extensions 2 * This file define a set of standard wireless extensions
3 * 3 *
4 * Version : 18 12.3.05 4 * Version : 19 18.3.05
5 * 5 *
6 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> 6 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
7 * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. 7 * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
@@ -69,11 +69,12 @@
69 69
70/***************************** INCLUDES *****************************/ 70/***************************** INCLUDES *****************************/
71 71
72/* To minimise problems in user space, I might remove those headers 72/* Do not put any header in this file, this creates a mess when
73 * at some point. Jean II */ 73 * exported to user space. Most users have included all the
74#include <linux/types.h> /* for "caddr_t" et al */ 74 * relevant headers anyway... Jean II */
75#include <linux/socket.h> /* for "struct sockaddr" et al */ 75/*#include <linux/types.h>*/ /* for "caddr_t" et al */
76#include <linux/if.h> /* for IFNAMSIZ and co... */ 76/*#include <linux/socket.h>*/ /* for "struct sockaddr" et al */
77/*#include <linux/if.h>*/ /* for IFNAMSIZ and co... */
77 78
78/***************************** VERSION *****************************/ 79/***************************** VERSION *****************************/
79/* 80/*
@@ -82,7 +83,7 @@
82 * (there is some stuff that will be added in the future...) 83 * (there is some stuff that will be added in the future...)
83 * I just plan to increment with each new version. 84 * I just plan to increment with each new version.
84 */ 85 */
85#define WIRELESS_EXT 18 86#define WIRELESS_EXT 19
86 87
87/* 88/*
88 * Changes : 89 * Changes :
@@ -197,6 +198,15 @@
197 * related parameters (extensible up to 4096 parameter values) 198 * related parameters (extensible up to 4096 parameter values)
198 * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, 199 * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
199 * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND 200 * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
201 *
202 * V18 to V19
203 * ----------
204 * - Remove (struct iw_point *)->pointer from events and streams
205 * - Remove header includes to help user space
206 * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
207 * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
208 * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
209 * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
200 */ 210 */
201 211
202/**************************** CONSTANTS ****************************/ 212/**************************** CONSTANTS ****************************/
@@ -322,6 +332,7 @@
322/* The first and the last (range) */ 332/* The first and the last (range) */
323#define SIOCIWFIRST 0x8B00 333#define SIOCIWFIRST 0x8B00
324#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ 334#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */
335#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
325 336
326/* Even : get (world access), odd : set (root access) */ 337/* Even : get (world access), odd : set (root access) */
327#define IW_IS_SET(cmd) (!((cmd) & 0x1)) 338#define IW_IS_SET(cmd) (!((cmd) & 0x1))
@@ -366,6 +377,7 @@
366 * (struct iw_pmkid_cand) */ 377 * (struct iw_pmkid_cand) */
367 378
368#define IWEVFIRST 0x8C00 379#define IWEVFIRST 0x8C00
380#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
369 381
370/* ------------------------- PRIVATE INFO ------------------------- */ 382/* ------------------------- PRIVATE INFO ------------------------- */
371/* 383/*
@@ -427,12 +439,15 @@
427#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ 439#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
428 440
429/* Statistics flags (bitmask in updated) */ 441/* Statistics flags (bitmask in updated) */
430#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */ 442#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
431#define IW_QUAL_LEVEL_UPDATED 0x2 443#define IW_QUAL_LEVEL_UPDATED 0x02
432#define IW_QUAL_NOISE_UPDATED 0x4 444#define IW_QUAL_NOISE_UPDATED 0x04
445#define IW_QUAL_ALL_UPDATED 0x07
446#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
433#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ 447#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
434#define IW_QUAL_LEVEL_INVALID 0x20 448#define IW_QUAL_LEVEL_INVALID 0x20
435#define IW_QUAL_NOISE_INVALID 0x40 449#define IW_QUAL_NOISE_INVALID 0x40
450#define IW_QUAL_ALL_INVALID 0x70
436 451
437/* Frequency flags */ 452/* Frequency flags */
438#define IW_FREQ_AUTO 0x00 /* Let the driver decides */ 453#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
@@ -443,7 +458,7 @@
443#define IW_MAX_ENCODING_SIZES 8 458#define IW_MAX_ENCODING_SIZES 8
444 459
445/* Maximum size of the encoding token in bytes */ 460/* Maximum size of the encoding token in bytes */
446#define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ 461#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */
447 462
448/* Flags for encoding (along with the token) */ 463/* Flags for encoding (along with the token) */
449#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ 464#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
@@ -1039,12 +1054,16 @@ struct iw_event
1039#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) 1054#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
1040#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) 1055#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
1041#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) 1056#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
1042#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point))
1043#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) 1057#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
1044#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) 1058#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
1045#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) 1059#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
1046 1060
1047/* Note : in the case of iw_point, the extra data will come at the 1061/* iw_point events are special. First, the payload (extra data) come at
1048 * end of the event */ 1062 * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
1063 * we omit the pointer, so start at an offset. */
1064#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
1065 (char *) NULL)
1066#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
1067 IW_EV_POINT_OFF)
1049 1068
1050#endif /* _LINUX_WIRELESS_H */ 1069#endif /* _LINUX_WIRELESS_H */
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index 44edd48f1234..d67c8393a343 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -1,10 +1,10 @@
1/* 1/*
2 * This file define the new driver API for Wireless Extensions 2 * This file define the new driver API for Wireless Extensions
3 * 3 *
4 * Version : 6 21.6.04 4 * Version : 7 18.3.05
5 * 5 *
6 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> 6 * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
7 * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved. 7 * Copyright (c) 2001-2005 Jean Tourrilhes, All Rights Reserved.
8 */ 8 */
9 9
10#ifndef _IW_HANDLER_H 10#ifndef _IW_HANDLER_H
@@ -207,7 +207,7 @@
207 * will be needed... 207 * will be needed...
208 * I just plan to increment with each new version. 208 * I just plan to increment with each new version.
209 */ 209 */
210#define IW_HANDLER_VERSION 6 210#define IW_HANDLER_VERSION 7
211 211
212/* 212/*
213 * Changes : 213 * Changes :
@@ -232,6 +232,13 @@
232 * - Remove spy #ifdef, they are always on -> cleaner code 232 * - Remove spy #ifdef, they are always on -> cleaner code
233 * - Add IW_DESCR_FLAG_NOMAX flag for very large requests 233 * - Add IW_DESCR_FLAG_NOMAX flag for very large requests
234 * - Start migrating get_wireless_stats to struct iw_handler_def 234 * - Start migrating get_wireless_stats to struct iw_handler_def
235 *
236 * V6 to V7
237 * --------
238 * - Add struct ieee80211_device pointer in struct iw_public_data
239 * - Remove (struct iw_point *)->pointer from events and streams
240 * - Remove spy_offset from struct iw_handler_def
241 * - Add "check" version of event macros for ieee802.11 stack
235 */ 242 */
236 243
237/**************************** CONSTANTS ****************************/ 244/**************************** CONSTANTS ****************************/
@@ -334,9 +341,6 @@ struct iw_handler_def
334 * We will automatically export that to user space... */ 341 * We will automatically export that to user space... */
335 const struct iw_priv_args * private_args; 342 const struct iw_priv_args * private_args;
336 343
337 /* This field will be *removed* in the next version of WE */
338 long spy_offset; /* DO NOT USE */
339
340 /* New location of get_wireless_stats, to de-bloat struct net_device. 344 /* New location of get_wireless_stats, to de-bloat struct net_device.
341 * The old pointer in struct net_device will be gradually phased 345 * The old pointer in struct net_device will be gradually phased
342 * out, and drivers are encouraged to use this one... */ 346 * out, and drivers are encouraged to use this one... */
@@ -400,16 +404,21 @@ struct iw_spy_data
400/* --------------------- DEVICE WIRELESS DATA --------------------- */ 404/* --------------------- DEVICE WIRELESS DATA --------------------- */
401/* 405/*
402 * This is all the wireless data specific to a device instance that 406 * This is all the wireless data specific to a device instance that
403 * is managed by the core of Wireless Extensions. 407 * is managed by the core of Wireless Extensions or the 802.11 layer.
404 * We only keep pointer to those structures, so that a driver is free 408 * We only keep pointer to those structures, so that a driver is free
405 * to share them between instances. 409 * to share them between instances.
406 * This structure should be initialised before registering the device. 410 * This structure should be initialised before registering the device.
407 * Access to this data follow the same rules as any other struct net_device 411 * Access to this data follow the same rules as any other struct net_device
408 * data (i.e. valid as long as struct net_device exist, same locking rules). 412 * data (i.e. valid as long as struct net_device exist, same locking rules).
409 */ 413 */
414/* Forward declaration */
415struct ieee80211_device;
416/* The struct */
410struct iw_public_data { 417struct iw_public_data {
411 /* Driver enhanced spy support */ 418 /* Driver enhanced spy support */
412 struct iw_spy_data * spy_data; 419 struct iw_spy_data * spy_data;
420 /* Structure managed by the in-kernel IEEE 802.11 layer */
421 struct ieee80211_device * ieee80211;
413}; 422};
414 423
415/**************************** PROTOTYPES ****************************/ 424/**************************** PROTOTYPES ****************************/
@@ -424,7 +433,7 @@ struct iw_public_data {
424extern int dev_get_wireless_info(char * buffer, char **start, off_t offset, 433extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
425 int length); 434 int length);
426 435
427/* Handle IOCTLs, called in net/code/dev.c */ 436/* Handle IOCTLs, called in net/core/dev.c */
428extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); 437extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
429 438
430/* Second : functions that may be called by driver modules */ 439/* Second : functions that may be called by driver modules */
@@ -479,7 +488,7 @@ iwe_stream_add_event(char * stream, /* Stream of events */
479 int event_len) /* Real size of payload */ 488 int event_len) /* Real size of payload */
480{ 489{
481 /* Check if it's possible */ 490 /* Check if it's possible */
482 if((stream + event_len) < ends) { 491 if(likely((stream + event_len) < ends)) {
483 iwe->len = event_len; 492 iwe->len = event_len;
484 memcpy(stream, (char *) iwe, event_len); 493 memcpy(stream, (char *) iwe, event_len);
485 stream += event_len; 494 stream += event_len;
@@ -495,14 +504,17 @@ iwe_stream_add_event(char * stream, /* Stream of events */
495static inline char * 504static inline char *
496iwe_stream_add_point(char * stream, /* Stream of events */ 505iwe_stream_add_point(char * stream, /* Stream of events */
497 char * ends, /* End of stream */ 506 char * ends, /* End of stream */
498 struct iw_event *iwe, /* Payload */ 507 struct iw_event *iwe, /* Payload length + flags */
499 char * extra) 508 char * extra) /* More payload */
500{ 509{
501 int event_len = IW_EV_POINT_LEN + iwe->u.data.length; 510 int event_len = IW_EV_POINT_LEN + iwe->u.data.length;
502 /* Check if it's possible */ 511 /* Check if it's possible */
503 if((stream + event_len) < ends) { 512 if(likely((stream + event_len) < ends)) {
504 iwe->len = event_len; 513 iwe->len = event_len;
505 memcpy(stream, (char *) iwe, IW_EV_POINT_LEN); 514 memcpy(stream, (char *) iwe, IW_EV_LCP_LEN);
515 memcpy(stream + IW_EV_LCP_LEN,
516 ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
517 IW_EV_POINT_LEN - IW_EV_LCP_LEN);
506 memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length); 518 memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
507 stream += event_len; 519 stream += event_len;
508 } 520 }
@@ -526,7 +538,7 @@ iwe_stream_add_value(char * event, /* Event in the stream */
526 event_len -= IW_EV_LCP_LEN; 538 event_len -= IW_EV_LCP_LEN;
527 539
528 /* Check if it's possible */ 540 /* Check if it's possible */
529 if((value + event_len) < ends) { 541 if(likely((value + event_len) < ends)) {
530 /* Add new value */ 542 /* Add new value */
531 memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len); 543 memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
532 value += event_len; 544 value += event_len;
@@ -537,4 +549,85 @@ iwe_stream_add_value(char * event, /* Event in the stream */
537 return value; 549 return value;
538} 550}
539 551
552/*------------------------------------------------------------------*/
553/*
554 * Wrapper to add an Wireless Event to a stream of events.
555 * Same as above, with explicit error check...
556 */
557static inline char *
558iwe_stream_check_add_event(char * stream, /* Stream of events */
559 char * ends, /* End of stream */
560 struct iw_event *iwe, /* Payload */
561 int event_len, /* Size of payload */
562 int * perr) /* Error report */
563{
564 /* Check if it's possible, set error if not */
565 if(likely((stream + event_len) < ends)) {
566 iwe->len = event_len;
567 memcpy(stream, (char *) iwe, event_len);
568 stream += event_len;
569 } else
570 *perr = -E2BIG;
571 return stream;
572}
573
574/*------------------------------------------------------------------*/
575/*
576 * Wrapper to add an short Wireless Event containing a pointer to a
577 * stream of events.
578 * Same as above, with explicit error check...
579 */
580static inline char *
581iwe_stream_check_add_point(char * stream, /* Stream of events */
582 char * ends, /* End of stream */
583 struct iw_event *iwe, /* Payload length + flags */
584 char * extra, /* More payload */
585 int * perr) /* Error report */
586{
587 int event_len = IW_EV_POINT_LEN + iwe->u.data.length;
588 /* Check if it's possible */
589 if(likely((stream + event_len) < ends)) {
590 iwe->len = event_len;
591 memcpy(stream, (char *) iwe, IW_EV_LCP_LEN);
592 memcpy(stream + IW_EV_LCP_LEN,
593 ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
594 IW_EV_POINT_LEN - IW_EV_LCP_LEN);
595 memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length);
596 stream += event_len;
597 } else
598 *perr = -E2BIG;
599 return stream;
600}
601
602/*------------------------------------------------------------------*/
603/*
604 * Wrapper to add a value to a Wireless Event in a stream of events.
605 * Be careful, this one is tricky to use properly :
606 * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
607 * Same as above, with explicit error check...
608 */
609static inline char *
610iwe_stream_check_add_value(char * event, /* Event in the stream */
611 char * value, /* Value in event */
612 char * ends, /* End of stream */
613 struct iw_event *iwe, /* Payload */
614 int event_len, /* Size of payload */
615 int * perr) /* Error report */
616{
617 /* Don't duplicate LCP */
618 event_len -= IW_EV_LCP_LEN;
619
620 /* Check if it's possible */
621 if(likely((value + event_len) < ends)) {
622 /* Add new value */
623 memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len);
624 value += event_len;
625 /* Patch LCP */
626 iwe->len = value - event;
627 memcpy(event, (char *) iwe, IW_EV_LCP_LEN);
628 } else
629 *perr = -E2BIG;
630 return value;
631}
632
540#endif /* _IW_HANDLER_H */ 633#endif /* _IW_HANDLER_H */
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 5caae2399f3a..d17f1583ea3e 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -58,6 +58,13 @@
58 * o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus 58 * o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus
59 * Based on patch from Pavel Roskin <proski@gnu.org> : 59 * Based on patch from Pavel Roskin <proski@gnu.org> :
60 * o Fix kernel data leak to user space in private handler handling 60 * o Fix kernel data leak to user space in private handler handling
61 *
62 * v7 - 18.3.05 - Jean II
63 * o Remove (struct iw_point *)->pointer from events and streams
64 * o Remove spy_offset from struct iw_handler_def
65 * o Start deprecating dev->get_wireless_stats, output a warning
66 * o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless
67 * o Don't loose INVALID/DBM flags when clearing UPDATED flags (iwstats)
61 */ 68 */
62 69
63/***************************** INCLUDES *****************************/ 70/***************************** INCLUDES *****************************/
@@ -446,10 +453,14 @@ static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
446 (dev->wireless_handlers->get_wireless_stats != NULL)) 453 (dev->wireless_handlers->get_wireless_stats != NULL))
447 return dev->wireless_handlers->get_wireless_stats(dev); 454 return dev->wireless_handlers->get_wireless_stats(dev);
448 455
449 /* Old location, will be phased out in next WE */ 456 /* Old location, field to be removed in next WE */
450 return (dev->get_wireless_stats ? 457 if(dev->get_wireless_stats) {
451 dev->get_wireless_stats(dev) : 458 printk(KERN_DEBUG "%s (WE) : Driver using old /proc/net/wireless support, please fix driver !\n",
452 (struct iw_statistics *) NULL); 459 dev->name);
460 return dev->get_wireless_stats(dev);
461 }
462 /* Not found */
463 return (struct iw_statistics *) NULL;
453} 464}
454 465
455/* ---------------------------------------------------------------- */ 466/* ---------------------------------------------------------------- */
@@ -541,16 +552,18 @@ static __inline__ void wireless_seq_printf_stats(struct seq_file *seq,
541 dev->name, stats->status, stats->qual.qual, 552 dev->name, stats->status, stats->qual.qual,
542 stats->qual.updated & IW_QUAL_QUAL_UPDATED 553 stats->qual.updated & IW_QUAL_QUAL_UPDATED
543 ? '.' : ' ', 554 ? '.' : ' ',
544 ((__u8) stats->qual.level), 555 ((__s32) stats->qual.level) -
556 ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
545 stats->qual.updated & IW_QUAL_LEVEL_UPDATED 557 stats->qual.updated & IW_QUAL_LEVEL_UPDATED
546 ? '.' : ' ', 558 ? '.' : ' ',
547 ((__u8) stats->qual.noise), 559 ((__s32) stats->qual.noise) -
560 ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
548 stats->qual.updated & IW_QUAL_NOISE_UPDATED 561 stats->qual.updated & IW_QUAL_NOISE_UPDATED
549 ? '.' : ' ', 562 ? '.' : ' ',
550 stats->discard.nwid, stats->discard.code, 563 stats->discard.nwid, stats->discard.code,
551 stats->discard.fragment, stats->discard.retries, 564 stats->discard.fragment, stats->discard.retries,
552 stats->discard.misc, stats->miss.beacon); 565 stats->discard.misc, stats->miss.beacon);
553 stats->qual.updated = 0; 566 stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
554 } 567 }
555} 568}
556 569
@@ -593,6 +606,7 @@ static struct file_operations wireless_seq_fops = {
593 606
594int __init wireless_proc_init(void) 607int __init wireless_proc_init(void)
595{ 608{
609 /* Create /proc/net/wireless entry */
596 if (!proc_net_fops_create("wireless", S_IRUGO, &wireless_seq_fops)) 610 if (!proc_net_fops_create("wireless", S_IRUGO, &wireless_seq_fops))
597 return -ENOMEM; 611 return -ENOMEM;
598 612
@@ -627,9 +641,9 @@ static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
627 sizeof(struct iw_statistics))) 641 sizeof(struct iw_statistics)))
628 return -EFAULT; 642 return -EFAULT;
629 643
630 /* Check if we need to clear the update flag */ 644 /* Check if we need to clear the updated flag */
631 if(wrq->u.data.flags != 0) 645 if(wrq->u.data.flags != 0)
632 stats->qual.updated = 0; 646 stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
633 return 0; 647 return 0;
634 } else 648 } else
635 return -EOPNOTSUPP; 649 return -EOPNOTSUPP;
@@ -1161,10 +1175,11 @@ void wireless_send_event(struct net_device * dev,
1161 struct iw_event *event; /* Mallocated whole event */ 1175 struct iw_event *event; /* Mallocated whole event */
1162 int event_len; /* Its size */ 1176 int event_len; /* Its size */
1163 int hdr_len; /* Size of the event header */ 1177 int hdr_len; /* Size of the event header */
1178 int wrqu_off = 0; /* Offset in wrqu */
1164 /* Don't "optimise" the following variable, it will crash */ 1179 /* Don't "optimise" the following variable, it will crash */
1165 unsigned cmd_index; /* *MUST* be unsigned */ 1180 unsigned cmd_index; /* *MUST* be unsigned */
1166 1181
1167 /* Get the description of the IOCTL */ 1182 /* Get the description of the Event */
1168 if(cmd <= SIOCIWLAST) { 1183 if(cmd <= SIOCIWLAST) {
1169 cmd_index = cmd - SIOCIWFIRST; 1184 cmd_index = cmd - SIOCIWFIRST;
1170 if(cmd_index < standard_ioctl_num) 1185 if(cmd_index < standard_ioctl_num)
@@ -1207,6 +1222,8 @@ void wireless_send_event(struct net_device * dev,
1207 /* Calculate extra_len - extra is NULL for restricted events */ 1222 /* Calculate extra_len - extra is NULL for restricted events */
1208 if(extra != NULL) 1223 if(extra != NULL)
1209 extra_len = wrqu->data.length * descr->token_size; 1224 extra_len = wrqu->data.length * descr->token_size;
1225 /* Always at an offset in wrqu */
1226 wrqu_off = IW_EV_POINT_OFF;
1210#ifdef WE_EVENT_DEBUG 1227#ifdef WE_EVENT_DEBUG
1211 printk(KERN_DEBUG "%s (WE) : Event 0x%04X, tokens %d, extra_len %d\n", dev->name, cmd, wrqu->data.length, extra_len); 1228 printk(KERN_DEBUG "%s (WE) : Event 0x%04X, tokens %d, extra_len %d\n", dev->name, cmd, wrqu->data.length, extra_len);
1212#endif /* WE_EVENT_DEBUG */ 1229#endif /* WE_EVENT_DEBUG */
@@ -1217,7 +1234,7 @@ void wireless_send_event(struct net_device * dev,
1217 event_len = hdr_len + extra_len; 1234 event_len = hdr_len + extra_len;
1218 1235
1219#ifdef WE_EVENT_DEBUG 1236#ifdef WE_EVENT_DEBUG
1220 printk(KERN_DEBUG "%s (WE) : Event 0x%04X, hdr_len %d, event_len %d\n", dev->name, cmd, hdr_len, event_len); 1237 printk(KERN_DEBUG "%s (WE) : Event 0x%04X, hdr_len %d, wrqu_off %d, event_len %d\n", dev->name, cmd, hdr_len, wrqu_off, event_len);
1221#endif /* WE_EVENT_DEBUG */ 1238#endif /* WE_EVENT_DEBUG */
1222 1239
1223 /* Create temporary buffer to hold the event */ 1240 /* Create temporary buffer to hold the event */
@@ -1228,7 +1245,7 @@ void wireless_send_event(struct net_device * dev,
1228 /* Fill event */ 1245 /* Fill event */
1229 event->len = event_len; 1246 event->len = event_len;
1230 event->cmd = cmd; 1247 event->cmd = cmd;
1231 memcpy(&event->u, wrqu, hdr_len - IW_EV_LCP_LEN); 1248 memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
1232 if(extra != NULL) 1249 if(extra != NULL)
1233 memcpy(((char *) event) + hdr_len, extra, extra_len); 1250 memcpy(((char *) event) + hdr_len, extra, extra_len);
1234 1251
@@ -1249,7 +1266,7 @@ void wireless_send_event(struct net_device * dev,
1249 * Now, the driver can delegate this task to Wireless Extensions. 1266 * Now, the driver can delegate this task to Wireless Extensions.
1250 * It needs to use those standard spy iw_handler in struct iw_handler_def, 1267 * It needs to use those standard spy iw_handler in struct iw_handler_def,
1251 * push data to us via wireless_spy_update() and include struct iw_spy_data 1268 * push data to us via wireless_spy_update() and include struct iw_spy_data
1252 * in its private part (and advertise it in iw_handler_def->spy_offset). 1269 * in its private part (and export it in net_device->wireless_data->spy_data).
1253 * One of the main advantage of centralising spy support here is that 1270 * One of the main advantage of centralising spy support here is that
1254 * it becomes much easier to improve and extend it without having to touch 1271 * it becomes much easier to improve and extend it without having to touch
1255 * the drivers. One example is the addition of the Spy-Threshold events. 1272 * the drivers. One example is the addition of the Spy-Threshold events.
@@ -1266,10 +1283,7 @@ static inline struct iw_spy_data * get_spydata(struct net_device *dev)
1266 /* This is the new way */ 1283 /* This is the new way */
1267 if(dev->wireless_data) 1284 if(dev->wireless_data)
1268 return(dev->wireless_data->spy_data); 1285 return(dev->wireless_data->spy_data);
1269 1286 return NULL;
1270 /* This is the old way. Doesn't work for multi-headed drivers.
1271 * It will be removed in the next version of WE. */
1272 return (dev->priv + dev->wireless_handlers->spy_offset);
1273} 1287}
1274 1288
1275/*------------------------------------------------------------------*/ 1289/*------------------------------------------------------------------*/
@@ -1284,10 +1298,6 @@ int iw_handler_set_spy(struct net_device * dev,
1284 struct iw_spy_data * spydata = get_spydata(dev); 1298 struct iw_spy_data * spydata = get_spydata(dev);
1285 struct sockaddr * address = (struct sockaddr *) extra; 1299 struct sockaddr * address = (struct sockaddr *) extra;
1286 1300
1287 if(!dev->wireless_data)
1288 /* Help user know that driver needs updating */
1289 printk(KERN_DEBUG "%s (WE) : Driver using old/buggy spy support, please fix driver !\n",
1290 dev->name);
1291 /* Make sure driver is not buggy or using the old API */ 1301 /* Make sure driver is not buggy or using the old API */
1292 if(!spydata) 1302 if(!spydata)
1293 return -EOPNOTSUPP; 1303 return -EOPNOTSUPP;
@@ -1318,7 +1328,7 @@ int iw_handler_set_spy(struct net_device * dev,
1318 sizeof(struct iw_quality) * IW_MAX_SPY); 1328 sizeof(struct iw_quality) * IW_MAX_SPY);
1319 1329
1320#ifdef WE_SPY_DEBUG 1330#ifdef WE_SPY_DEBUG
1321 printk(KERN_DEBUG "iw_handler_set_spy() : offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length); 1331 printk(KERN_DEBUG "iw_handler_set_spy() : wireless_data %p, spydata %p, num %d\n", dev->wireless_data, spydata, wrqu->data.length);
1322 for (i = 0; i < wrqu->data.length; i++) 1332 for (i = 0; i < wrqu->data.length; i++)
1323 printk(KERN_DEBUG 1333 printk(KERN_DEBUG
1324 "%02X:%02X:%02X:%02X:%02X:%02X \n", 1334 "%02X:%02X:%02X:%02X:%02X:%02X \n",
@@ -1371,7 +1381,7 @@ int iw_handler_get_spy(struct net_device * dev,
1371 sizeof(struct iw_quality) * spydata->spy_number); 1381 sizeof(struct iw_quality) * spydata->spy_number);
1372 /* Reset updated flags. */ 1382 /* Reset updated flags. */
1373 for(i = 0; i < spydata->spy_number; i++) 1383 for(i = 0; i < spydata->spy_number; i++)
1374 spydata->spy_stat[i].updated = 0; 1384 spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED;
1375 return 0; 1385 return 0;
1376} 1386}
1377 1387
@@ -1486,7 +1496,7 @@ void wireless_spy_update(struct net_device * dev,
1486 return; 1496 return;
1487 1497
1488#ifdef WE_SPY_DEBUG 1498#ifdef WE_SPY_DEBUG
1489 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]); 1499 printk(KERN_DEBUG "wireless_spy_update() : wireless_data %p, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_data, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
1490#endif /* WE_SPY_DEBUG */ 1500#endif /* WE_SPY_DEBUG */
1491 1501
1492 /* Update all records that match */ 1502 /* Update all records that match */