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 /*================================================================*/
41 #include <linux/version.h>
43 #include <linux/kernel.h>
44 #include <linux/sched.h>
45 #include <linux/types.h>
46 #include <linux/slab.h>
47 #include <linux/netdevice.h>
48 #include <linux/etherdevice.h>
49 #include <linux/wireless.h>
50 #include <net/iw_handler.h>
51 #include <linux/if_arp.h>
52 #include <asm/bitops.h>
53 #include <asm/uaccess.h>
54 #include <asm/byteorder.h>
56 /*================================================================*/
57 /* Project Includes */
59 #include "wlan_compat.h"
61 #include "p80211types.h"
62 #include "p80211hdr.h"
63 #include "p80211conv.h"
64 #include "p80211mgmt.h"
65 #include "p80211msg.h"
66 #include "p80211metastruct.h"
67 #include "p80211metadef.h"
68 #include "p80211netdev.h"
69 #include "p80211ioctl.h"
70 #include "p80211req.h"
72 static int p80211wext_giwrate(netdevice_t *dev,
73 struct iw_request_info *info,
74 struct iw_param *rrq, char *extra);
75 static int p80211wext_giwessid(netdevice_t *dev,
76 struct iw_request_info *info,
77 struct iw_point *data, char *essid);
79 static u8 p80211_mhz_to_channel(u16 mhz)
82 return ((mhz - 5000) / 5);
89 return ((mhz - 2407) / 5);
95 static u16 p80211_channel_to_mhz(u8 ch, int dot11a)
106 return (5000 + (5 * ch));
114 if ((ch < 14) && (ch > 0)) {
115 return (2407 + (5 * ch));
121 /* taken from orinoco.c ;-) */
122 static const long p80211wext_channel_freq[] = {
123 2412, 2417, 2422, 2427, 2432, 2437, 2442,
124 2447, 2452, 2457, 2462, 2467, 2472, 2484
126 #define NUM_CHANNELS (sizeof(p80211wext_channel_freq) / sizeof(p80211wext_channel_freq[0]))
128 /* steal a spare bit to store the shared/opensystems state. should default to open if not set */
129 #define HOSTWEP_SHAREDKEY BIT3
132 /** function declarations =============== */
134 static int qual_as_percent(int snr ) {
145 static int p80211wext_dorequest(wlandevice_t *wlandev, u32 did, u32 data)
147 p80211msg_dot11req_mibset_t msg;
148 p80211item_uint32_t mibitem;
153 msg.msgcode = DIDmsg_dot11req_mibset;
156 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
157 result = p80211req_dorequest(wlandev, (u8*)&msg);
163 static int p80211wext_autojoin(wlandevice_t *wlandev)
165 p80211msg_lnxreq_autojoin_t msg;
166 struct iw_point data;
167 char ssid[IW_ESSID_MAX_SIZE];
175 result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid);
182 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
183 msg.authtype.data = P80211ENUM_authalg_sharedkey;
185 msg.authtype.data = P80211ENUM_authalg_opensystem;
187 msg.msgcode = DIDmsg_lnxreq_autojoin;
189 /* Trim the last '\0' to fit the SSID format */
191 if (data.length && ssid[data.length-1] == '\0') {
192 data.length = data.length - 1;
195 memcpy(msg.ssid.data.data, ssid, data.length);
196 msg.ssid.data.len = data.length;
198 result = p80211req_dorequest(wlandev, (u8*)&msg);
212 /* called by /proc/net/wireless */
213 struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev)
215 p80211msg_lnxreq_commsquality_t quality;
216 wlandevice_t *wlandev = dev->ml_priv;
217 struct iw_statistics* wstats = &wlandev->wstats;
222 if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) )
225 /* XXX Only valid in station mode */
228 /* build request message */
229 quality.msgcode = DIDmsg_lnxreq_commsquality;
230 quality.dbm.data = P80211ENUM_truth_true;
231 quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
233 /* send message to nsd */
234 if ( wlandev->mlmerequest == NULL )
237 retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality);
239 wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
240 wstats->qual.level = quality.level.data; /* instant signal level */
241 wstats->qual.noise = quality.noise.data; /* instant noise level */
243 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
244 wstats->discard.code = wlandev->rx.decrypt_err;
245 wstats->discard.nwid = 0;
246 wstats->discard.misc = 0;
248 wstats->discard.fragment = 0; // incomplete fragments
249 wstats->discard.retries = 0; // tx retries.
250 wstats->miss.beacon = 0;
257 static int p80211wext_giwname(netdevice_t *dev,
258 struct iw_request_info *info,
259 char *name, char *extra)
261 struct iw_param rate;
267 result = p80211wext_giwrate(dev, NULL, &rate, NULL);
274 switch (rate.value) {
277 strcpy(name, "IEEE 802.11-DS");
281 strcpy(name, "IEEE 802.11-b");
289 static int p80211wext_giwfreq(netdevice_t *dev,
290 struct iw_request_info *info,
291 struct iw_freq *freq, char *extra)
293 wlandevice_t *wlandev = dev->ml_priv;
294 p80211item_uint32_t mibitem;
295 p80211msg_dot11req_mibset_t msg;
301 msg.msgcode = DIDmsg_dot11req_mibget;
302 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
303 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
304 result = p80211req_dorequest(wlandev, (u8*)&msg);
311 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
313 if (mibitem.data > NUM_CHANNELS) {
318 /* convert into frequency instead of a channel */
320 freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000;
327 static int p80211wext_siwfreq(netdevice_t *dev,
328 struct iw_request_info *info,
329 struct iw_freq *freq, char *extra)
331 wlandevice_t *wlandev = dev->ml_priv;
332 p80211item_uint32_t mibitem;
333 p80211msg_dot11req_mibset_t msg;
339 if (!wlan_wext_write) {
344 msg.msgcode = DIDmsg_dot11req_mibset;
345 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
346 mibitem.status = P80211ENUM_msgitem_status_data_ok;
348 if ( (freq->e == 0) && (freq->m <= 1000) )
349 mibitem.data = freq->m;
351 mibitem.data = p80211_mhz_to_channel(freq->m);
353 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
354 result = p80211req_dorequest(wlandev, (u8*)&msg);
366 static int p80211wext_giwmode(netdevice_t *dev,
367 struct iw_request_info *info,
368 __u32 *mode, char *extra)
370 wlandevice_t *wlandev = dev->ml_priv;
374 switch (wlandev->macmode) {
375 case WLAN_MACMODE_IBSS_STA:
376 *mode = IW_MODE_ADHOC;
378 case WLAN_MACMODE_ESS_STA:
379 *mode = IW_MODE_INFRA;
381 case WLAN_MACMODE_ESS_AP:
382 *mode = IW_MODE_MASTER;
386 *mode = IW_MODE_AUTO;
393 static int p80211wext_siwmode(netdevice_t *dev,
394 struct iw_request_info *info,
395 __u32 *mode, char *extra)
397 wlandevice_t *wlandev = dev->ml_priv;
398 p80211item_uint32_t mibitem;
399 p80211msg_dot11req_mibset_t msg;
405 if (!wlan_wext_write) {
410 if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
411 *mode != IW_MODE_MASTER) {
416 /* Operation mode is the same with current mode */
417 if (*mode == wlandev->macmode)
422 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
425 wlandev->macmode = WLAN_MACMODE_ESS_STA;
428 wlandev->macmode = WLAN_MACMODE_ESS_AP;
432 WLAN_LOG_INFO("Operation mode: %d not support\n", *mode);
436 /* Set Operation mode to the PORT TYPE RID */
437 msg.msgcode = DIDmsg_dot11req_mibset;
438 mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
439 mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
440 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
441 result = p80211req_dorequest(wlandev, (u8*)&msg);
453 static int p80211wext_giwrange(netdevice_t *dev,
454 struct iw_request_info *info,
455 struct iw_point *data, char *extra)
457 struct iw_range *range = (struct iw_range *) extra;
462 // for backward compatability set size & zero everything we don't understand
463 data->length = sizeof(*range);
464 memset(range,0,sizeof(*range));
466 range->txpower_capa = IW_TXPOW_DBM;
467 // XXX what about min/max_pmp, min/max_pmt, etc.
469 range->we_version_compiled = WIRELESS_EXT;
470 range->we_version_source = 13;
472 range->retry_capa = IW_RETRY_LIMIT;
473 range->retry_flags = IW_RETRY_LIMIT;
474 range->min_retry = 0;
475 range->max_retry = 255;
477 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | //mode/freq/ssid
478 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
479 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
480 range->event_capa[1] = IW_EVENT_CAPA_K_1; //encode
481 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
482 IW_EVENT_CAPA_MASK(IWEVCUSTOM) );
484 range->num_channels = NUM_CHANNELS;
486 /* XXX need to filter against the regulatory domain &| active set */
488 for (i = 0; i < NUM_CHANNELS ; i++) {
489 range->freq[val].i = i + 1;
490 range->freq[val].m = p80211wext_channel_freq[i] * 100000;
491 range->freq[val].e = 1;
495 range->num_frequency = val;
497 /* Max of /proc/net/wireless */
498 range->max_qual.qual = 100;
499 range->max_qual.level = 0;
500 range->max_qual.noise = 0;
501 range->sensitivity = 3;
502 // XXX these need to be nsd-specific!
505 range->max_rts = 2347;
506 range->min_frag = 256;
507 range->max_frag = 2346;
509 range->max_encoding_tokens = NUM_WEPKEYS;
510 range->num_encoding_sizes = 2;
511 range->encoding_size[0] = 5;
512 range->encoding_size[1] = 13;
514 // XXX what about num_bitrates/throughput?
515 range->num_bitrates = 0;
517 /* estimated max throughput */
518 // XXX need to cap it if we're running at ~2Mbps..
519 range->throughput = 5500000;
525 static int p80211wext_giwap(netdevice_t *dev,
526 struct iw_request_info *info,
527 struct sockaddr *ap_addr, char *extra)
530 wlandevice_t *wlandev = dev->ml_priv;
534 memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
535 ap_addr->sa_family = ARPHRD_ETHER;
541 static int p80211wext_giwencode(netdevice_t *dev,
542 struct iw_request_info *info,
543 struct iw_point *erq, char *key)
545 wlandevice_t *wlandev = dev->ml_priv;
551 i = (erq->flags & IW_ENCODE_INDEX) - 1;
554 if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
555 erq->flags |= IW_ENCODE_ENABLED;
557 erq->flags |= IW_ENCODE_DISABLED;
559 if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
560 erq->flags |= IW_ENCODE_RESTRICTED;
562 erq->flags |= IW_ENCODE_OPEN;
564 i = (erq->flags & IW_ENCODE_INDEX) - 1;
567 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
569 if ((i < 0) || (i >= NUM_WEPKEYS)) {
576 /* copy the key from the driver cache as the keys are read-only MIBs */
577 erq->length = wlandev->wep_keylens[i];
578 memcpy(key, wlandev->wep_keys[i], erq->length);
585 static int p80211wext_siwencode(netdevice_t *dev,
586 struct iw_request_info *info,
587 struct iw_point *erq, char *key)
589 wlandevice_t *wlandev = dev->ml_priv;
590 p80211msg_dot11req_mibset_t msg;
591 p80211item_pstr32_t pstr;
599 if (!wlan_wext_write) {
604 /* Check the Key index first. */
605 if((i = (erq->flags & IW_ENCODE_INDEX))) {
607 if ((i < 1) || (i > NUM_WEPKEYS)) {
614 /* Set current key number only if no keys are given */
615 if (erq->flags & IW_ENCODE_NOKEY) {
616 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i);
625 // Use defaultkey if no Key Index
626 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
629 /* Check if there is no key information in the iwconfig request */
630 if((erq->flags & IW_ENCODE_NOKEY) == 0 ) {
632 /*------------------------------------------------------------
633 * If there is WEP Key for setting, check the Key Information
634 * and then set it to the firmware.
635 -------------------------------------------------------------*/
637 if (erq->length > 0) {
639 /* copy the key from the driver cache as the keys are read-only MIBs */
640 wlandev->wep_keylens[i] = erq->length;
641 memcpy(wlandev->wep_keys[i], key, erq->length);
643 /* Prepare data struture for p80211req_dorequest. */
644 memcpy(pstr.data.data, key, erq->length);
645 pstr.data.len = erq->length;
650 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
654 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
658 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
662 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
670 msg.msgcode = DIDmsg_dot11req_mibset;
671 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
672 result = p80211req_dorequest(wlandev, (u8*)&msg);
682 /* Check the PrivacyInvoked flag */
683 if (erq->flags & IW_ENCODE_DISABLED) {
684 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
686 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
694 /* The security mode may be open or restricted, and its meaning
695 depends on the card used. With most cards, in open mode no
696 authentication is used and the card may also accept non-
697 encrypted sessions, whereas in restricted mode only encrypted
698 sessions are accepted and the card will use authentication if
701 if (erq->flags & IW_ENCODE_RESTRICTED) {
702 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
704 else if (erq->flags & IW_ENCODE_OPEN) {
705 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
719 static int p80211wext_giwessid(netdevice_t *dev,
720 struct iw_request_info *info,
721 struct iw_point *data, char *essid)
723 wlandevice_t *wlandev = dev->ml_priv;
727 if (wlandev->ssid.len) {
728 data->length = wlandev->ssid.len;
730 memcpy(essid, wlandev->ssid.data, data->length);
731 essid[data->length] = 0;
732 #if (WIRELESS_EXT < 21)
736 memset(essid, 0, sizeof(wlandev->ssid.data));
745 static int p80211wext_siwessid(netdevice_t *dev,
746 struct iw_request_info *info,
747 struct iw_point *data, char *essid)
749 wlandevice_t *wlandev = dev->ml_priv;
750 p80211msg_lnxreq_autojoin_t msg;
754 int length = data->length;
758 if (!wlan_wext_write) {
764 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
765 msg.authtype.data = P80211ENUM_authalg_sharedkey;
767 msg.authtype.data = P80211ENUM_authalg_opensystem;
769 msg.msgcode = DIDmsg_lnxreq_autojoin;
771 #if (WIRELESS_EXT < 21)
772 if (length) length--;
775 /* Trim the last '\0' to fit the SSID format */
777 if (length && essid[length-1] == '\0') {
781 memcpy(msg.ssid.data.data, essid, length);
782 msg.ssid.data.len = length;
784 WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid);
785 result = p80211req_dorequest(wlandev, (u8*)&msg);
786 WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result);
799 static int p80211wext_siwcommit(netdevice_t *dev,
800 struct iw_request_info *info,
801 struct iw_point *data, char *essid)
803 wlandevice_t *wlandev = dev->ml_priv;
808 if (!wlan_wext_write) {
814 err = p80211wext_autojoin(wlandev);
822 static int p80211wext_giwrate(netdevice_t *dev,
823 struct iw_request_info *info,
824 struct iw_param *rrq, char *extra)
826 wlandevice_t *wlandev = dev->ml_priv;
827 p80211item_uint32_t mibitem;
828 p80211msg_dot11req_mibset_t msg;
834 msg.msgcode = DIDmsg_dot11req_mibget;
835 mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
836 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
837 result = p80211req_dorequest(wlandev, (u8*)&msg);
844 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
846 rrq->fixed = 0; /* can it change? */
850 #define HFA384x_RATEBIT_1 ((u16)1)
851 #define HFA384x_RATEBIT_2 ((u16)2)
852 #define HFA384x_RATEBIT_5dot5 ((u16)4)
853 #define HFA384x_RATEBIT_11 ((u16)8)
855 switch (mibitem.data) {
856 case HFA384x_RATEBIT_1:
857 rrq->value = 1000000;
859 case HFA384x_RATEBIT_2:
860 rrq->value = 2000000;
862 case HFA384x_RATEBIT_5dot5:
863 rrq->value = 5500000;
865 case HFA384x_RATEBIT_11:
866 rrq->value = 11000000;
876 static int p80211wext_giwrts(netdevice_t *dev,
877 struct iw_request_info *info,
878 struct iw_param *rts, char *extra)
880 wlandevice_t *wlandev = dev->ml_priv;
881 p80211item_uint32_t mibitem;
882 p80211msg_dot11req_mibset_t msg;
888 msg.msgcode = DIDmsg_dot11req_mibget;
889 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
890 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
891 result = p80211req_dorequest(wlandev, (u8*)&msg);
898 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
900 rts->value = mibitem.data;
901 rts->disabled = (rts->value == 2347);
910 static int p80211wext_siwrts(netdevice_t *dev,
911 struct iw_request_info *info,
912 struct iw_param *rts, char *extra)
914 wlandevice_t *wlandev = dev->ml_priv;
915 p80211item_uint32_t mibitem;
916 p80211msg_dot11req_mibset_t msg;
922 if (!wlan_wext_write) {
927 msg.msgcode = DIDmsg_dot11req_mibget;
928 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
932 mibitem.data = rts->value;
934 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
935 result = p80211req_dorequest(wlandev, (u8*)&msg);
947 static int p80211wext_giwfrag(netdevice_t *dev,
948 struct iw_request_info *info,
949 struct iw_param *frag, char *extra)
951 wlandevice_t *wlandev = dev->ml_priv;
952 p80211item_uint32_t mibitem;
953 p80211msg_dot11req_mibset_t msg;
959 msg.msgcode = DIDmsg_dot11req_mibget;
960 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
961 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
962 result = p80211req_dorequest(wlandev, (u8*)&msg);
969 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
971 frag->value = mibitem.data;
972 frag->disabled = (frag->value == 2346);
980 static int p80211wext_siwfrag(netdevice_t *dev,
981 struct iw_request_info *info,
982 struct iw_param *frag, char *extra)
984 wlandevice_t *wlandev = dev->ml_priv;
985 p80211item_uint32_t mibitem;
986 p80211msg_dot11req_mibset_t msg;
992 if (!wlan_wext_write) {
997 msg.msgcode = DIDmsg_dot11req_mibset;
998 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
1001 mibitem.data = 2346;
1003 mibitem.data = frag->value;
1005 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1006 result = p80211req_dorequest(wlandev, (u8*)&msg);
1018 #ifndef IW_RETRY_LONG
1019 #define IW_RETRY_LONG IW_RETRY_MAX
1022 #ifndef IW_RETRY_SHORT
1023 #define IW_RETRY_SHORT IW_RETRY_MIN
1026 static int p80211wext_giwretry(netdevice_t *dev,
1027 struct iw_request_info *info,
1028 struct iw_param *rrq, char *extra)
1030 wlandevice_t *wlandev = dev->ml_priv;
1031 p80211item_uint32_t mibitem;
1032 p80211msg_dot11req_mibset_t msg;
1035 u16 shortretry, longretry, lifetime;
1039 msg.msgcode = DIDmsg_dot11req_mibget;
1040 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1042 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1043 result = p80211req_dorequest(wlandev, (u8*)&msg);
1050 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1052 shortretry = mibitem.data;
1054 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1056 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1057 result = p80211req_dorequest(wlandev, (u8*)&msg);
1064 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1066 longretry = mibitem.data;
1068 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1070 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1071 result = p80211req_dorequest(wlandev, (u8*)&msg);
1078 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1080 lifetime = mibitem.data;
1084 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1085 rrq->flags = IW_RETRY_LIFETIME;
1086 rrq->value = lifetime * 1024;
1088 if (rrq->flags & IW_RETRY_LONG) {
1089 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1090 rrq->value = longretry;
1092 rrq->flags = IW_RETRY_LIMIT;
1093 rrq->value = shortretry;
1094 if (shortretry != longretry)
1095 rrq->flags |= IW_RETRY_SHORT;
1105 static int p80211wext_siwretry(netdevice_t *dev,
1106 struct iw_request_info *info,
1107 struct iw_param *rrq, char *extra)
1109 wlandevice_t *wlandev = dev->ml_priv;
1110 p80211item_uint32_t mibitem;
1111 p80211msg_dot11req_mibset_t msg;
1117 if (!wlan_wext_write) {
1118 err = (-EOPNOTSUPP);
1122 if (rrq->disabled) {
1127 msg.msgcode = DIDmsg_dot11req_mibset;
1129 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1130 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1131 mibitem.data = rrq->value /= 1024;
1133 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1134 result = p80211req_dorequest(wlandev, (u8*)&msg);
1141 if (rrq->flags & IW_RETRY_LONG) {
1142 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1143 mibitem.data = rrq->value;
1145 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1146 result = p80211req_dorequest(wlandev, (u8*)&msg);
1154 if (rrq->flags & IW_RETRY_SHORT) {
1155 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1156 mibitem.data = rrq->value;
1158 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1159 result = p80211req_dorequest(wlandev, (u8*)&msg);
1174 static int p80211wext_siwtxpow(netdevice_t *dev,
1175 struct iw_request_info *info,
1176 struct iw_param *rrq, char *extra)
1178 wlandevice_t *wlandev = dev->ml_priv;
1179 p80211item_uint32_t mibitem;
1180 p80211msg_dot11req_mibset_t msg;
1186 if (!wlan_wext_write) {
1187 err = (-EOPNOTSUPP);
1191 msg.msgcode = DIDmsg_dot11req_mibset;
1192 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1193 if (rrq->fixed == 0)
1196 mibitem.data = rrq->value;
1197 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1198 result = p80211req_dorequest(wlandev, (u8*)&msg);
1210 static int p80211wext_giwtxpow(netdevice_t *dev,
1211 struct iw_request_info *info,
1212 struct iw_param *rrq, char *extra)
1214 wlandevice_t *wlandev = dev->ml_priv;
1215 p80211item_uint32_t mibitem;
1216 p80211msg_dot11req_mibset_t msg;
1222 msg.msgcode = DIDmsg_dot11req_mibget;
1223 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1225 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1226 result = p80211req_dorequest(wlandev, (u8*)&msg);
1233 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1235 // XXX handle OFF by setting disabled = 1;
1237 rrq->flags = 0; // IW_TXPOW_DBM;
1240 rrq->value = mibitem.data;
1247 static int p80211wext_siwspy(netdevice_t *dev,
1248 struct iw_request_info *info,
1249 struct iw_point *srq, char *extra)
1251 wlandevice_t *wlandev = dev->ml_priv;
1252 struct sockaddr address[IW_MAX_SPY];
1253 int number = srq->length;
1258 /* Copy the data from the input buffer */
1259 memcpy(address, extra, sizeof(struct sockaddr)*number);
1261 wlandev->spy_number = 0;
1265 /* extract the addresses */
1266 for (i = 0; i < number; i++) {
1268 memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN);
1272 memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
1274 /* set number of addresses */
1275 wlandev->spy_number = number;
1282 /* jkriegl: from orinoco, modified */
1283 static int p80211wext_giwspy(netdevice_t *dev,
1284 struct iw_request_info *info,
1285 struct iw_point *srq, char *extra)
1287 wlandevice_t *wlandev = dev->ml_priv;
1289 struct sockaddr address[IW_MAX_SPY];
1290 struct iw_quality spy_stat[IW_MAX_SPY];
1296 number = wlandev->spy_number;
1300 /* populate address and spy struct's */
1301 for (i = 0; i < number; i++) {
1302 memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN);
1303 address[i].sa_family = AF_UNIX;
1304 memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality));
1307 /* reset update flag */
1308 for (i=0; i < number; i++)
1309 wlandev->spy_stat[i].updated = 0;
1312 /* push stuff to user space */
1313 srq->length = number;
1314 memcpy(extra, address, sizeof(struct sockaddr)*number);
1315 memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number);
1321 static int prism2_result2err (int prism2_result)
1325 switch (prism2_result) {
1326 case P80211ENUM_resultcode_invalid_parameters:
1329 case P80211ENUM_resultcode_implementation_failure:
1332 case P80211ENUM_resultcode_not_supported:
1343 static int p80211wext_siwscan(netdevice_t *dev,
1344 struct iw_request_info *info,
1345 struct iw_point *srq, char *extra)
1347 wlandevice_t *wlandev = dev->ml_priv;
1348 p80211msg_dot11req_scan_t msg;
1355 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1356 WLAN_LOG_ERROR("Can't scan in AP mode\n");
1357 err = (-EOPNOTSUPP);
1361 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1362 msg.msgcode = DIDmsg_dot11req_scan;
1363 msg.bsstype.data = P80211ENUM_bsstype_any;
1365 memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t));
1366 msg.bssid.data.len = 6;
1368 msg.scantype.data = P80211ENUM_scantype_active;
1369 msg.probedelay.data = 0;
1371 for (i = 1; i <= 14; i++)
1372 msg.channellist.data.data[i-1] = i;
1373 msg.channellist.data.len = 14;
1375 msg.maxchanneltime.data = 250;
1376 msg.minchanneltime.data = 200;
1378 result = p80211req_dorequest(wlandev, (u8*)&msg);
1380 err = prism2_result2err (msg.resultcode.data);
1388 /* Helper to translate scan into Wireless Extensions scan results.
1389 * Inspired by the prism54 code, which was in turn inspired by the
1393 wext_translate_bss(struct iw_request_info *info, char *current_ev,
1394 char *end_buf, p80211msg_dot11req_scan_results_t *bss)
1396 struct iw_event iwe; /* Temporary buffer */
1398 /* The first entry must be the MAC address */
1399 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1400 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1401 iwe.cmd = SIOCGIWAP;
1402 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
1404 /* The following entries will be displayed in the same order we give them */
1407 if (bss->ssid.data.len > 0) {
1408 char essid[IW_ESSID_MAX_SIZE + 1];
1411 size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len);
1412 memset(&essid, 0, sizeof (essid));
1413 memcpy(&essid, bss->ssid.data.data, size);
1414 WLAN_LOG_DEBUG(1, " essid size = %d\n", size);
1415 iwe.u.data.length = size;
1416 iwe.u.data.flags = 1;
1417 iwe.cmd = SIOCGIWESSID;
1418 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]);
1419 WLAN_LOG_DEBUG(1, " essid size OK.\n");
1422 switch (bss->bsstype.data) {
1423 case P80211ENUM_bsstype_infrastructure:
1424 iwe.u.mode = IW_MODE_MASTER;
1427 case P80211ENUM_bsstype_independent:
1428 iwe.u.mode = IW_MODE_ADHOC;
1435 iwe.cmd = SIOCGIWMODE;
1437 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
1439 /* Encryption capability */
1440 if (bss->privacy.data == P80211ENUM_truth_true)
1441 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1443 iwe.u.data.flags = IW_ENCODE_DISABLED;
1444 iwe.u.data.length = 0;
1445 iwe.cmd = SIOCGIWENCODE;
1446 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1448 /* Add frequency. (short) bss->channel is the frequency in MHz */
1449 iwe.u.freq.m = bss->dschannel.data;
1451 iwe.cmd = SIOCGIWFREQ;
1452 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
1454 /* Add quality statistics */
1455 iwe.u.qual.level = bss->signal.data;
1456 iwe.u.qual.noise = bss->noise.data;
1457 /* do a simple SNR for quality */
1458 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1460 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
1466 static int p80211wext_giwscan(netdevice_t *dev,
1467 struct iw_request_info *info,
1468 struct iw_point *srq, char *extra)
1470 wlandevice_t *wlandev = dev->ml_priv;
1471 p80211msg_dot11req_scan_results_t msg;
1476 char *current_ev = extra;
1480 /* Since wireless tools doesn't really have a way of passing how
1481 * many scan results results there were back here, keep grabbing them
1485 memset(&msg, 0, sizeof(msg));
1486 msg.msgcode = DIDmsg_dot11req_scan_results;
1487 msg.bssindex.data = i;
1489 result = p80211req_dorequest(wlandev, (u8*)&msg);
1490 if ((result != 0) ||
1491 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1495 current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg);
1498 } while (i < IW_MAX_AP);
1500 srq->length = (current_ev - extra);
1501 srq->flags = 0; /* todo */
1503 if (result && !scan_good)
1504 err = prism2_result2err (msg.resultcode.data);
1510 /*****************************************************/
1511 //extra wireless extensions stuff to support NetworkManager (I hope)
1513 /* SIOCSIWENCODEEXT */
1514 static int p80211wext_set_encodeext(struct net_device *dev,
1515 struct iw_request_info *info,
1516 union iwreq_data *wrqu, char *extra)
1518 wlandevice_t *wlandev = dev->ml_priv;
1519 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1520 p80211msg_dot11req_mibset_t msg;
1521 p80211item_pstr32_t *pstr;
1524 struct iw_point *encoding = &wrqu->encoding;
1525 int idx = encoding->flags & IW_ENCODE_INDEX;
1527 WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1530 if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
1531 // set default key ? I'm not sure if this the the correct thing to do here
1534 if (idx < 1 || idx > NUM_WEPKEYS) {
1539 WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx);
1540 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx);
1546 if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) {
1547 if (!(ext->alg & IW_ENCODE_ALG_WEP)) {
1548 WLAN_LOG_DEBUG(1,"asked to set a non wep key :(");
1552 if (idx <1 || idx > NUM_WEPKEYS)
1557 WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx);
1558 wlandev->wep_keylens[idx] = ext->key_len;
1559 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1561 memset( &msg,0,sizeof(msg));
1562 pstr = (p80211item_pstr32_t*)&msg.mibattribute.data;
1563 memcpy(pstr->data.data, ext->key,ext->key_len);
1564 pstr->data.len = ext->key_len;
1567 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1570 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1573 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1576 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1581 msg.msgcode = DIDmsg_dot11req_mibset;
1582 result = p80211req_dorequest(wlandev,(u8*)&msg);
1583 WLAN_LOG_DEBUG(1,"result (%d)\n",result);
1588 /* SIOCGIWENCODEEXT */
1589 static int p80211wext_get_encodeext(struct net_device *dev,
1590 struct iw_request_info *info,
1591 union iwreq_data *wrqu, char *extra)
1594 wlandevice_t *wlandev = dev->ml_priv;
1595 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1597 struct iw_point *encoding = &wrqu->encoding;
1604 WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1607 max_len = encoding->length - sizeof(*ext);
1608 if ( max_len <= 0) {
1609 WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len);
1613 idx = encoding->flags & IW_ENCODE_INDEX;
1615 WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx);
1618 if (idx < 1 || idx > NUM_WEPKEYS ) {
1619 WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx);
1625 /* default key ? not sure what to do */
1626 /* will just use key[0] for now ! FIX ME */
1629 encoding->flags = idx + 1;
1630 memset(ext,0,sizeof(*ext));
1632 ext->alg = IW_ENCODE_ALG_WEP;
1633 ext->key_len = wlandev->wep_keylens[idx];
1634 memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len );
1636 encoding->flags |= IW_ENCODE_ENABLED;
1645 static int p80211_wext_set_iwauth (struct net_device *dev,
1646 struct iw_request_info *info,
1647 union iwreq_data *wrqu, char *extra)
1649 wlandevice_t *wlandev = dev->ml_priv;
1650 struct iw_param *param = &wrqu->param;
1653 WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1655 switch (param->flags & IW_AUTH_INDEX) {
1656 case IW_AUTH_DROP_UNENCRYPTED:
1657 WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value);
1659 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
1661 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
1664 case IW_AUTH_PRIVACY_INVOKED:
1665 WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value);
1667 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
1669 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
1673 case IW_AUTH_80211_AUTH_ALG:
1674 if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) {
1675 WLAN_LOG_DEBUG(1,"set open_system\n");
1676 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1677 } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) {
1678 WLAN_LOG_DEBUG(1,"set shared key\n");
1679 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1681 /* don't know what to do know :( */
1682 WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value);
1697 static int p80211_wext_get_iwauth (struct net_device *dev,
1698 struct iw_request_info *info,
1699 union iwreq_data *wrqu, char *extra)
1701 wlandevice_t *wlandev = dev->ml_priv;
1702 struct iw_param *param = &wrqu->param;
1705 WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1707 switch (param->flags & IW_AUTH_INDEX) {
1708 case IW_AUTH_DROP_UNENCRYPTED:
1709 param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0;
1712 case IW_AUTH_PRIVACY_INVOKED:
1713 param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0;
1716 case IW_AUTH_80211_AUTH_ALG:
1717 param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM;
1730 static iw_handler p80211wext_handlers[] = {
1731 (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
1732 (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
1733 (iw_handler) NULL, /* SIOCSIWNWID */
1734 (iw_handler) NULL, /* SIOCGIWNWID */
1735 (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
1736 (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
1737 (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
1738 (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
1739 (iw_handler) NULL, /* SIOCSIWSENS */
1740 (iw_handler) NULL, /* SIOCGIWSENS */
1741 (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */
1742 (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
1743 (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */
1744 (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */
1745 (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */
1746 (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */
1747 (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
1748 (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
1749 (iw_handler) NULL, /* -- hole -- */
1750 (iw_handler) NULL, /* -- hole -- */
1751 (iw_handler) NULL, /* SIOCSIWAP */
1752 (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
1753 (iw_handler) NULL, /* -- hole -- */
1754 (iw_handler) NULL, /* SIOCGIWAPLIST */
1755 (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
1756 (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
1757 (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
1758 (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
1759 (iw_handler) NULL, /* SIOCSIWNICKN */
1760 (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
1761 (iw_handler) NULL, /* -- hole -- */
1762 (iw_handler) NULL, /* -- hole -- */
1763 (iw_handler) NULL, /* SIOCSIWRATE */
1764 (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
1765 (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
1766 (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
1767 (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
1768 (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
1769 (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
1770 (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
1771 (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
1772 (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
1773 (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
1774 (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
1775 (iw_handler) NULL, /* SIOCSIWPOWER */
1776 (iw_handler) NULL, /* SIOCGIWPOWER */
1777 /* WPA operations */
1778 (iw_handler) NULL, /* -- hole -- */
1779 (iw_handler) NULL, /* -- hole -- */
1780 (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
1781 (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
1782 (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
1783 (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
1785 (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
1786 (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
1787 (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
1790 struct iw_handler_def p80211wext_handler_def = {
1791 .num_standard = sizeof(p80211wext_handlers) / sizeof(iw_handler),
1793 .num_private_args = 0,
1794 .standard = p80211wext_handlers,
1796 .private_args = NULL,
1797 .get_wireless_stats = p80211wext_get_wireless_stats
1801 int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
1803 union iwreq_data data;
1807 /* Send the association state first */
1808 data.ap_addr.sa_family = ARPHRD_ETHER;
1810 memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN);
1812 memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN);
1815 if (wlan_wext_write)
1816 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1818 if (!assoc) goto done;
1820 // XXX send association data, like IEs, etc etc.