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 (sizeof(p80211wext_channel_freq) / sizeof(p80211wext_channel_freq[0]))
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;
598 if (!wlan_wext_write) {
603 /* Check the Key index first. */
604 if((i = (erq->flags & IW_ENCODE_INDEX))) {
606 if ((i < 1) || (i > NUM_WEPKEYS)) {
613 /* Set current key number only if no keys are given */
614 if (erq->flags & IW_ENCODE_NOKEY) {
615 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i);
624 // Use defaultkey if no Key Index
625 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
628 /* Check if there is no key information in the iwconfig request */
629 if((erq->flags & IW_ENCODE_NOKEY) == 0 ) {
631 /*------------------------------------------------------------
632 * If there is WEP Key for setting, check the Key Information
633 * and then set it to the firmware.
634 -------------------------------------------------------------*/
636 if (erq->length > 0) {
638 /* copy the key from the driver cache as the keys are read-only MIBs */
639 wlandev->wep_keylens[i] = erq->length;
640 memcpy(wlandev->wep_keys[i], key, erq->length);
642 /* Prepare data struture for p80211req_dorequest. */
643 memcpy(pstr.data.data, key, erq->length);
644 pstr.data.len = erq->length;
649 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
653 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
657 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
661 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
669 msg.msgcode = DIDmsg_dot11req_mibset;
670 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
671 result = p80211req_dorequest(wlandev, (u8*)&msg);
681 /* Check the PrivacyInvoked flag */
682 if (erq->flags & IW_ENCODE_DISABLED) {
683 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
685 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
693 /* The security mode may be open or restricted, and its meaning
694 depends on the card used. With most cards, in open mode no
695 authentication is used and the card may also accept non-
696 encrypted sessions, whereas in restricted mode only encrypted
697 sessions are accepted and the card will use authentication if
700 if (erq->flags & IW_ENCODE_RESTRICTED) {
701 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
703 else if (erq->flags & IW_ENCODE_OPEN) {
704 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
718 static int p80211wext_giwessid(netdevice_t *dev,
719 struct iw_request_info *info,
720 struct iw_point *data, char *essid)
722 wlandevice_t *wlandev = dev->ml_priv;
726 if (wlandev->ssid.len) {
727 data->length = wlandev->ssid.len;
729 memcpy(essid, wlandev->ssid.data, data->length);
730 essid[data->length] = 0;
731 #if (WIRELESS_EXT < 21)
735 memset(essid, 0, sizeof(wlandev->ssid.data));
744 static int p80211wext_siwessid(netdevice_t *dev,
745 struct iw_request_info *info,
746 struct iw_point *data, char *essid)
748 wlandevice_t *wlandev = dev->ml_priv;
749 p80211msg_lnxreq_autojoin_t msg;
753 int length = data->length;
757 if (!wlan_wext_write) {
763 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
764 msg.authtype.data = P80211ENUM_authalg_sharedkey;
766 msg.authtype.data = P80211ENUM_authalg_opensystem;
768 msg.msgcode = DIDmsg_lnxreq_autojoin;
770 #if (WIRELESS_EXT < 21)
771 if (length) length--;
774 /* Trim the last '\0' to fit the SSID format */
776 if (length && essid[length-1] == '\0') {
780 memcpy(msg.ssid.data.data, essid, length);
781 msg.ssid.data.len = length;
783 WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid);
784 result = p80211req_dorequest(wlandev, (u8*)&msg);
785 WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result);
798 static int p80211wext_siwcommit(netdevice_t *dev,
799 struct iw_request_info *info,
800 struct iw_point *data, char *essid)
802 wlandevice_t *wlandev = dev->ml_priv;
807 if (!wlan_wext_write) {
813 err = p80211wext_autojoin(wlandev);
821 static int p80211wext_giwrate(netdevice_t *dev,
822 struct iw_request_info *info,
823 struct iw_param *rrq, char *extra)
825 wlandevice_t *wlandev = dev->ml_priv;
826 p80211item_uint32_t mibitem;
827 p80211msg_dot11req_mibset_t msg;
833 msg.msgcode = DIDmsg_dot11req_mibget;
834 mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
835 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
836 result = p80211req_dorequest(wlandev, (u8*)&msg);
843 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
845 rrq->fixed = 0; /* can it change? */
849 #define HFA384x_RATEBIT_1 ((u16)1)
850 #define HFA384x_RATEBIT_2 ((u16)2)
851 #define HFA384x_RATEBIT_5dot5 ((u16)4)
852 #define HFA384x_RATEBIT_11 ((u16)8)
854 switch (mibitem.data) {
855 case HFA384x_RATEBIT_1:
856 rrq->value = 1000000;
858 case HFA384x_RATEBIT_2:
859 rrq->value = 2000000;
861 case HFA384x_RATEBIT_5dot5:
862 rrq->value = 5500000;
864 case HFA384x_RATEBIT_11:
865 rrq->value = 11000000;
875 static int p80211wext_giwrts(netdevice_t *dev,
876 struct iw_request_info *info,
877 struct iw_param *rts, char *extra)
879 wlandevice_t *wlandev = dev->ml_priv;
880 p80211item_uint32_t mibitem;
881 p80211msg_dot11req_mibset_t msg;
887 msg.msgcode = DIDmsg_dot11req_mibget;
888 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
889 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
890 result = p80211req_dorequest(wlandev, (u8*)&msg);
897 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
899 rts->value = mibitem.data;
900 rts->disabled = (rts->value == 2347);
909 static int p80211wext_siwrts(netdevice_t *dev,
910 struct iw_request_info *info,
911 struct iw_param *rts, char *extra)
913 wlandevice_t *wlandev = dev->ml_priv;
914 p80211item_uint32_t mibitem;
915 p80211msg_dot11req_mibset_t msg;
921 if (!wlan_wext_write) {
926 msg.msgcode = DIDmsg_dot11req_mibget;
927 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
931 mibitem.data = rts->value;
933 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
934 result = p80211req_dorequest(wlandev, (u8*)&msg);
946 static int p80211wext_giwfrag(netdevice_t *dev,
947 struct iw_request_info *info,
948 struct iw_param *frag, char *extra)
950 wlandevice_t *wlandev = dev->ml_priv;
951 p80211item_uint32_t mibitem;
952 p80211msg_dot11req_mibset_t msg;
958 msg.msgcode = DIDmsg_dot11req_mibget;
959 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
960 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
961 result = p80211req_dorequest(wlandev, (u8*)&msg);
968 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
970 frag->value = mibitem.data;
971 frag->disabled = (frag->value == 2346);
979 static int p80211wext_siwfrag(netdevice_t *dev,
980 struct iw_request_info *info,
981 struct iw_param *frag, char *extra)
983 wlandevice_t *wlandev = dev->ml_priv;
984 p80211item_uint32_t mibitem;
985 p80211msg_dot11req_mibset_t msg;
991 if (!wlan_wext_write) {
996 msg.msgcode = DIDmsg_dot11req_mibset;
997 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
1000 mibitem.data = 2346;
1002 mibitem.data = frag->value;
1004 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1005 result = p80211req_dorequest(wlandev, (u8*)&msg);
1017 #ifndef IW_RETRY_LONG
1018 #define IW_RETRY_LONG IW_RETRY_MAX
1021 #ifndef IW_RETRY_SHORT
1022 #define IW_RETRY_SHORT IW_RETRY_MIN
1025 static int p80211wext_giwretry(netdevice_t *dev,
1026 struct iw_request_info *info,
1027 struct iw_param *rrq, char *extra)
1029 wlandevice_t *wlandev = dev->ml_priv;
1030 p80211item_uint32_t mibitem;
1031 p80211msg_dot11req_mibset_t msg;
1034 u16 shortretry, longretry, lifetime;
1038 msg.msgcode = DIDmsg_dot11req_mibget;
1039 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1041 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1042 result = p80211req_dorequest(wlandev, (u8*)&msg);
1049 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1051 shortretry = mibitem.data;
1053 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1055 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1056 result = p80211req_dorequest(wlandev, (u8*)&msg);
1063 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1065 longretry = mibitem.data;
1067 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1069 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1070 result = p80211req_dorequest(wlandev, (u8*)&msg);
1077 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1079 lifetime = mibitem.data;
1083 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1084 rrq->flags = IW_RETRY_LIFETIME;
1085 rrq->value = lifetime * 1024;
1087 if (rrq->flags & IW_RETRY_LONG) {
1088 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1089 rrq->value = longretry;
1091 rrq->flags = IW_RETRY_LIMIT;
1092 rrq->value = shortretry;
1093 if (shortretry != longretry)
1094 rrq->flags |= IW_RETRY_SHORT;
1104 static int p80211wext_siwretry(netdevice_t *dev,
1105 struct iw_request_info *info,
1106 struct iw_param *rrq, char *extra)
1108 wlandevice_t *wlandev = dev->ml_priv;
1109 p80211item_uint32_t mibitem;
1110 p80211msg_dot11req_mibset_t msg;
1116 if (!wlan_wext_write) {
1117 err = (-EOPNOTSUPP);
1121 if (rrq->disabled) {
1126 msg.msgcode = DIDmsg_dot11req_mibset;
1128 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1129 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1130 mibitem.data = rrq->value /= 1024;
1132 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1133 result = p80211req_dorequest(wlandev, (u8*)&msg);
1140 if (rrq->flags & IW_RETRY_LONG) {
1141 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1142 mibitem.data = rrq->value;
1144 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1145 result = p80211req_dorequest(wlandev, (u8*)&msg);
1153 if (rrq->flags & IW_RETRY_SHORT) {
1154 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1155 mibitem.data = rrq->value;
1157 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1158 result = p80211req_dorequest(wlandev, (u8*)&msg);
1173 static int p80211wext_siwtxpow(netdevice_t *dev,
1174 struct iw_request_info *info,
1175 struct iw_param *rrq, char *extra)
1177 wlandevice_t *wlandev = dev->ml_priv;
1178 p80211item_uint32_t mibitem;
1179 p80211msg_dot11req_mibset_t msg;
1185 if (!wlan_wext_write) {
1186 err = (-EOPNOTSUPP);
1190 msg.msgcode = DIDmsg_dot11req_mibset;
1191 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1192 if (rrq->fixed == 0)
1195 mibitem.data = rrq->value;
1196 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1197 result = p80211req_dorequest(wlandev, (u8*)&msg);
1209 static int p80211wext_giwtxpow(netdevice_t *dev,
1210 struct iw_request_info *info,
1211 struct iw_param *rrq, char *extra)
1213 wlandevice_t *wlandev = dev->ml_priv;
1214 p80211item_uint32_t mibitem;
1215 p80211msg_dot11req_mibset_t msg;
1221 msg.msgcode = DIDmsg_dot11req_mibget;
1222 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1224 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1225 result = p80211req_dorequest(wlandev, (u8*)&msg);
1232 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1234 // XXX handle OFF by setting disabled = 1;
1236 rrq->flags = 0; // IW_TXPOW_DBM;
1239 rrq->value = mibitem.data;
1246 static int p80211wext_siwspy(netdevice_t *dev,
1247 struct iw_request_info *info,
1248 struct iw_point *srq, char *extra)
1250 wlandevice_t *wlandev = dev->ml_priv;
1251 struct sockaddr address[IW_MAX_SPY];
1252 int number = srq->length;
1257 /* Copy the data from the input buffer */
1258 memcpy(address, extra, sizeof(struct sockaddr)*number);
1260 wlandev->spy_number = 0;
1264 /* extract the addresses */
1265 for (i = 0; i < number; i++) {
1267 memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN);
1271 memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
1273 /* set number of addresses */
1274 wlandev->spy_number = number;
1281 /* jkriegl: from orinoco, modified */
1282 static int p80211wext_giwspy(netdevice_t *dev,
1283 struct iw_request_info *info,
1284 struct iw_point *srq, char *extra)
1286 wlandevice_t *wlandev = dev->ml_priv;
1288 struct sockaddr address[IW_MAX_SPY];
1289 struct iw_quality spy_stat[IW_MAX_SPY];
1295 number = wlandev->spy_number;
1299 /* populate address and spy struct's */
1300 for (i = 0; i < number; i++) {
1301 memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN);
1302 address[i].sa_family = AF_UNIX;
1303 memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality));
1306 /* reset update flag */
1307 for (i=0; i < number; i++)
1308 wlandev->spy_stat[i].updated = 0;
1311 /* push stuff to user space */
1312 srq->length = number;
1313 memcpy(extra, address, sizeof(struct sockaddr)*number);
1314 memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number);
1320 static int prism2_result2err (int prism2_result)
1324 switch (prism2_result) {
1325 case P80211ENUM_resultcode_invalid_parameters:
1328 case P80211ENUM_resultcode_implementation_failure:
1331 case P80211ENUM_resultcode_not_supported:
1342 static int p80211wext_siwscan(netdevice_t *dev,
1343 struct iw_request_info *info,
1344 struct iw_point *srq, char *extra)
1346 wlandevice_t *wlandev = dev->ml_priv;
1347 p80211msg_dot11req_scan_t msg;
1354 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1355 WLAN_LOG_ERROR("Can't scan in AP mode\n");
1356 err = (-EOPNOTSUPP);
1360 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1361 msg.msgcode = DIDmsg_dot11req_scan;
1362 msg.bsstype.data = P80211ENUM_bsstype_any;
1364 memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t));
1365 msg.bssid.data.len = 6;
1367 msg.scantype.data = P80211ENUM_scantype_active;
1368 msg.probedelay.data = 0;
1370 for (i = 1; i <= 14; i++)
1371 msg.channellist.data.data[i-1] = i;
1372 msg.channellist.data.len = 14;
1374 msg.maxchanneltime.data = 250;
1375 msg.minchanneltime.data = 200;
1377 result = p80211req_dorequest(wlandev, (u8*)&msg);
1379 err = prism2_result2err (msg.resultcode.data);
1387 /* Helper to translate scan into Wireless Extensions scan results.
1388 * Inspired by the prism54 code, which was in turn inspired by the
1392 wext_translate_bss(struct iw_request_info *info, char *current_ev,
1393 char *end_buf, p80211msg_dot11req_scan_results_t *bss)
1395 struct iw_event iwe; /* Temporary buffer */
1397 /* The first entry must be the MAC address */
1398 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1399 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1400 iwe.cmd = SIOCGIWAP;
1401 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
1403 /* The following entries will be displayed in the same order we give them */
1406 if (bss->ssid.data.len > 0) {
1407 char essid[IW_ESSID_MAX_SIZE + 1];
1410 size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len);
1411 memset(&essid, 0, sizeof (essid));
1412 memcpy(&essid, bss->ssid.data.data, size);
1413 WLAN_LOG_DEBUG(1, " essid size = %d\n", size);
1414 iwe.u.data.length = size;
1415 iwe.u.data.flags = 1;
1416 iwe.cmd = SIOCGIWESSID;
1417 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]);
1418 WLAN_LOG_DEBUG(1, " essid size OK.\n");
1421 switch (bss->bsstype.data) {
1422 case P80211ENUM_bsstype_infrastructure:
1423 iwe.u.mode = IW_MODE_MASTER;
1426 case P80211ENUM_bsstype_independent:
1427 iwe.u.mode = IW_MODE_ADHOC;
1434 iwe.cmd = SIOCGIWMODE;
1436 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
1438 /* Encryption capability */
1439 if (bss->privacy.data == P80211ENUM_truth_true)
1440 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1442 iwe.u.data.flags = IW_ENCODE_DISABLED;
1443 iwe.u.data.length = 0;
1444 iwe.cmd = SIOCGIWENCODE;
1445 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1447 /* Add frequency. (short) bss->channel is the frequency in MHz */
1448 iwe.u.freq.m = bss->dschannel.data;
1450 iwe.cmd = SIOCGIWFREQ;
1451 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
1453 /* Add quality statistics */
1454 iwe.u.qual.level = bss->signal.data;
1455 iwe.u.qual.noise = bss->noise.data;
1456 /* do a simple SNR for quality */
1457 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1459 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
1465 static int p80211wext_giwscan(netdevice_t *dev,
1466 struct iw_request_info *info,
1467 struct iw_point *srq, char *extra)
1469 wlandevice_t *wlandev = dev->ml_priv;
1470 p80211msg_dot11req_scan_results_t msg;
1475 char *current_ev = extra;
1479 /* Since wireless tools doesn't really have a way of passing how
1480 * many scan results results there were back here, keep grabbing them
1484 memset(&msg, 0, sizeof(msg));
1485 msg.msgcode = DIDmsg_dot11req_scan_results;
1486 msg.bssindex.data = i;
1488 result = p80211req_dorequest(wlandev, (u8*)&msg);
1489 if ((result != 0) ||
1490 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1494 current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg);
1497 } while (i < IW_MAX_AP);
1499 srq->length = (current_ev - extra);
1500 srq->flags = 0; /* todo */
1502 if (result && !scan_good)
1503 err = prism2_result2err (msg.resultcode.data);
1509 /*****************************************************/
1510 //extra wireless extensions stuff to support NetworkManager (I hope)
1512 /* SIOCSIWENCODEEXT */
1513 static int p80211wext_set_encodeext(struct net_device *dev,
1514 struct iw_request_info *info,
1515 union iwreq_data *wrqu, char *extra)
1517 wlandevice_t *wlandev = dev->ml_priv;
1518 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1519 p80211msg_dot11req_mibset_t msg;
1520 p80211item_pstr32_t *pstr;
1523 struct iw_point *encoding = &wrqu->encoding;
1524 int idx = encoding->flags & IW_ENCODE_INDEX;
1526 WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1529 if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
1530 // set default key ? I'm not sure if this the the correct thing to do here
1533 if (idx < 1 || idx > NUM_WEPKEYS) {
1538 WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx);
1539 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx);
1545 if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) {
1546 if (!(ext->alg & IW_ENCODE_ALG_WEP)) {
1547 WLAN_LOG_DEBUG(1,"asked to set a non wep key :(");
1551 if (idx <1 || idx > NUM_WEPKEYS)
1556 WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx);
1557 wlandev->wep_keylens[idx] = ext->key_len;
1558 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1560 memset( &msg,0,sizeof(msg));
1561 pstr = (p80211item_pstr32_t*)&msg.mibattribute.data;
1562 memcpy(pstr->data.data, ext->key,ext->key_len);
1563 pstr->data.len = ext->key_len;
1566 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1569 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1572 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1575 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1580 msg.msgcode = DIDmsg_dot11req_mibset;
1581 result = p80211req_dorequest(wlandev,(u8*)&msg);
1582 WLAN_LOG_DEBUG(1,"result (%d)\n",result);
1587 /* SIOCGIWENCODEEXT */
1588 static int p80211wext_get_encodeext(struct net_device *dev,
1589 struct iw_request_info *info,
1590 union iwreq_data *wrqu, char *extra)
1593 wlandevice_t *wlandev = dev->ml_priv;
1594 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1596 struct iw_point *encoding = &wrqu->encoding;
1603 WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1606 max_len = encoding->length - sizeof(*ext);
1607 if ( max_len <= 0) {
1608 WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len);
1612 idx = encoding->flags & IW_ENCODE_INDEX;
1614 WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx);
1617 if (idx < 1 || idx > NUM_WEPKEYS ) {
1618 WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx);
1624 /* default key ? not sure what to do */
1625 /* will just use key[0] for now ! FIX ME */
1628 encoding->flags = idx + 1;
1629 memset(ext,0,sizeof(*ext));
1631 ext->alg = IW_ENCODE_ALG_WEP;
1632 ext->key_len = wlandev->wep_keylens[idx];
1633 memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len );
1635 encoding->flags |= IW_ENCODE_ENABLED;
1644 static int p80211_wext_set_iwauth (struct net_device *dev,
1645 struct iw_request_info *info,
1646 union iwreq_data *wrqu, char *extra)
1648 wlandevice_t *wlandev = dev->ml_priv;
1649 struct iw_param *param = &wrqu->param;
1652 WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1654 switch (param->flags & IW_AUTH_INDEX) {
1655 case IW_AUTH_DROP_UNENCRYPTED:
1656 WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value);
1658 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
1660 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
1663 case IW_AUTH_PRIVACY_INVOKED:
1664 WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value);
1666 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
1668 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
1672 case IW_AUTH_80211_AUTH_ALG:
1673 if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) {
1674 WLAN_LOG_DEBUG(1,"set open_system\n");
1675 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1676 } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) {
1677 WLAN_LOG_DEBUG(1,"set shared key\n");
1678 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1680 /* don't know what to do know :( */
1681 WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value);
1696 static int p80211_wext_get_iwauth (struct net_device *dev,
1697 struct iw_request_info *info,
1698 union iwreq_data *wrqu, char *extra)
1700 wlandevice_t *wlandev = dev->ml_priv;
1701 struct iw_param *param = &wrqu->param;
1704 WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1706 switch (param->flags & IW_AUTH_INDEX) {
1707 case IW_AUTH_DROP_UNENCRYPTED:
1708 param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0;
1711 case IW_AUTH_PRIVACY_INVOKED:
1712 param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0;
1715 case IW_AUTH_80211_AUTH_ALG:
1716 param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM;
1729 static iw_handler p80211wext_handlers[] = {
1730 (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
1731 (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
1732 (iw_handler) NULL, /* SIOCSIWNWID */
1733 (iw_handler) NULL, /* SIOCGIWNWID */
1734 (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
1735 (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
1736 (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
1737 (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
1738 (iw_handler) NULL, /* SIOCSIWSENS */
1739 (iw_handler) NULL, /* SIOCGIWSENS */
1740 (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */
1741 (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
1742 (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */
1743 (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */
1744 (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */
1745 (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */
1746 (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
1747 (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
1748 (iw_handler) NULL, /* -- hole -- */
1749 (iw_handler) NULL, /* -- hole -- */
1750 (iw_handler) NULL, /* SIOCSIWAP */
1751 (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
1752 (iw_handler) NULL, /* -- hole -- */
1753 (iw_handler) NULL, /* SIOCGIWAPLIST */
1754 (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
1755 (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
1756 (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
1757 (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
1758 (iw_handler) NULL, /* SIOCSIWNICKN */
1759 (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
1760 (iw_handler) NULL, /* -- hole -- */
1761 (iw_handler) NULL, /* -- hole -- */
1762 (iw_handler) NULL, /* SIOCSIWRATE */
1763 (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
1764 (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
1765 (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
1766 (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
1767 (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
1768 (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
1769 (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
1770 (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
1771 (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
1772 (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
1773 (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
1774 (iw_handler) NULL, /* SIOCSIWPOWER */
1775 (iw_handler) NULL, /* SIOCGIWPOWER */
1776 /* WPA operations */
1777 (iw_handler) NULL, /* -- hole -- */
1778 (iw_handler) NULL, /* -- hole -- */
1779 (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
1780 (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
1781 (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
1782 (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
1784 (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
1785 (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
1786 (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
1789 struct iw_handler_def p80211wext_handler_def = {
1790 .num_standard = sizeof(p80211wext_handlers) / sizeof(iw_handler),
1792 .num_private_args = 0,
1793 .standard = p80211wext_handlers,
1795 .private_args = NULL,
1796 .get_wireless_stats = p80211wext_get_wireless_stats
1800 int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
1802 union iwreq_data data;
1806 /* Send the association state first */
1807 data.ap_addr.sa_family = ARPHRD_ETHER;
1809 memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN);
1811 memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN);
1814 if (wlan_wext_write)
1815 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1817 if (!assoc) goto done;
1819 // XXX send association data, like IEs, etc etc.