1 /* src/p80211/p80211wext.c
3 * Glue code to make linux-wlan-ng a happy wireless extension camper.
5 * original author: Reyk Floeter <reyk@synack.de>
6 * Completely re-written by Solomon Peachy <solomon@linux-wlan.com>
8 * Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved.
9 * --------------------------------------------------------------------
13 * The contents of this file are subject to the Mozilla Public
14 * License Version 1.1 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.mozilla.org/MPL/
18 * Software distributed under the License is distributed on an "AS
19 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
20 * implied. See the License for the specific language governing
21 * rights and limitations under the License.
23 * Alternatively, the contents of this file may be used under the
24 * terms of the GNU Public License version 2 (the "GPL"), in which
25 * case the provisions of the GPL are applicable instead of the
26 * above. If you wish to allow the use of your version of this file
27 * only under the terms of the GPL and not to allow others to use
28 * your version of this file under the MPL, indicate your decision
29 * by deleting the provisions above and replace them with the notice
30 * and other provisions required by the GPL. If you do not delete
31 * the provisions above, a recipient may use your version of this
32 * file under either the MPL or the GPL.
34 * --------------------------------------------------------------------
37 /*================================================================*/
42 #include <linux/kernel.h>
43 #include <linux/sched.h>
44 #include <linux/types.h>
45 #include <linux/slab.h>
46 #include <linux/netdevice.h>
47 #include <linux/etherdevice.h>
48 #include <linux/wireless.h>
49 #include <net/iw_handler.h>
50 #include <linux/if_arp.h>
51 #include <asm/bitops.h>
52 #include <asm/uaccess.h>
53 #include <asm/byteorder.h>
55 /*================================================================*/
56 /* Project Includes */
58 #include "wlan_compat.h"
60 #include "p80211types.h"
61 #include "p80211hdr.h"
62 #include "p80211conv.h"
63 #include "p80211mgmt.h"
64 #include "p80211msg.h"
65 #include "p80211metastruct.h"
66 #include "p80211metadef.h"
67 #include "p80211netdev.h"
68 #include "p80211ioctl.h"
69 #include "p80211req.h"
71 static int p80211wext_giwrate(netdevice_t *dev,
72 struct iw_request_info *info,
73 struct iw_param *rrq, char *extra);
74 static int p80211wext_giwessid(netdevice_t *dev,
75 struct iw_request_info *info,
76 struct iw_point *data, char *essid);
78 static u8 p80211_mhz_to_channel(u16 mhz)
81 return ((mhz - 5000) / 5);
88 return ((mhz - 2407) / 5);
94 static u16 p80211_channel_to_mhz(u8 ch, int dot11a)
105 return (5000 + (5 * ch));
113 if ((ch < 14) && (ch > 0)) {
114 return (2407 + (5 * ch));
120 /* taken from orinoco.c ;-) */
121 static const long p80211wext_channel_freq[] = {
122 2412, 2417, 2422, 2427, 2432, 2437, 2442,
123 2447, 2452, 2457, 2462, 2467, 2472, 2484
125 #define NUM_CHANNELS ARRAY_SIZE(p80211wext_channel_freq)
127 /* steal a spare bit to store the shared/opensystems state. should default to open if not set */
128 #define HOSTWEP_SHAREDKEY BIT3
131 /** function declarations =============== */
133 static int qual_as_percent(int snr ) {
144 static int p80211wext_dorequest(wlandevice_t *wlandev, u32 did, u32 data)
146 p80211msg_dot11req_mibset_t msg;
147 p80211item_uint32_t mibitem;
152 msg.msgcode = DIDmsg_dot11req_mibset;
155 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
156 result = p80211req_dorequest(wlandev, (u8*)&msg);
162 static int p80211wext_autojoin(wlandevice_t *wlandev)
164 p80211msg_lnxreq_autojoin_t msg;
165 struct iw_point data;
166 char ssid[IW_ESSID_MAX_SIZE];
174 result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid);
181 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
182 msg.authtype.data = P80211ENUM_authalg_sharedkey;
184 msg.authtype.data = P80211ENUM_authalg_opensystem;
186 msg.msgcode = DIDmsg_lnxreq_autojoin;
188 /* Trim the last '\0' to fit the SSID format */
190 if (data.length && ssid[data.length-1] == '\0') {
191 data.length = data.length - 1;
194 memcpy(msg.ssid.data.data, ssid, data.length);
195 msg.ssid.data.len = data.length;
197 result = p80211req_dorequest(wlandev, (u8*)&msg);
211 /* called by /proc/net/wireless */
212 struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev)
214 p80211msg_lnxreq_commsquality_t quality;
215 wlandevice_t *wlandev = dev->ml_priv;
216 struct iw_statistics* wstats = &wlandev->wstats;
221 if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) )
224 /* XXX Only valid in station mode */
227 /* build request message */
228 quality.msgcode = DIDmsg_lnxreq_commsquality;
229 quality.dbm.data = P80211ENUM_truth_true;
230 quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
232 /* send message to nsd */
233 if ( wlandev->mlmerequest == NULL )
236 retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality);
238 wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
239 wstats->qual.level = quality.level.data; /* instant signal level */
240 wstats->qual.noise = quality.noise.data; /* instant noise level */
242 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
243 wstats->discard.code = wlandev->rx.decrypt_err;
244 wstats->discard.nwid = 0;
245 wstats->discard.misc = 0;
247 wstats->discard.fragment = 0; // incomplete fragments
248 wstats->discard.retries = 0; // tx retries.
249 wstats->miss.beacon = 0;
256 static int p80211wext_giwname(netdevice_t *dev,
257 struct iw_request_info *info,
258 char *name, char *extra)
260 struct iw_param rate;
266 result = p80211wext_giwrate(dev, NULL, &rate, NULL);
273 switch (rate.value) {
276 strcpy(name, "IEEE 802.11-DS");
280 strcpy(name, "IEEE 802.11-b");
288 static int p80211wext_giwfreq(netdevice_t *dev,
289 struct iw_request_info *info,
290 struct iw_freq *freq, char *extra)
292 wlandevice_t *wlandev = dev->ml_priv;
293 p80211item_uint32_t mibitem;
294 p80211msg_dot11req_mibset_t msg;
300 msg.msgcode = DIDmsg_dot11req_mibget;
301 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
302 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
303 result = p80211req_dorequest(wlandev, (u8*)&msg);
310 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
312 if (mibitem.data > NUM_CHANNELS) {
317 /* convert into frequency instead of a channel */
319 freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000;
326 static int p80211wext_siwfreq(netdevice_t *dev,
327 struct iw_request_info *info,
328 struct iw_freq *freq, char *extra)
330 wlandevice_t *wlandev = dev->ml_priv;
331 p80211item_uint32_t mibitem;
332 p80211msg_dot11req_mibset_t msg;
338 if (!wlan_wext_write) {
343 msg.msgcode = DIDmsg_dot11req_mibset;
344 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
345 mibitem.status = P80211ENUM_msgitem_status_data_ok;
347 if ( (freq->e == 0) && (freq->m <= 1000) )
348 mibitem.data = freq->m;
350 mibitem.data = p80211_mhz_to_channel(freq->m);
352 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
353 result = p80211req_dorequest(wlandev, (u8*)&msg);
365 static int p80211wext_giwmode(netdevice_t *dev,
366 struct iw_request_info *info,
367 __u32 *mode, char *extra)
369 wlandevice_t *wlandev = dev->ml_priv;
373 switch (wlandev->macmode) {
374 case WLAN_MACMODE_IBSS_STA:
375 *mode = IW_MODE_ADHOC;
377 case WLAN_MACMODE_ESS_STA:
378 *mode = IW_MODE_INFRA;
380 case WLAN_MACMODE_ESS_AP:
381 *mode = IW_MODE_MASTER;
385 *mode = IW_MODE_AUTO;
392 static int p80211wext_siwmode(netdevice_t *dev,
393 struct iw_request_info *info,
394 __u32 *mode, char *extra)
396 wlandevice_t *wlandev = dev->ml_priv;
397 p80211item_uint32_t mibitem;
398 p80211msg_dot11req_mibset_t msg;
404 if (!wlan_wext_write) {
409 if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
410 *mode != IW_MODE_MASTER) {
415 /* Operation mode is the same with current mode */
416 if (*mode == wlandev->macmode)
421 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
424 wlandev->macmode = WLAN_MACMODE_ESS_STA;
427 wlandev->macmode = WLAN_MACMODE_ESS_AP;
431 WLAN_LOG_INFO("Operation mode: %d not support\n", *mode);
435 /* Set Operation mode to the PORT TYPE RID */
436 msg.msgcode = DIDmsg_dot11req_mibset;
437 mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
438 mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
439 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
440 result = p80211req_dorequest(wlandev, (u8*)&msg);
452 static int p80211wext_giwrange(netdevice_t *dev,
453 struct iw_request_info *info,
454 struct iw_point *data, char *extra)
456 struct iw_range *range = (struct iw_range *) extra;
461 // for backward compatability set size & zero everything we don't understand
462 data->length = sizeof(*range);
463 memset(range,0,sizeof(*range));
465 range->txpower_capa = IW_TXPOW_DBM;
466 // XXX what about min/max_pmp, min/max_pmt, etc.
468 range->we_version_compiled = WIRELESS_EXT;
469 range->we_version_source = 13;
471 range->retry_capa = IW_RETRY_LIMIT;
472 range->retry_flags = IW_RETRY_LIMIT;
473 range->min_retry = 0;
474 range->max_retry = 255;
476 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | //mode/freq/ssid
477 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
478 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
479 range->event_capa[1] = IW_EVENT_CAPA_K_1; //encode
480 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
481 IW_EVENT_CAPA_MASK(IWEVCUSTOM) );
483 range->num_channels = NUM_CHANNELS;
485 /* XXX need to filter against the regulatory domain &| active set */
487 for (i = 0; i < NUM_CHANNELS ; i++) {
488 range->freq[val].i = i + 1;
489 range->freq[val].m = p80211wext_channel_freq[i] * 100000;
490 range->freq[val].e = 1;
494 range->num_frequency = val;
496 /* Max of /proc/net/wireless */
497 range->max_qual.qual = 100;
498 range->max_qual.level = 0;
499 range->max_qual.noise = 0;
500 range->sensitivity = 3;
501 // XXX these need to be nsd-specific!
504 range->max_rts = 2347;
505 range->min_frag = 256;
506 range->max_frag = 2346;
508 range->max_encoding_tokens = NUM_WEPKEYS;
509 range->num_encoding_sizes = 2;
510 range->encoding_size[0] = 5;
511 range->encoding_size[1] = 13;
513 // XXX what about num_bitrates/throughput?
514 range->num_bitrates = 0;
516 /* estimated max throughput */
517 // XXX need to cap it if we're running at ~2Mbps..
518 range->throughput = 5500000;
524 static int p80211wext_giwap(netdevice_t *dev,
525 struct iw_request_info *info,
526 struct sockaddr *ap_addr, char *extra)
529 wlandevice_t *wlandev = dev->ml_priv;
533 memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
534 ap_addr->sa_family = ARPHRD_ETHER;
540 static int p80211wext_giwencode(netdevice_t *dev,
541 struct iw_request_info *info,
542 struct iw_point *erq, char *key)
544 wlandevice_t *wlandev = dev->ml_priv;
550 i = (erq->flags & IW_ENCODE_INDEX) - 1;
553 if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
554 erq->flags |= IW_ENCODE_ENABLED;
556 erq->flags |= IW_ENCODE_DISABLED;
558 if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
559 erq->flags |= IW_ENCODE_RESTRICTED;
561 erq->flags |= IW_ENCODE_OPEN;
563 i = (erq->flags & IW_ENCODE_INDEX) - 1;
566 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
568 if ((i < 0) || (i >= NUM_WEPKEYS)) {
575 /* copy the key from the driver cache as the keys are read-only MIBs */
576 erq->length = wlandev->wep_keylens[i];
577 memcpy(key, wlandev->wep_keys[i], erq->length);
584 static int p80211wext_siwencode(netdevice_t *dev,
585 struct iw_request_info *info,
586 struct iw_point *erq, char *key)
588 wlandevice_t *wlandev = dev->ml_priv;
589 p80211msg_dot11req_mibset_t msg;
590 p80211item_pstr32_t pstr;
597 if (!wlan_wext_write) {
602 /* Check the Key index first. */
603 if((i = (erq->flags & IW_ENCODE_INDEX))) {
605 if ((i < 1) || (i > NUM_WEPKEYS)) {
612 /* Set current key number only if no keys are given */
613 if (erq->flags & IW_ENCODE_NOKEY) {
614 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i);
623 // Use defaultkey if no Key Index
624 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
627 /* Check if there is no key information in the iwconfig request */
628 if((erq->flags & IW_ENCODE_NOKEY) == 0 ) {
630 /*------------------------------------------------------------
631 * If there is WEP Key for setting, check the Key Information
632 * and then set it to the firmware.
633 -------------------------------------------------------------*/
635 if (erq->length > 0) {
637 /* copy the key from the driver cache as the keys are read-only MIBs */
638 wlandev->wep_keylens[i] = erq->length;
639 memcpy(wlandev->wep_keys[i], key, erq->length);
641 /* Prepare data struture for p80211req_dorequest. */
642 memcpy(pstr.data.data, key, erq->length);
643 pstr.data.len = erq->length;
648 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
652 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
656 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
660 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
668 msg.msgcode = DIDmsg_dot11req_mibset;
669 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
670 result = p80211req_dorequest(wlandev, (u8*)&msg);
680 /* Check the PrivacyInvoked flag */
681 if (erq->flags & IW_ENCODE_DISABLED) {
682 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
684 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
692 /* The security mode may be open or restricted, and its meaning
693 depends on the card used. With most cards, in open mode no
694 authentication is used and the card may also accept non-
695 encrypted sessions, whereas in restricted mode only encrypted
696 sessions are accepted and the card will use authentication if
699 if (erq->flags & IW_ENCODE_RESTRICTED) {
700 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
702 else if (erq->flags & IW_ENCODE_OPEN) {
703 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
717 static int p80211wext_giwessid(netdevice_t *dev,
718 struct iw_request_info *info,
719 struct iw_point *data, char *essid)
721 wlandevice_t *wlandev = dev->ml_priv;
725 if (wlandev->ssid.len) {
726 data->length = wlandev->ssid.len;
728 memcpy(essid, wlandev->ssid.data, data->length);
729 essid[data->length] = 0;
730 #if (WIRELESS_EXT < 21)
734 memset(essid, 0, sizeof(wlandev->ssid.data));
743 static int p80211wext_siwessid(netdevice_t *dev,
744 struct iw_request_info *info,
745 struct iw_point *data, char *essid)
747 wlandevice_t *wlandev = dev->ml_priv;
748 p80211msg_lnxreq_autojoin_t msg;
752 int length = data->length;
756 if (!wlan_wext_write) {
762 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
763 msg.authtype.data = P80211ENUM_authalg_sharedkey;
765 msg.authtype.data = P80211ENUM_authalg_opensystem;
767 msg.msgcode = DIDmsg_lnxreq_autojoin;
769 #if (WIRELESS_EXT < 21)
770 if (length) length--;
773 /* Trim the last '\0' to fit the SSID format */
775 if (length && essid[length-1] == '\0') {
779 memcpy(msg.ssid.data.data, essid, length);
780 msg.ssid.data.len = length;
782 WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid);
783 result = p80211req_dorequest(wlandev, (u8*)&msg);
784 WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result);
797 static int p80211wext_siwcommit(netdevice_t *dev,
798 struct iw_request_info *info,
799 struct iw_point *data, char *essid)
801 wlandevice_t *wlandev = dev->ml_priv;
806 if (!wlan_wext_write) {
812 err = p80211wext_autojoin(wlandev);
820 static int p80211wext_giwrate(netdevice_t *dev,
821 struct iw_request_info *info,
822 struct iw_param *rrq, char *extra)
824 wlandevice_t *wlandev = dev->ml_priv;
825 p80211item_uint32_t mibitem;
826 p80211msg_dot11req_mibset_t msg;
832 msg.msgcode = DIDmsg_dot11req_mibget;
833 mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
834 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
835 result = p80211req_dorequest(wlandev, (u8*)&msg);
842 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
844 rrq->fixed = 0; /* can it change? */
848 #define HFA384x_RATEBIT_1 ((u16)1)
849 #define HFA384x_RATEBIT_2 ((u16)2)
850 #define HFA384x_RATEBIT_5dot5 ((u16)4)
851 #define HFA384x_RATEBIT_11 ((u16)8)
853 switch (mibitem.data) {
854 case HFA384x_RATEBIT_1:
855 rrq->value = 1000000;
857 case HFA384x_RATEBIT_2:
858 rrq->value = 2000000;
860 case HFA384x_RATEBIT_5dot5:
861 rrq->value = 5500000;
863 case HFA384x_RATEBIT_11:
864 rrq->value = 11000000;
874 static int p80211wext_giwrts(netdevice_t *dev,
875 struct iw_request_info *info,
876 struct iw_param *rts, char *extra)
878 wlandevice_t *wlandev = dev->ml_priv;
879 p80211item_uint32_t mibitem;
880 p80211msg_dot11req_mibset_t msg;
886 msg.msgcode = DIDmsg_dot11req_mibget;
887 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
888 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
889 result = p80211req_dorequest(wlandev, (u8*)&msg);
896 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
898 rts->value = mibitem.data;
899 rts->disabled = (rts->value == 2347);
908 static int p80211wext_siwrts(netdevice_t *dev,
909 struct iw_request_info *info,
910 struct iw_param *rts, char *extra)
912 wlandevice_t *wlandev = dev->ml_priv;
913 p80211item_uint32_t mibitem;
914 p80211msg_dot11req_mibset_t msg;
920 if (!wlan_wext_write) {
925 msg.msgcode = DIDmsg_dot11req_mibget;
926 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
930 mibitem.data = rts->value;
932 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
933 result = p80211req_dorequest(wlandev, (u8*)&msg);
945 static int p80211wext_giwfrag(netdevice_t *dev,
946 struct iw_request_info *info,
947 struct iw_param *frag, char *extra)
949 wlandevice_t *wlandev = dev->ml_priv;
950 p80211item_uint32_t mibitem;
951 p80211msg_dot11req_mibset_t msg;
957 msg.msgcode = DIDmsg_dot11req_mibget;
958 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
959 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
960 result = p80211req_dorequest(wlandev, (u8*)&msg);
967 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
969 frag->value = mibitem.data;
970 frag->disabled = (frag->value == 2346);
978 static int p80211wext_siwfrag(netdevice_t *dev,
979 struct iw_request_info *info,
980 struct iw_param *frag, char *extra)
982 wlandevice_t *wlandev = dev->ml_priv;
983 p80211item_uint32_t mibitem;
984 p80211msg_dot11req_mibset_t msg;
990 if (!wlan_wext_write) {
995 msg.msgcode = DIDmsg_dot11req_mibset;
996 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
1001 mibitem.data = frag->value;
1003 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1004 result = p80211req_dorequest(wlandev, (u8*)&msg);
1016 #ifndef IW_RETRY_LONG
1017 #define IW_RETRY_LONG IW_RETRY_MAX
1020 #ifndef IW_RETRY_SHORT
1021 #define IW_RETRY_SHORT IW_RETRY_MIN
1024 static int p80211wext_giwretry(netdevice_t *dev,
1025 struct iw_request_info *info,
1026 struct iw_param *rrq, char *extra)
1028 wlandevice_t *wlandev = dev->ml_priv;
1029 p80211item_uint32_t mibitem;
1030 p80211msg_dot11req_mibset_t msg;
1033 u16 shortretry, longretry, lifetime;
1037 msg.msgcode = DIDmsg_dot11req_mibget;
1038 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1040 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1041 result = p80211req_dorequest(wlandev, (u8*)&msg);
1048 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1050 shortretry = mibitem.data;
1052 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1054 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1055 result = p80211req_dorequest(wlandev, (u8*)&msg);
1062 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1064 longretry = mibitem.data;
1066 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1068 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1069 result = p80211req_dorequest(wlandev, (u8*)&msg);
1076 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1078 lifetime = mibitem.data;
1082 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1083 rrq->flags = IW_RETRY_LIFETIME;
1084 rrq->value = lifetime * 1024;
1086 if (rrq->flags & IW_RETRY_LONG) {
1087 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1088 rrq->value = longretry;
1090 rrq->flags = IW_RETRY_LIMIT;
1091 rrq->value = shortretry;
1092 if (shortretry != longretry)
1093 rrq->flags |= IW_RETRY_SHORT;
1103 static int p80211wext_siwretry(netdevice_t *dev,
1104 struct iw_request_info *info,
1105 struct iw_param *rrq, char *extra)
1107 wlandevice_t *wlandev = dev->ml_priv;
1108 p80211item_uint32_t mibitem;
1109 p80211msg_dot11req_mibset_t msg;
1115 if (!wlan_wext_write) {
1116 err = (-EOPNOTSUPP);
1120 if (rrq->disabled) {
1125 msg.msgcode = DIDmsg_dot11req_mibset;
1127 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1128 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1129 mibitem.data = rrq->value /= 1024;
1131 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1132 result = p80211req_dorequest(wlandev, (u8*)&msg);
1139 if (rrq->flags & IW_RETRY_LONG) {
1140 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1141 mibitem.data = rrq->value;
1143 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1144 result = p80211req_dorequest(wlandev, (u8*)&msg);
1152 if (rrq->flags & IW_RETRY_SHORT) {
1153 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1154 mibitem.data = rrq->value;
1156 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1157 result = p80211req_dorequest(wlandev, (u8*)&msg);
1172 static int p80211wext_siwtxpow(netdevice_t *dev,
1173 struct iw_request_info *info,
1174 struct iw_param *rrq, char *extra)
1176 wlandevice_t *wlandev = dev->ml_priv;
1177 p80211item_uint32_t mibitem;
1178 p80211msg_dot11req_mibset_t msg;
1184 if (!wlan_wext_write) {
1185 err = (-EOPNOTSUPP);
1189 msg.msgcode = DIDmsg_dot11req_mibset;
1190 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1191 if (rrq->fixed == 0)
1194 mibitem.data = rrq->value;
1195 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1196 result = p80211req_dorequest(wlandev, (u8*)&msg);
1208 static int p80211wext_giwtxpow(netdevice_t *dev,
1209 struct iw_request_info *info,
1210 struct iw_param *rrq, char *extra)
1212 wlandevice_t *wlandev = dev->ml_priv;
1213 p80211item_uint32_t mibitem;
1214 p80211msg_dot11req_mibset_t msg;
1220 msg.msgcode = DIDmsg_dot11req_mibget;
1221 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1223 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1224 result = p80211req_dorequest(wlandev, (u8*)&msg);
1231 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1233 // XXX handle OFF by setting disabled = 1;
1235 rrq->flags = 0; // IW_TXPOW_DBM;
1238 rrq->value = mibitem.data;
1245 static int p80211wext_siwspy(netdevice_t *dev,
1246 struct iw_request_info *info,
1247 struct iw_point *srq, char *extra)
1249 wlandevice_t *wlandev = dev->ml_priv;
1250 struct sockaddr address[IW_MAX_SPY];
1251 int number = srq->length;
1256 /* Copy the data from the input buffer */
1257 memcpy(address, extra, sizeof(struct sockaddr)*number);
1259 wlandev->spy_number = 0;
1263 /* extract the addresses */
1264 for (i = 0; i < number; i++) {
1266 memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN);
1270 memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
1272 /* set number of addresses */
1273 wlandev->spy_number = number;
1280 /* jkriegl: from orinoco, modified */
1281 static int p80211wext_giwspy(netdevice_t *dev,
1282 struct iw_request_info *info,
1283 struct iw_point *srq, char *extra)
1285 wlandevice_t *wlandev = dev->ml_priv;
1287 struct sockaddr address[IW_MAX_SPY];
1288 struct iw_quality spy_stat[IW_MAX_SPY];
1294 number = wlandev->spy_number;
1298 /* populate address and spy struct's */
1299 for (i = 0; i < number; i++) {
1300 memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN);
1301 address[i].sa_family = AF_UNIX;
1302 memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality));
1305 /* reset update flag */
1306 for (i=0; i < number; i++)
1307 wlandev->spy_stat[i].updated = 0;
1310 /* push stuff to user space */
1311 srq->length = number;
1312 memcpy(extra, address, sizeof(struct sockaddr)*number);
1313 memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number);
1319 static int prism2_result2err (int prism2_result)
1323 switch (prism2_result) {
1324 case P80211ENUM_resultcode_invalid_parameters:
1327 case P80211ENUM_resultcode_implementation_failure:
1330 case P80211ENUM_resultcode_not_supported:
1341 static int p80211wext_siwscan(netdevice_t *dev,
1342 struct iw_request_info *info,
1343 struct iw_point *srq, char *extra)
1345 wlandevice_t *wlandev = dev->ml_priv;
1346 p80211msg_dot11req_scan_t msg;
1353 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1354 WLAN_LOG_ERROR("Can't scan in AP mode\n");
1355 err = (-EOPNOTSUPP);
1359 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1360 msg.msgcode = DIDmsg_dot11req_scan;
1361 msg.bsstype.data = P80211ENUM_bsstype_any;
1363 memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t));
1364 msg.bssid.data.len = 6;
1366 msg.scantype.data = P80211ENUM_scantype_active;
1367 msg.probedelay.data = 0;
1369 for (i = 1; i <= 14; i++)
1370 msg.channellist.data.data[i-1] = i;
1371 msg.channellist.data.len = 14;
1373 msg.maxchanneltime.data = 250;
1374 msg.minchanneltime.data = 200;
1376 result = p80211req_dorequest(wlandev, (u8*)&msg);
1378 err = prism2_result2err (msg.resultcode.data);
1386 /* Helper to translate scan into Wireless Extensions scan results.
1387 * Inspired by the prism54 code, which was in turn inspired by the
1391 wext_translate_bss(struct iw_request_info *info, char *current_ev,
1392 char *end_buf, p80211msg_dot11req_scan_results_t *bss)
1394 struct iw_event iwe; /* Temporary buffer */
1396 /* The first entry must be the MAC address */
1397 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1398 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1399 iwe.cmd = SIOCGIWAP;
1400 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
1402 /* The following entries will be displayed in the same order we give them */
1405 if (bss->ssid.data.len > 0) {
1406 char essid[IW_ESSID_MAX_SIZE + 1];
1409 size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len);
1410 memset(&essid, 0, sizeof (essid));
1411 memcpy(&essid, bss->ssid.data.data, size);
1412 WLAN_LOG_DEBUG(1, " essid size = %d\n", size);
1413 iwe.u.data.length = size;
1414 iwe.u.data.flags = 1;
1415 iwe.cmd = SIOCGIWESSID;
1416 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]);
1417 WLAN_LOG_DEBUG(1, " essid size OK.\n");
1420 switch (bss->bsstype.data) {
1421 case P80211ENUM_bsstype_infrastructure:
1422 iwe.u.mode = IW_MODE_MASTER;
1425 case P80211ENUM_bsstype_independent:
1426 iwe.u.mode = IW_MODE_ADHOC;
1433 iwe.cmd = SIOCGIWMODE;
1435 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
1437 /* Encryption capability */
1438 if (bss->privacy.data == P80211ENUM_truth_true)
1439 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1441 iwe.u.data.flags = IW_ENCODE_DISABLED;
1442 iwe.u.data.length = 0;
1443 iwe.cmd = SIOCGIWENCODE;
1444 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1446 /* Add frequency. (short) bss->channel is the frequency in MHz */
1447 iwe.u.freq.m = bss->dschannel.data;
1449 iwe.cmd = SIOCGIWFREQ;
1450 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
1452 /* Add quality statistics */
1453 iwe.u.qual.level = bss->signal.data;
1454 iwe.u.qual.noise = bss->noise.data;
1455 /* do a simple SNR for quality */
1456 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1458 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
1464 static int p80211wext_giwscan(netdevice_t *dev,
1465 struct iw_request_info *info,
1466 struct iw_point *srq, char *extra)
1468 wlandevice_t *wlandev = dev->ml_priv;
1469 p80211msg_dot11req_scan_results_t msg;
1474 char *current_ev = extra;
1478 /* Since wireless tools doesn't really have a way of passing how
1479 * many scan results results there were back here, keep grabbing them
1483 memset(&msg, 0, sizeof(msg));
1484 msg.msgcode = DIDmsg_dot11req_scan_results;
1485 msg.bssindex.data = i;
1487 result = p80211req_dorequest(wlandev, (u8*)&msg);
1488 if ((result != 0) ||
1489 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1493 current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg);
1496 } while (i < IW_MAX_AP);
1498 srq->length = (current_ev - extra);
1499 srq->flags = 0; /* todo */
1501 if (result && !scan_good)
1502 err = prism2_result2err (msg.resultcode.data);
1508 /*****************************************************/
1509 //extra wireless extensions stuff to support NetworkManager (I hope)
1511 /* SIOCSIWENCODEEXT */
1512 static int p80211wext_set_encodeext(struct net_device *dev,
1513 struct iw_request_info *info,
1514 union iwreq_data *wrqu, char *extra)
1516 wlandevice_t *wlandev = dev->ml_priv;
1517 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1518 p80211msg_dot11req_mibset_t msg;
1519 p80211item_pstr32_t *pstr;
1522 struct iw_point *encoding = &wrqu->encoding;
1523 int idx = encoding->flags & IW_ENCODE_INDEX;
1525 WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1528 if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
1529 // set default key ? I'm not sure if this the the correct thing to do here
1532 if (idx < 1 || idx > NUM_WEPKEYS) {
1537 WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx);
1538 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx);
1544 if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) {
1545 if (!(ext->alg & IW_ENCODE_ALG_WEP)) {
1546 WLAN_LOG_DEBUG(1,"asked to set a non wep key :(");
1550 if (idx <1 || idx > NUM_WEPKEYS)
1555 WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx);
1556 wlandev->wep_keylens[idx] = ext->key_len;
1557 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1559 memset( &msg,0,sizeof(msg));
1560 pstr = (p80211item_pstr32_t*)&msg.mibattribute.data;
1561 memcpy(pstr->data.data, ext->key,ext->key_len);
1562 pstr->data.len = ext->key_len;
1565 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1568 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1571 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1574 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1579 msg.msgcode = DIDmsg_dot11req_mibset;
1580 result = p80211req_dorequest(wlandev,(u8*)&msg);
1581 WLAN_LOG_DEBUG(1,"result (%d)\n",result);
1586 /* SIOCGIWENCODEEXT */
1587 static int p80211wext_get_encodeext(struct net_device *dev,
1588 struct iw_request_info *info,
1589 union iwreq_data *wrqu, char *extra)
1592 wlandevice_t *wlandev = dev->ml_priv;
1593 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1595 struct iw_point *encoding = &wrqu->encoding;
1602 WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1605 max_len = encoding->length - sizeof(*ext);
1606 if ( max_len <= 0) {
1607 WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len);
1611 idx = encoding->flags & IW_ENCODE_INDEX;
1613 WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx);
1616 if (idx < 1 || idx > NUM_WEPKEYS ) {
1617 WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx);
1623 /* default key ? not sure what to do */
1624 /* will just use key[0] for now ! FIX ME */
1627 encoding->flags = idx + 1;
1628 memset(ext,0,sizeof(*ext));
1630 ext->alg = IW_ENCODE_ALG_WEP;
1631 ext->key_len = wlandev->wep_keylens[idx];
1632 memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len );
1634 encoding->flags |= IW_ENCODE_ENABLED;
1643 static int p80211_wext_set_iwauth (struct net_device *dev,
1644 struct iw_request_info *info,
1645 union iwreq_data *wrqu, char *extra)
1647 wlandevice_t *wlandev = dev->ml_priv;
1648 struct iw_param *param = &wrqu->param;
1651 WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1653 switch (param->flags & IW_AUTH_INDEX) {
1654 case IW_AUTH_DROP_UNENCRYPTED:
1655 WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value);
1657 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
1659 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
1662 case IW_AUTH_PRIVACY_INVOKED:
1663 WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value);
1665 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
1667 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
1671 case IW_AUTH_80211_AUTH_ALG:
1672 if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) {
1673 WLAN_LOG_DEBUG(1,"set open_system\n");
1674 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1675 } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) {
1676 WLAN_LOG_DEBUG(1,"set shared key\n");
1677 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1679 /* don't know what to do know :( */
1680 WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value);
1695 static int p80211_wext_get_iwauth (struct net_device *dev,
1696 struct iw_request_info *info,
1697 union iwreq_data *wrqu, char *extra)
1699 wlandevice_t *wlandev = dev->ml_priv;
1700 struct iw_param *param = &wrqu->param;
1703 WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1705 switch (param->flags & IW_AUTH_INDEX) {
1706 case IW_AUTH_DROP_UNENCRYPTED:
1707 param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0;
1710 case IW_AUTH_PRIVACY_INVOKED:
1711 param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0;
1714 case IW_AUTH_80211_AUTH_ALG:
1715 param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM;
1728 static iw_handler p80211wext_handlers[] = {
1729 (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
1730 (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
1731 (iw_handler) NULL, /* SIOCSIWNWID */
1732 (iw_handler) NULL, /* SIOCGIWNWID */
1733 (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
1734 (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
1735 (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
1736 (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
1737 (iw_handler) NULL, /* SIOCSIWSENS */
1738 (iw_handler) NULL, /* SIOCGIWSENS */
1739 (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */
1740 (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
1741 (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */
1742 (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */
1743 (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */
1744 (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */
1745 (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
1746 (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
1747 (iw_handler) NULL, /* -- hole -- */
1748 (iw_handler) NULL, /* -- hole -- */
1749 (iw_handler) NULL, /* SIOCSIWAP */
1750 (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
1751 (iw_handler) NULL, /* -- hole -- */
1752 (iw_handler) NULL, /* SIOCGIWAPLIST */
1753 (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
1754 (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
1755 (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
1756 (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
1757 (iw_handler) NULL, /* SIOCSIWNICKN */
1758 (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
1759 (iw_handler) NULL, /* -- hole -- */
1760 (iw_handler) NULL, /* -- hole -- */
1761 (iw_handler) NULL, /* SIOCSIWRATE */
1762 (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
1763 (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
1764 (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
1765 (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
1766 (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
1767 (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
1768 (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
1769 (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
1770 (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
1771 (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
1772 (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
1773 (iw_handler) NULL, /* SIOCSIWPOWER */
1774 (iw_handler) NULL, /* SIOCGIWPOWER */
1775 /* WPA operations */
1776 (iw_handler) NULL, /* -- hole -- */
1777 (iw_handler) NULL, /* -- hole -- */
1778 (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
1779 (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
1780 (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
1781 (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
1783 (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
1784 (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
1785 (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
1788 struct iw_handler_def p80211wext_handler_def = {
1789 .num_standard = ARRAY_SIZE(p80211wext_handlers),
1791 .num_private_args = 0,
1792 .standard = p80211wext_handlers,
1794 .private_args = NULL,
1795 .get_wireless_stats = p80211wext_get_wireless_stats
1799 int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
1801 union iwreq_data data;
1805 /* Send the association state first */
1806 data.ap_addr.sa_family = ARPHRD_ETHER;
1808 memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN);
1810 memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN);
1813 if (wlan_wext_write)
1814 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1816 if (!assoc) goto done;
1818 // XXX send association data, like IEs, etc etc.