aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */