diff options
-rw-r--r-- | include/linux/wireless.h | 47 | ||||
-rw-r--r-- | include/net/iw_handler.h | 123 | ||||
-rw-r--r-- | net/core/wireless.c | 58 |
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 */ | ||
415 | struct ieee80211_device; | ||
416 | /* The struct */ | ||
410 | struct iw_public_data { | 417 | struct 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 { | |||
424 | extern int dev_get_wireless_info(char * buffer, char **start, off_t offset, | 433 | extern 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 */ |
428 | extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); | 437 | extern 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 */ | |||
495 | static inline char * | 504 | static inline char * |
496 | iwe_stream_add_point(char * stream, /* Stream of events */ | 505 | iwe_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 | */ | ||
557 | static inline char * | ||
558 | iwe_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 | */ | ||
580 | static inline char * | ||
581 | iwe_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 | */ | ||
609 | static inline char * | ||
610 | iwe_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 | ||
594 | int __init wireless_proc_init(void) | 607 | int __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 */ |