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>
54 #include <linux/if_ether.h>
55 #include <linux/bitops.h>
57 /*================================================================*/
58 /* Project Includes */
60 #include "wlan_compat.h"
62 #include "p80211types.h"
63 #include "p80211hdr.h"
64 #include "p80211conv.h"
65 #include "p80211mgmt.h"
66 #include "p80211msg.h"
67 #include "p80211metastruct.h"
68 #include "p80211metadef.h"
69 #include "p80211netdev.h"
70 #include "p80211ioctl.h"
71 #include "p80211req.h"
73 static int p80211wext_giwrate(netdevice_t *dev,
74 struct iw_request_info *info,
75 struct iw_param *rrq, char *extra);
76 static int p80211wext_giwessid(netdevice_t *dev,
77 struct iw_request_info *info,
78 struct iw_point *data, char *essid);
80 static u8 p80211_mhz_to_channel(u16 mhz)
83 return ((mhz - 5000) / 5);
90 return ((mhz - 2407) / 5);
96 static u16 p80211_channel_to_mhz(u8 ch, int dot11a)
107 return (5000 + (5 * ch));
115 if ((ch < 14) && (ch > 0)) {
116 return (2407 + (5 * ch));
122 /* taken from orinoco.c ;-) */
123 static const long p80211wext_channel_freq[] = {
124 2412, 2417, 2422, 2427, 2432, 2437, 2442,
125 2447, 2452, 2457, 2462, 2467, 2472, 2484
127 #define NUM_CHANNELS ARRAY_SIZE(p80211wext_channel_freq)
129 /* steal a spare bit to store the shared/opensystems state. should default to open if not set */
130 #define HOSTWEP_SHAREDKEY BIT(3)
133 /** function declarations =============== */
135 static int qual_as_percent(int snr ) {
146 static int p80211wext_dorequest(wlandevice_t *wlandev, u32 did, u32 data)
148 p80211msg_dot11req_mibset_t msg;
149 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);
161 static int p80211wext_autojoin(wlandevice_t *wlandev)
163 p80211msg_lnxreq_autojoin_t msg;
164 struct iw_point data;
165 char ssid[IW_ESSID_MAX_SIZE];
171 result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid);
178 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
179 msg.authtype.data = P80211ENUM_authalg_sharedkey;
181 msg.authtype.data = P80211ENUM_authalg_opensystem;
183 msg.msgcode = DIDmsg_lnxreq_autojoin;
185 /* Trim the last '\0' to fit the SSID format */
187 if (data.length && ssid[data.length-1] == '\0') {
188 data.length = data.length - 1;
191 memcpy(msg.ssid.data.data, ssid, data.length);
192 msg.ssid.data.len = data.length;
194 result = p80211req_dorequest(wlandev, (u8*)&msg);
207 /* called by /proc/net/wireless */
208 struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev)
210 p80211msg_lnxreq_commsquality_t quality;
211 wlandevice_t *wlandev = dev->ml_priv;
212 struct iw_statistics* wstats = &wlandev->wstats;
216 if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) )
219 /* XXX Only valid in station mode */
222 /* build request message */
223 quality.msgcode = DIDmsg_lnxreq_commsquality;
224 quality.dbm.data = P80211ENUM_truth_true;
225 quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
227 /* send message to nsd */
228 if ( wlandev->mlmerequest == NULL )
231 retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality);
233 wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
234 wstats->qual.level = quality.level.data; /* instant signal level */
235 wstats->qual.noise = quality.noise.data; /* instant noise level */
237 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
238 wstats->discard.code = wlandev->rx.decrypt_err;
239 wstats->discard.nwid = 0;
240 wstats->discard.misc = 0;
242 wstats->discard.fragment = 0; // incomplete fragments
243 wstats->discard.retries = 0; // tx retries.
244 wstats->miss.beacon = 0;
249 static int p80211wext_giwname(netdevice_t *dev,
250 struct iw_request_info *info,
251 char *name, char *extra)
253 struct iw_param rate;
257 result = p80211wext_giwrate(dev, NULL, &rate, NULL);
264 switch (rate.value) {
267 strcpy(name, "IEEE 802.11-DS");
271 strcpy(name, "IEEE 802.11-b");
278 static int p80211wext_giwfreq(netdevice_t *dev,
279 struct iw_request_info *info,
280 struct iw_freq *freq, char *extra)
282 wlandevice_t *wlandev = dev->ml_priv;
283 p80211item_uint32_t mibitem;
284 p80211msg_dot11req_mibset_t msg;
288 msg.msgcode = DIDmsg_dot11req_mibget;
289 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
290 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
291 result = p80211req_dorequest(wlandev, (u8*)&msg);
298 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
300 if (mibitem.data > NUM_CHANNELS) {
305 /* convert into frequency instead of a channel */
307 freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000;
313 static int p80211wext_siwfreq(netdevice_t *dev,
314 struct iw_request_info *info,
315 struct iw_freq *freq, char *extra)
317 wlandevice_t *wlandev = dev->ml_priv;
318 p80211item_uint32_t mibitem;
319 p80211msg_dot11req_mibset_t msg;
323 if (!wlan_wext_write) {
328 msg.msgcode = DIDmsg_dot11req_mibset;
329 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
330 mibitem.status = P80211ENUM_msgitem_status_data_ok;
332 if ( (freq->e == 0) && (freq->m <= 1000) )
333 mibitem.data = freq->m;
335 mibitem.data = p80211_mhz_to_channel(freq->m);
337 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
338 result = p80211req_dorequest(wlandev, (u8*)&msg);
349 static int p80211wext_giwmode(netdevice_t *dev,
350 struct iw_request_info *info,
351 __u32 *mode, char *extra)
353 wlandevice_t *wlandev = dev->ml_priv;
355 switch (wlandev->macmode) {
356 case WLAN_MACMODE_IBSS_STA:
357 *mode = IW_MODE_ADHOC;
359 case WLAN_MACMODE_ESS_STA:
360 *mode = IW_MODE_INFRA;
362 case WLAN_MACMODE_ESS_AP:
363 *mode = IW_MODE_MASTER;
367 *mode = IW_MODE_AUTO;
373 static int p80211wext_siwmode(netdevice_t *dev,
374 struct iw_request_info *info,
375 __u32 *mode, char *extra)
377 wlandevice_t *wlandev = dev->ml_priv;
378 p80211item_uint32_t mibitem;
379 p80211msg_dot11req_mibset_t msg;
383 if (!wlan_wext_write) {
388 if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
389 *mode != IW_MODE_MASTER) {
394 /* Operation mode is the same with current mode */
395 if (*mode == wlandev->macmode)
400 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
403 wlandev->macmode = WLAN_MACMODE_ESS_STA;
406 wlandev->macmode = WLAN_MACMODE_ESS_AP;
410 printk(KERN_INFO "Operation mode: %d not support\n", *mode);
414 /* Set Operation mode to the PORT TYPE RID */
415 msg.msgcode = DIDmsg_dot11req_mibset;
416 mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
417 mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
418 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
419 result = p80211req_dorequest(wlandev, (u8*)&msg);
429 static int p80211wext_giwrange(netdevice_t *dev,
430 struct iw_request_info *info,
431 struct iw_point *data, char *extra)
433 struct iw_range *range = (struct iw_range *) extra;
436 // for backward compatability set size & zero everything we don't understand
437 data->length = sizeof(*range);
438 memset(range,0,sizeof(*range));
440 range->txpower_capa = IW_TXPOW_DBM;
441 // XXX what about min/max_pmp, min/max_pmt, etc.
443 range->we_version_compiled = WIRELESS_EXT;
444 range->we_version_source = 13;
446 range->retry_capa = IW_RETRY_LIMIT;
447 range->retry_flags = IW_RETRY_LIMIT;
448 range->min_retry = 0;
449 range->max_retry = 255;
451 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | //mode/freq/ssid
452 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
453 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
454 range->event_capa[1] = IW_EVENT_CAPA_K_1; //encode
455 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
456 IW_EVENT_CAPA_MASK(IWEVCUSTOM) );
458 range->num_channels = NUM_CHANNELS;
460 /* XXX need to filter against the regulatory domain &| active set */
462 for (i = 0; i < NUM_CHANNELS ; i++) {
463 range->freq[val].i = i + 1;
464 range->freq[val].m = p80211wext_channel_freq[i] * 100000;
465 range->freq[val].e = 1;
469 range->num_frequency = val;
471 /* Max of /proc/net/wireless */
472 range->max_qual.qual = 100;
473 range->max_qual.level = 0;
474 range->max_qual.noise = 0;
475 range->sensitivity = 3;
476 // XXX these need to be nsd-specific!
479 range->max_rts = 2347;
480 range->min_frag = 256;
481 range->max_frag = 2346;
483 range->max_encoding_tokens = NUM_WEPKEYS;
484 range->num_encoding_sizes = 2;
485 range->encoding_size[0] = 5;
486 range->encoding_size[1] = 13;
488 // XXX what about num_bitrates/throughput?
489 range->num_bitrates = 0;
491 /* estimated max throughput */
492 // XXX need to cap it if we're running at ~2Mbps..
493 range->throughput = 5500000;
498 static int p80211wext_giwap(netdevice_t *dev,
499 struct iw_request_info *info,
500 struct sockaddr *ap_addr, char *extra)
503 wlandevice_t *wlandev = dev->ml_priv;
505 memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
506 ap_addr->sa_family = ARPHRD_ETHER;
511 static int p80211wext_giwencode(netdevice_t *dev,
512 struct iw_request_info *info,
513 struct iw_point *erq, char *key)
515 wlandevice_t *wlandev = dev->ml_priv;
519 i = (erq->flags & IW_ENCODE_INDEX) - 1;
522 if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
523 erq->flags |= IW_ENCODE_ENABLED;
525 erq->flags |= IW_ENCODE_DISABLED;
527 if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
528 erq->flags |= IW_ENCODE_RESTRICTED;
530 erq->flags |= IW_ENCODE_OPEN;
532 i = (erq->flags & IW_ENCODE_INDEX) - 1;
535 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
537 if ((i < 0) || (i >= NUM_WEPKEYS)) {
544 /* copy the key from the driver cache as the keys are read-only MIBs */
545 erq->length = wlandev->wep_keylens[i];
546 memcpy(key, wlandev->wep_keys[i], erq->length);
552 static int p80211wext_siwencode(netdevice_t *dev,
553 struct iw_request_info *info,
554 struct iw_point *erq, char *key)
556 wlandevice_t *wlandev = dev->ml_priv;
557 p80211msg_dot11req_mibset_t msg;
558 p80211item_pstr32_t pstr;
564 if (!wlan_wext_write) {
569 /* Check the Key index first. */
570 if((i = (erq->flags & IW_ENCODE_INDEX))) {
572 if ((i < 1) || (i > NUM_WEPKEYS)) {
579 /* Set current key number only if no keys are given */
580 if (erq->flags & IW_ENCODE_NOKEY) {
581 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i);
590 // Use defaultkey if no Key Index
591 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
594 /* Check if there is no key information in the iwconfig request */
595 if((erq->flags & IW_ENCODE_NOKEY) == 0 ) {
597 /*------------------------------------------------------------
598 * If there is WEP Key for setting, check the Key Information
599 * and then set it to the firmware.
600 -------------------------------------------------------------*/
602 if (erq->length > 0) {
604 /* copy the key from the driver cache as the keys are read-only MIBs */
605 wlandev->wep_keylens[i] = erq->length;
606 memcpy(wlandev->wep_keys[i], key, erq->length);
608 /* Prepare data struture for p80211req_dorequest. */
609 memcpy(pstr.data.data, key, erq->length);
610 pstr.data.len = erq->length;
615 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
619 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
623 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
627 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
635 msg.msgcode = DIDmsg_dot11req_mibset;
636 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
637 result = p80211req_dorequest(wlandev, (u8*)&msg);
647 /* Check the PrivacyInvoked flag */
648 if (erq->flags & IW_ENCODE_DISABLED) {
649 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
651 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
659 /* The security mode may be open or restricted, and its meaning
660 depends on the card used. With most cards, in open mode no
661 authentication is used and the card may also accept non-
662 encrypted sessions, whereas in restricted mode only encrypted
663 sessions are accepted and the card will use authentication if
666 if (erq->flags & IW_ENCODE_RESTRICTED) {
667 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
669 else if (erq->flags & IW_ENCODE_OPEN) {
670 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
683 static int p80211wext_giwessid(netdevice_t *dev,
684 struct iw_request_info *info,
685 struct iw_point *data, char *essid)
687 wlandevice_t *wlandev = dev->ml_priv;
689 if (wlandev->ssid.len) {
690 data->length = wlandev->ssid.len;
692 memcpy(essid, wlandev->ssid.data, data->length);
693 essid[data->length] = 0;
694 #if (WIRELESS_EXT < 21)
698 memset(essid, 0, sizeof(wlandev->ssid.data));
706 static int p80211wext_siwessid(netdevice_t *dev,
707 struct iw_request_info *info,
708 struct iw_point *data, char *essid)
710 wlandevice_t *wlandev = dev->ml_priv;
711 p80211msg_lnxreq_autojoin_t msg;
715 int length = data->length;
717 if (!wlan_wext_write) {
723 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
724 msg.authtype.data = P80211ENUM_authalg_sharedkey;
726 msg.authtype.data = P80211ENUM_authalg_opensystem;
728 msg.msgcode = DIDmsg_lnxreq_autojoin;
730 #if (WIRELESS_EXT < 21)
731 if (length) length--;
734 /* Trim the last '\0' to fit the SSID format */
736 if (length && essid[length-1] == '\0') {
740 memcpy(msg.ssid.data.data, essid, length);
741 msg.ssid.data.len = length;
743 WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid);
744 result = p80211req_dorequest(wlandev, (u8*)&msg);
745 WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result);
757 static int p80211wext_siwcommit(netdevice_t *dev,
758 struct iw_request_info *info,
759 struct iw_point *data, char *essid)
761 wlandevice_t *wlandev = dev->ml_priv;
764 if (!wlan_wext_write) {
770 err = p80211wext_autojoin(wlandev);
777 static int p80211wext_giwrate(netdevice_t *dev,
778 struct iw_request_info *info,
779 struct iw_param *rrq, char *extra)
781 wlandevice_t *wlandev = dev->ml_priv;
782 p80211item_uint32_t mibitem;
783 p80211msg_dot11req_mibset_t msg;
787 msg.msgcode = DIDmsg_dot11req_mibget;
788 mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
789 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
790 result = p80211req_dorequest(wlandev, (u8*)&msg);
797 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
799 rrq->fixed = 0; /* can it change? */
803 #define HFA384x_RATEBIT_1 ((u16)1)
804 #define HFA384x_RATEBIT_2 ((u16)2)
805 #define HFA384x_RATEBIT_5dot5 ((u16)4)
806 #define HFA384x_RATEBIT_11 ((u16)8)
808 switch (mibitem.data) {
809 case HFA384x_RATEBIT_1:
810 rrq->value = 1000000;
812 case HFA384x_RATEBIT_2:
813 rrq->value = 2000000;
815 case HFA384x_RATEBIT_5dot5:
816 rrq->value = 5500000;
818 case HFA384x_RATEBIT_11:
819 rrq->value = 11000000;
828 static int p80211wext_giwrts(netdevice_t *dev,
829 struct iw_request_info *info,
830 struct iw_param *rts, char *extra)
832 wlandevice_t *wlandev = dev->ml_priv;
833 p80211item_uint32_t mibitem;
834 p80211msg_dot11req_mibset_t msg;
838 msg.msgcode = DIDmsg_dot11req_mibget;
839 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
840 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
841 result = p80211req_dorequest(wlandev, (u8*)&msg);
848 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
850 rts->value = mibitem.data;
851 rts->disabled = (rts->value == 2347);
859 static int p80211wext_siwrts(netdevice_t *dev,
860 struct iw_request_info *info,
861 struct iw_param *rts, char *extra)
863 wlandevice_t *wlandev = dev->ml_priv;
864 p80211item_uint32_t mibitem;
865 p80211msg_dot11req_mibset_t msg;
869 if (!wlan_wext_write) {
874 msg.msgcode = DIDmsg_dot11req_mibget;
875 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
879 mibitem.data = rts->value;
881 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
882 result = p80211req_dorequest(wlandev, (u8*)&msg);
893 static int p80211wext_giwfrag(netdevice_t *dev,
894 struct iw_request_info *info,
895 struct iw_param *frag, char *extra)
897 wlandevice_t *wlandev = dev->ml_priv;
898 p80211item_uint32_t mibitem;
899 p80211msg_dot11req_mibset_t msg;
903 msg.msgcode = DIDmsg_dot11req_mibget;
904 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
905 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
906 result = p80211req_dorequest(wlandev, (u8*)&msg);
913 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
915 frag->value = mibitem.data;
916 frag->disabled = (frag->value == 2346);
923 static int p80211wext_siwfrag(netdevice_t *dev,
924 struct iw_request_info *info,
925 struct iw_param *frag, char *extra)
927 wlandevice_t *wlandev = dev->ml_priv;
928 p80211item_uint32_t mibitem;
929 p80211msg_dot11req_mibset_t msg;
933 if (!wlan_wext_write) {
938 msg.msgcode = DIDmsg_dot11req_mibset;
939 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
944 mibitem.data = frag->value;
946 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
947 result = p80211req_dorequest(wlandev, (u8*)&msg);
958 #ifndef IW_RETRY_LONG
959 #define IW_RETRY_LONG IW_RETRY_MAX
962 #ifndef IW_RETRY_SHORT
963 #define IW_RETRY_SHORT IW_RETRY_MIN
966 static int p80211wext_giwretry(netdevice_t *dev,
967 struct iw_request_info *info,
968 struct iw_param *rrq, char *extra)
970 wlandevice_t *wlandev = dev->ml_priv;
971 p80211item_uint32_t mibitem;
972 p80211msg_dot11req_mibset_t msg;
975 u16 shortretry, longretry, lifetime;
977 msg.msgcode = DIDmsg_dot11req_mibget;
978 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
980 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
981 result = p80211req_dorequest(wlandev, (u8*)&msg);
988 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
990 shortretry = mibitem.data;
992 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
994 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
995 result = p80211req_dorequest(wlandev, (u8*)&msg);
1002 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1004 longretry = mibitem.data;
1006 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1008 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1009 result = p80211req_dorequest(wlandev, (u8*)&msg);
1016 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1018 lifetime = mibitem.data;
1022 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1023 rrq->flags = IW_RETRY_LIFETIME;
1024 rrq->value = lifetime * 1024;
1026 if (rrq->flags & IW_RETRY_LONG) {
1027 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1028 rrq->value = longretry;
1030 rrq->flags = IW_RETRY_LIMIT;
1031 rrq->value = shortretry;
1032 if (shortretry != longretry)
1033 rrq->flags |= IW_RETRY_SHORT;
1042 static int p80211wext_siwretry(netdevice_t *dev,
1043 struct iw_request_info *info,
1044 struct iw_param *rrq, char *extra)
1046 wlandevice_t *wlandev = dev->ml_priv;
1047 p80211item_uint32_t mibitem;
1048 p80211msg_dot11req_mibset_t msg;
1052 if (!wlan_wext_write) {
1053 err = (-EOPNOTSUPP);
1057 if (rrq->disabled) {
1062 msg.msgcode = DIDmsg_dot11req_mibset;
1064 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1065 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1066 mibitem.data = rrq->value /= 1024;
1068 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1069 result = p80211req_dorequest(wlandev, (u8*)&msg);
1076 if (rrq->flags & IW_RETRY_LONG) {
1077 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1078 mibitem.data = rrq->value;
1080 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1081 result = p80211req_dorequest(wlandev, (u8*)&msg);
1089 if (rrq->flags & IW_RETRY_SHORT) {
1090 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1091 mibitem.data = rrq->value;
1093 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1094 result = p80211req_dorequest(wlandev, (u8*)&msg);
1108 static int p80211wext_siwtxpow(netdevice_t *dev,
1109 struct iw_request_info *info,
1110 struct iw_param *rrq, char *extra)
1112 wlandevice_t *wlandev = dev->ml_priv;
1113 p80211item_uint32_t mibitem;
1114 p80211msg_dot11req_mibset_t msg;
1118 if (!wlan_wext_write) {
1119 err = (-EOPNOTSUPP);
1123 msg.msgcode = DIDmsg_dot11req_mibset;
1124 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1125 if (rrq->fixed == 0)
1128 mibitem.data = rrq->value;
1129 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1130 result = p80211req_dorequest(wlandev, (u8*)&msg);
1141 static int p80211wext_giwtxpow(netdevice_t *dev,
1142 struct iw_request_info *info,
1143 struct iw_param *rrq, char *extra)
1145 wlandevice_t *wlandev = dev->ml_priv;
1146 p80211item_uint32_t mibitem;
1147 p80211msg_dot11req_mibset_t msg;
1151 msg.msgcode = DIDmsg_dot11req_mibget;
1152 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1154 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1155 result = p80211req_dorequest(wlandev, (u8*)&msg);
1162 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1164 // XXX handle OFF by setting disabled = 1;
1166 rrq->flags = 0; // IW_TXPOW_DBM;
1169 rrq->value = mibitem.data;
1175 static int p80211wext_siwspy(netdevice_t *dev,
1176 struct iw_request_info *info,
1177 struct iw_point *srq, char *extra)
1179 wlandevice_t *wlandev = dev->ml_priv;
1180 struct sockaddr address[IW_MAX_SPY];
1181 int number = srq->length;
1185 /* Copy the data from the input buffer */
1186 memcpy(address, extra, sizeof(struct sockaddr)*number);
1188 wlandev->spy_number = 0;
1192 /* extract the addresses */
1193 for (i = 0; i < number; i++) {
1195 memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN);
1199 memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
1201 /* set number of addresses */
1202 wlandev->spy_number = number;
1208 /* jkriegl: from orinoco, modified */
1209 static int p80211wext_giwspy(netdevice_t *dev,
1210 struct iw_request_info *info,
1211 struct iw_point *srq, char *extra)
1213 wlandevice_t *wlandev = dev->ml_priv;
1215 struct sockaddr address[IW_MAX_SPY];
1216 struct iw_quality spy_stat[IW_MAX_SPY];
1220 number = wlandev->spy_number;
1224 /* populate address and spy struct's */
1225 for (i = 0; i < number; i++) {
1226 memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN);
1227 address[i].sa_family = AF_UNIX;
1228 memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality));
1231 /* reset update flag */
1232 for (i=0; i < number; i++)
1233 wlandev->spy_stat[i].updated = 0;
1236 /* push stuff to user space */
1237 srq->length = number;
1238 memcpy(extra, address, sizeof(struct sockaddr)*number);
1239 memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number);
1244 static int prism2_result2err (int prism2_result)
1248 switch (prism2_result) {
1249 case P80211ENUM_resultcode_invalid_parameters:
1252 case P80211ENUM_resultcode_implementation_failure:
1255 case P80211ENUM_resultcode_not_supported:
1266 static int p80211wext_siwscan(netdevice_t *dev,
1267 struct iw_request_info *info,
1268 struct iw_point *srq, char *extra)
1270 wlandevice_t *wlandev = dev->ml_priv;
1271 p80211msg_dot11req_scan_t msg;
1276 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1277 WLAN_LOG_ERROR("Can't scan in AP mode\n");
1278 err = (-EOPNOTSUPP);
1282 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1283 msg.msgcode = DIDmsg_dot11req_scan;
1284 msg.bsstype.data = P80211ENUM_bsstype_any;
1286 memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t));
1287 msg.bssid.data.len = 6;
1289 msg.scantype.data = P80211ENUM_scantype_active;
1290 msg.probedelay.data = 0;
1292 for (i = 1; i <= 14; i++)
1293 msg.channellist.data.data[i-1] = i;
1294 msg.channellist.data.len = 14;
1296 msg.maxchanneltime.data = 250;
1297 msg.minchanneltime.data = 200;
1299 result = p80211req_dorequest(wlandev, (u8*)&msg);
1301 err = prism2_result2err (msg.resultcode.data);
1308 /* Helper to translate scan into Wireless Extensions scan results.
1309 * Inspired by the prism54 code, which was in turn inspired by the
1313 wext_translate_bss(struct iw_request_info *info, char *current_ev,
1314 char *end_buf, p80211msg_dot11req_scan_results_t *bss)
1316 struct iw_event iwe; /* Temporary buffer */
1318 /* The first entry must be the MAC address */
1319 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1320 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1321 iwe.cmd = SIOCGIWAP;
1322 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
1324 /* The following entries will be displayed in the same order we give them */
1327 if (bss->ssid.data.len > 0) {
1328 char essid[IW_ESSID_MAX_SIZE + 1];
1331 size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len);
1332 memset(&essid, 0, sizeof (essid));
1333 memcpy(&essid, bss->ssid.data.data, size);
1334 WLAN_LOG_DEBUG(1, " essid size = %d\n", size);
1335 iwe.u.data.length = size;
1336 iwe.u.data.flags = 1;
1337 iwe.cmd = SIOCGIWESSID;
1338 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]);
1339 WLAN_LOG_DEBUG(1, " essid size OK.\n");
1342 switch (bss->bsstype.data) {
1343 case P80211ENUM_bsstype_infrastructure:
1344 iwe.u.mode = IW_MODE_MASTER;
1347 case P80211ENUM_bsstype_independent:
1348 iwe.u.mode = IW_MODE_ADHOC;
1355 iwe.cmd = SIOCGIWMODE;
1357 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
1359 /* Encryption capability */
1360 if (bss->privacy.data == P80211ENUM_truth_true)
1361 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1363 iwe.u.data.flags = IW_ENCODE_DISABLED;
1364 iwe.u.data.length = 0;
1365 iwe.cmd = SIOCGIWENCODE;
1366 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1368 /* Add frequency. (short) bss->channel is the frequency in MHz */
1369 iwe.u.freq.m = bss->dschannel.data;
1371 iwe.cmd = SIOCGIWFREQ;
1372 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
1374 /* Add quality statistics */
1375 iwe.u.qual.level = bss->signal.data;
1376 iwe.u.qual.noise = bss->noise.data;
1377 /* do a simple SNR for quality */
1378 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1380 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
1386 static int p80211wext_giwscan(netdevice_t *dev,
1387 struct iw_request_info *info,
1388 struct iw_point *srq, char *extra)
1390 wlandevice_t *wlandev = dev->ml_priv;
1391 p80211msg_dot11req_scan_results_t msg;
1396 char *current_ev = extra;
1398 /* Since wireless tools doesn't really have a way of passing how
1399 * many scan results results there were back here, keep grabbing them
1403 memset(&msg, 0, sizeof(msg));
1404 msg.msgcode = DIDmsg_dot11req_scan_results;
1405 msg.bssindex.data = i;
1407 result = p80211req_dorequest(wlandev, (u8*)&msg);
1408 if ((result != 0) ||
1409 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1413 current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg);
1416 } while (i < IW_MAX_AP);
1418 srq->length = (current_ev - extra);
1419 srq->flags = 0; /* todo */
1421 if (result && !scan_good)
1422 err = prism2_result2err (msg.resultcode.data);
1427 /*****************************************************/
1428 //extra wireless extensions stuff to support NetworkManager (I hope)
1430 /* SIOCSIWENCODEEXT */
1431 static int p80211wext_set_encodeext(struct net_device *dev,
1432 struct iw_request_info *info,
1433 union iwreq_data *wrqu, char *extra)
1435 wlandevice_t *wlandev = dev->ml_priv;
1436 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1437 p80211msg_dot11req_mibset_t msg;
1438 p80211item_pstr32_t *pstr;
1441 struct iw_point *encoding = &wrqu->encoding;
1442 int idx = encoding->flags & IW_ENCODE_INDEX;
1444 WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1447 if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
1448 // set default key ? I'm not sure if this the the correct thing to do here
1451 if (idx < 1 || idx > NUM_WEPKEYS) {
1456 WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx);
1457 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx);
1463 if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) {
1464 if (!(ext->alg & IW_ENCODE_ALG_WEP)) {
1465 WLAN_LOG_DEBUG(1,"asked to set a non wep key :(");
1469 if (idx <1 || idx > NUM_WEPKEYS)
1474 WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx);
1475 wlandev->wep_keylens[idx] = ext->key_len;
1476 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1478 memset( &msg,0,sizeof(msg));
1479 pstr = (p80211item_pstr32_t*)&msg.mibattribute.data;
1480 memcpy(pstr->data.data, ext->key,ext->key_len);
1481 pstr->data.len = ext->key_len;
1484 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1487 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1490 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1493 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1498 msg.msgcode = DIDmsg_dot11req_mibset;
1499 result = p80211req_dorequest(wlandev,(u8*)&msg);
1500 WLAN_LOG_DEBUG(1,"result (%d)\n",result);
1505 /* SIOCGIWENCODEEXT */
1506 static int p80211wext_get_encodeext(struct net_device *dev,
1507 struct iw_request_info *info,
1508 union iwreq_data *wrqu, char *extra)
1511 wlandevice_t *wlandev = dev->ml_priv;
1512 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1514 struct iw_point *encoding = &wrqu->encoding;
1519 WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1522 max_len = encoding->length - sizeof(*ext);
1523 if ( max_len <= 0) {
1524 WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len);
1528 idx = encoding->flags & IW_ENCODE_INDEX;
1530 WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx);
1533 if (idx < 1 || idx > NUM_WEPKEYS ) {
1534 WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx);
1540 /* default key ? not sure what to do */
1541 /* will just use key[0] for now ! FIX ME */
1544 encoding->flags = idx + 1;
1545 memset(ext,0,sizeof(*ext));
1547 ext->alg = IW_ENCODE_ALG_WEP;
1548 ext->key_len = wlandev->wep_keylens[idx];
1549 memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len );
1551 encoding->flags |= IW_ENCODE_ENABLED;
1558 static int p80211_wext_set_iwauth (struct net_device *dev,
1559 struct iw_request_info *info,
1560 union iwreq_data *wrqu, char *extra)
1562 wlandevice_t *wlandev = dev->ml_priv;
1563 struct iw_param *param = &wrqu->param;
1566 WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1568 switch (param->flags & IW_AUTH_INDEX) {
1569 case IW_AUTH_DROP_UNENCRYPTED:
1570 WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value);
1572 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
1574 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
1577 case IW_AUTH_PRIVACY_INVOKED:
1578 WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value);
1580 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
1582 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
1586 case IW_AUTH_80211_AUTH_ALG:
1587 if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) {
1588 WLAN_LOG_DEBUG(1,"set open_system\n");
1589 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1590 } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) {
1591 WLAN_LOG_DEBUG(1,"set shared key\n");
1592 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1594 /* don't know what to do know :( */
1595 WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value);
1610 static int p80211_wext_get_iwauth (struct net_device *dev,
1611 struct iw_request_info *info,
1612 union iwreq_data *wrqu, char *extra)
1614 wlandevice_t *wlandev = dev->ml_priv;
1615 struct iw_param *param = &wrqu->param;
1618 WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1620 switch (param->flags & IW_AUTH_INDEX) {
1621 case IW_AUTH_DROP_UNENCRYPTED:
1622 param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0;
1625 case IW_AUTH_PRIVACY_INVOKED:
1626 param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0;
1629 case IW_AUTH_80211_AUTH_ALG:
1630 param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM;
1643 static iw_handler p80211wext_handlers[] = {
1644 (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
1645 (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
1646 (iw_handler) NULL, /* SIOCSIWNWID */
1647 (iw_handler) NULL, /* SIOCGIWNWID */
1648 (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
1649 (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
1650 (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
1651 (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
1652 (iw_handler) NULL, /* SIOCSIWSENS */
1653 (iw_handler) NULL, /* SIOCGIWSENS */
1654 (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */
1655 (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
1656 (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */
1657 (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */
1658 (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */
1659 (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */
1660 (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
1661 (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
1662 (iw_handler) NULL, /* -- hole -- */
1663 (iw_handler) NULL, /* -- hole -- */
1664 (iw_handler) NULL, /* SIOCSIWAP */
1665 (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
1666 (iw_handler) NULL, /* -- hole -- */
1667 (iw_handler) NULL, /* SIOCGIWAPLIST */
1668 (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
1669 (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
1670 (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
1671 (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
1672 (iw_handler) NULL, /* SIOCSIWNICKN */
1673 (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
1674 (iw_handler) NULL, /* -- hole -- */
1675 (iw_handler) NULL, /* -- hole -- */
1676 (iw_handler) NULL, /* SIOCSIWRATE */
1677 (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
1678 (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
1679 (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
1680 (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
1681 (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
1682 (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
1683 (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
1684 (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
1685 (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
1686 (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
1687 (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
1688 (iw_handler) NULL, /* SIOCSIWPOWER */
1689 (iw_handler) NULL, /* SIOCGIWPOWER */
1690 /* WPA operations */
1691 (iw_handler) NULL, /* -- hole -- */
1692 (iw_handler) NULL, /* -- hole -- */
1693 (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
1694 (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
1695 (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
1696 (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
1698 (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
1699 (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
1700 (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
1703 struct iw_handler_def p80211wext_handler_def = {
1704 .num_standard = ARRAY_SIZE(p80211wext_handlers),
1706 .num_private_args = 0,
1707 .standard = p80211wext_handlers,
1709 .private_args = NULL,
1710 .get_wireless_stats = p80211wext_get_wireless_stats
1714 int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
1716 union iwreq_data data;
1718 /* Send the association state first */
1719 data.ap_addr.sa_family = ARPHRD_ETHER;
1721 memcpy(data.ap_addr.sa_data, wlandev->bssid, ETH_ALEN);
1723 memset(data.ap_addr.sa_data, 0, ETH_ALEN);
1726 if (wlan_wext_write)
1727 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1729 if (!assoc) goto done;
1731 // XXX send association data, like IEs, etc etc.