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 /*================================================================*/
40 #include <linux/kernel.h>
41 #include <linux/sched.h>
42 #include <linux/types.h>
43 #include <linux/slab.h>
44 #include <linux/netdevice.h>
45 #include <linux/etherdevice.h>
46 #include <linux/wireless.h>
47 #include <net/iw_handler.h>
48 #include <linux/if_arp.h>
49 #include <linux/bitops.h>
50 #include <linux/uaccess.h>
51 #include <asm/byteorder.h>
52 #include <linux/if_ether.h>
53 #include <linux/bitops.h>
55 #include "p80211types.h"
56 #include "p80211hdr.h"
57 #include "p80211conv.h"
58 #include "p80211mgmt.h"
59 #include "p80211msg.h"
60 #include "p80211metastruct.h"
61 #include "p80211metadef.h"
62 #include "p80211netdev.h"
63 #include "p80211ioctl.h"
64 #include "p80211req.h"
66 static int p80211wext_giwrate(netdevice_t *dev,
67 struct iw_request_info *info,
68 struct iw_param *rrq, char *extra);
69 static int p80211wext_giwessid(netdevice_t *dev,
70 struct iw_request_info *info,
71 struct iw_point *data, char *essid);
73 static u8 p80211_mhz_to_channel(u16 mhz)
76 return (mhz - 5000) / 5;
82 return (mhz - 2407) / 5;
87 static u16 p80211_channel_to_mhz(u8 ch, int dot11a)
97 return 5000 + (5 * ch);
103 if ((ch < 14) && (ch > 0))
104 return 2407 + (5 * ch);
109 /* taken from orinoco.c ;-) */
110 static const long p80211wext_channel_freq[] = {
111 2412, 2417, 2422, 2427, 2432, 2437, 2442,
112 2447, 2452, 2457, 2462, 2467, 2472, 2484
115 #define NUM_CHANNELS ARRAY_SIZE(p80211wext_channel_freq)
117 /* steal a spare bit to store the shared/opensystems state.
118 should default to open if not set */
119 #define HOSTWEP_SHAREDKEY BIT(3)
121 static int qual_as_percent(int snr)
130 static int p80211wext_dorequest(wlandevice_t *wlandev, u32 did, u32 data)
132 p80211msg_dot11req_mibset_t msg;
133 p80211item_uint32_t mibitem;
136 msg.msgcode = DIDmsg_dot11req_mibset;
137 memset(&mibitem, 0, sizeof(mibitem));
140 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
141 result = p80211req_dorequest(wlandev, (u8 *) &msg);
146 static int p80211wext_autojoin(wlandevice_t *wlandev)
148 p80211msg_lnxreq_autojoin_t msg;
149 struct iw_point data;
150 char ssid[IW_ESSID_MAX_SIZE];
156 result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid);
163 if (wlandev->hostwep & HOSTWEP_SHAREDKEY)
164 msg.authtype.data = P80211ENUM_authalg_sharedkey;
166 msg.authtype.data = P80211ENUM_authalg_opensystem;
168 msg.msgcode = DIDmsg_lnxreq_autojoin;
170 /* Trim the last '\0' to fit the SSID format */
172 if (data.length && ssid[data.length - 1] == '\0')
173 data.length = data.length - 1;
175 memcpy(msg.ssid.data.data, ssid, data.length);
176 msg.ssid.data.len = data.length;
178 result = p80211req_dorequest(wlandev, (u8 *) &msg);
191 /* called by /proc/net/wireless */
192 struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t *dev)
194 p80211msg_lnxreq_commsquality_t quality;
195 wlandevice_t *wlandev = dev->ml_priv;
196 struct iw_statistics *wstats = &wlandev->wstats;
200 if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING))
203 /* XXX Only valid in station mode */
206 /* build request message */
207 quality.msgcode = DIDmsg_lnxreq_commsquality;
208 quality.dbm.data = P80211ENUM_truth_true;
209 quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
211 /* send message to nsd */
212 if (wlandev->mlmerequest == NULL)
215 retval = wlandev->mlmerequest(wlandev, (p80211msg_t *) &quality);
217 wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
218 wstats->qual.level = quality.level.data; /* instant signal level */
219 wstats->qual.noise = quality.noise.data; /* instant noise level */
221 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
222 wstats->discard.code = wlandev->rx.decrypt_err;
223 wstats->discard.nwid = 0;
224 wstats->discard.misc = 0;
226 wstats->discard.fragment = 0; /* incomplete fragments */
227 wstats->discard.retries = 0; /* tx retries. */
228 wstats->miss.beacon = 0;
233 static int p80211wext_giwname(netdevice_t *dev,
234 struct iw_request_info *info,
235 char *name, char *extra)
237 struct iw_param rate;
241 result = p80211wext_giwrate(dev, NULL, &rate, NULL);
248 switch (rate.value) {
251 strcpy(name, "IEEE 802.11-DS");
255 strcpy(name, "IEEE 802.11-b");
262 static int p80211wext_giwfreq(netdevice_t *dev,
263 struct iw_request_info *info,
264 struct iw_freq *freq, char *extra)
266 wlandevice_t *wlandev = dev->ml_priv;
267 p80211item_uint32_t mibitem;
268 p80211msg_dot11req_mibset_t msg;
272 msg.msgcode = DIDmsg_dot11req_mibget;
273 memset(&mibitem, 0, sizeof(mibitem));
274 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
275 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
276 result = p80211req_dorequest(wlandev, (u8 *) &msg);
283 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
285 if (mibitem.data > NUM_CHANNELS) {
290 /* convert into frequency instead of a channel */
292 freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000;
298 static int p80211wext_siwfreq(netdevice_t *dev,
299 struct iw_request_info *info,
300 struct iw_freq *freq, char *extra)
302 wlandevice_t *wlandev = dev->ml_priv;
303 p80211item_uint32_t mibitem;
304 p80211msg_dot11req_mibset_t msg;
308 if (!wlan_wext_write) {
313 msg.msgcode = DIDmsg_dot11req_mibset;
314 memset(&mibitem, 0, sizeof(mibitem));
315 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
316 mibitem.status = P80211ENUM_msgitem_status_data_ok;
318 if ((freq->e == 0) && (freq->m <= 1000))
319 mibitem.data = freq->m;
321 mibitem.data = p80211_mhz_to_channel(freq->m);
323 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
324 result = p80211req_dorequest(wlandev, (u8 *) &msg);
335 static int p80211wext_giwmode(netdevice_t *dev,
336 struct iw_request_info *info,
337 __u32 *mode, char *extra)
339 wlandevice_t *wlandev = dev->ml_priv;
341 switch (wlandev->macmode) {
342 case WLAN_MACMODE_IBSS_STA:
343 *mode = IW_MODE_ADHOC;
345 case WLAN_MACMODE_ESS_STA:
346 *mode = IW_MODE_INFRA;
348 case WLAN_MACMODE_ESS_AP:
349 *mode = IW_MODE_MASTER;
353 *mode = IW_MODE_AUTO;
359 static int p80211wext_siwmode(netdevice_t *dev,
360 struct iw_request_info *info,
361 __u32 *mode, char *extra)
363 wlandevice_t *wlandev = dev->ml_priv;
364 p80211item_uint32_t mibitem;
365 p80211msg_dot11req_mibset_t msg;
369 if (!wlan_wext_write) {
374 if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
375 *mode != IW_MODE_MASTER) {
380 /* Operation mode is the same with current mode */
381 if (*mode == wlandev->macmode)
386 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
389 wlandev->macmode = WLAN_MACMODE_ESS_STA;
392 wlandev->macmode = WLAN_MACMODE_ESS_AP;
396 printk(KERN_INFO "Operation mode: %d not support\n", *mode);
400 /* Set Operation mode to the PORT TYPE RID */
401 msg.msgcode = DIDmsg_dot11req_mibset;
402 memset(&mibitem, 0, sizeof(mibitem));
403 mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
404 mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
405 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
406 result = p80211req_dorequest(wlandev, (u8 *) &msg);
415 static int p80211wext_giwrange(netdevice_t *dev,
416 struct iw_request_info *info,
417 struct iw_point *data, char *extra)
419 struct iw_range *range = (struct iw_range *)extra;
422 /* for backward compatability set size and zero everything we don't understand */
423 data->length = sizeof(*range);
424 memset(range, 0, sizeof(*range));
426 range->txpower_capa = IW_TXPOW_DBM;
427 /* XXX what about min/max_pmp, min/max_pmt, etc. */
429 range->we_version_compiled = WIRELESS_EXT;
430 range->we_version_source = 13;
432 range->retry_capa = IW_RETRY_LIMIT;
433 range->retry_flags = IW_RETRY_LIMIT;
434 range->min_retry = 0;
435 range->max_retry = 255;
437 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | /* mode/freq/ssid */
438 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
439 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
440 range->event_capa[1] = IW_EVENT_CAPA_K_1; /* encode */
441 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
442 IW_EVENT_CAPA_MASK(IWEVCUSTOM));
444 range->num_channels = NUM_CHANNELS;
446 /* XXX need to filter against the regulatory domain &| active set */
448 for (i = 0; i < NUM_CHANNELS; i++) {
449 range->freq[val].i = i + 1;
450 range->freq[val].m = p80211wext_channel_freq[i] * 100000;
451 range->freq[val].e = 1;
455 range->num_frequency = val;
457 /* Max of /proc/net/wireless */
458 range->max_qual.qual = 100;
459 range->max_qual.level = 0;
460 range->max_qual.noise = 0;
461 range->sensitivity = 3;
462 /* XXX these need to be nsd-specific! */
465 range->max_rts = 2347;
466 range->min_frag = 256;
467 range->max_frag = 2346;
469 range->max_encoding_tokens = NUM_WEPKEYS;
470 range->num_encoding_sizes = 2;
471 range->encoding_size[0] = 5;
472 range->encoding_size[1] = 13;
474 /* XXX what about num_bitrates/throughput? */
475 range->num_bitrates = 0;
477 /* estimated max throughput */
478 /* XXX need to cap it if we're running at ~2Mbps.. */
479 range->throughput = 5500000;
484 static int p80211wext_giwap(netdevice_t *dev,
485 struct iw_request_info *info,
486 struct sockaddr *ap_addr, char *extra)
489 wlandevice_t *wlandev = dev->ml_priv;
491 memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
492 ap_addr->sa_family = ARPHRD_ETHER;
497 static int p80211wext_giwencode(netdevice_t *dev,
498 struct iw_request_info *info,
499 struct iw_point *erq, char *key)
501 wlandevice_t *wlandev = dev->ml_priv;
505 i = (erq->flags & IW_ENCODE_INDEX) - 1;
508 if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
509 erq->flags |= IW_ENCODE_ENABLED;
511 erq->flags |= IW_ENCODE_DISABLED;
513 if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
514 erq->flags |= IW_ENCODE_RESTRICTED;
516 erq->flags |= IW_ENCODE_OPEN;
518 i = (erq->flags & IW_ENCODE_INDEX) - 1;
521 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
523 if ((i < 0) || (i >= NUM_WEPKEYS)) {
530 /* copy the key from the driver cache as the keys are read-only MIBs */
531 erq->length = wlandev->wep_keylens[i];
532 memcpy(key, wlandev->wep_keys[i], erq->length);
538 static int p80211wext_siwencode(netdevice_t *dev,
539 struct iw_request_info *info,
540 struct iw_point *erq, char *key)
542 wlandevice_t *wlandev = dev->ml_priv;
543 p80211msg_dot11req_mibset_t msg;
544 p80211item_pstr32_t pstr;
550 if (!wlan_wext_write) {
555 /* Check the Key index first. */
556 i = (erq->flags & IW_ENCODE_INDEX);
558 if ((i < 1) || (i > NUM_WEPKEYS)) {
564 /* Set current key number only if no keys are given */
565 if (erq->flags & IW_ENCODE_NOKEY) {
567 p80211wext_dorequest(wlandev,
568 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
578 /* Use defaultkey if no Key Index */
579 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
582 /* Check if there is no key information in the iwconfig request */
583 if ((erq->flags & IW_ENCODE_NOKEY) == 0) {
585 /*------------------------------------------------------------
586 * If there is WEP Key for setting, check the Key Information
587 * and then set it to the firmware.
588 -------------------------------------------------------------*/
590 if (erq->length > 0) {
592 /* copy the key from the driver cache as the keys are read-only MIBs */
593 wlandev->wep_keylens[i] = erq->length;
594 memcpy(wlandev->wep_keys[i], key, erq->length);
596 /* Prepare data struture for p80211req_dorequest. */
597 memcpy(pstr.data.data, key, erq->length);
598 pstr.data.len = erq->length;
603 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
608 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
613 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
618 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
626 msg.msgcode = DIDmsg_dot11req_mibset;
627 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
628 result = p80211req_dorequest(wlandev, (u8 *) &msg);
638 /* Check the PrivacyInvoked flag */
639 if (erq->flags & IW_ENCODE_DISABLED) {
641 p80211wext_dorequest(wlandev,
642 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
643 P80211ENUM_truth_false);
646 p80211wext_dorequest(wlandev,
647 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
648 P80211ENUM_truth_true);
656 /* The security mode may be open or restricted, and its meaning
657 depends on the card used. With most cards, in open mode no
658 authentication is used and the card may also accept non-
659 encrypted sessions, whereas in restricted mode only encrypted
660 sessions are accepted and the card will use authentication if
663 if (erq->flags & IW_ENCODE_RESTRICTED) {
665 p80211wext_dorequest(wlandev,
666 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
667 P80211ENUM_truth_true);
668 } else if (erq->flags & IW_ENCODE_OPEN) {
670 p80211wext_dorequest(wlandev,
671 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
672 P80211ENUM_truth_false);
685 static int p80211wext_giwessid(netdevice_t *dev,
686 struct iw_request_info *info,
687 struct iw_point *data, char *essid)
689 wlandevice_t *wlandev = dev->ml_priv;
691 if (wlandev->ssid.len) {
692 data->length = wlandev->ssid.len;
694 memcpy(essid, wlandev->ssid.data, data->length);
695 essid[data->length] = 0;
697 memset(essid, 0, sizeof(wlandev->ssid.data));
705 static int p80211wext_siwessid(netdevice_t *dev,
706 struct iw_request_info *info,
707 struct iw_point *data, char *essid)
709 wlandevice_t *wlandev = dev->ml_priv;
710 p80211msg_lnxreq_autojoin_t msg;
714 int length = data->length;
716 if (!wlan_wext_write) {
721 if (wlandev->hostwep & HOSTWEP_SHAREDKEY)
722 msg.authtype.data = P80211ENUM_authalg_sharedkey;
724 msg.authtype.data = P80211ENUM_authalg_opensystem;
726 msg.msgcode = DIDmsg_lnxreq_autojoin;
728 /* Trim the last '\0' to fit the SSID format */
729 if (length && essid[length - 1] == '\0')
732 memcpy(msg.ssid.data.data, essid, length);
733 msg.ssid.data.len = length;
735 pr_debug("autojoin_ssid for %s \n", essid);
736 result = p80211req_dorequest(wlandev, (u8 *) &msg);
737 pr_debug("autojoin_ssid %d\n", result);
748 static int p80211wext_siwcommit(netdevice_t *dev,
749 struct iw_request_info *info,
750 struct iw_point *data, char *essid)
752 wlandevice_t *wlandev = dev->ml_priv;
755 if (!wlan_wext_write) {
761 err = p80211wext_autojoin(wlandev);
767 static int p80211wext_giwrate(netdevice_t *dev,
768 struct iw_request_info *info,
769 struct iw_param *rrq, char *extra)
771 wlandevice_t *wlandev = dev->ml_priv;
772 p80211item_uint32_t mibitem;
773 p80211msg_dot11req_mibset_t msg;
777 msg.msgcode = DIDmsg_dot11req_mibget;
778 memset(&mibitem, 0, sizeof(mibitem));
779 mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
780 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
781 result = p80211req_dorequest(wlandev, (u8 *) &msg);
788 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
790 rrq->fixed = 0; /* can it change? */
794 #define HFA384x_RATEBIT_1 ((u16)1)
795 #define HFA384x_RATEBIT_2 ((u16)2)
796 #define HFA384x_RATEBIT_5dot5 ((u16)4)
797 #define HFA384x_RATEBIT_11 ((u16)8)
799 switch (mibitem.data) {
800 case HFA384x_RATEBIT_1:
801 rrq->value = 1000000;
803 case HFA384x_RATEBIT_2:
804 rrq->value = 2000000;
806 case HFA384x_RATEBIT_5dot5:
807 rrq->value = 5500000;
809 case HFA384x_RATEBIT_11:
810 rrq->value = 11000000;
819 static int p80211wext_giwrts(netdevice_t *dev,
820 struct iw_request_info *info,
821 struct iw_param *rts, char *extra)
823 wlandevice_t *wlandev = dev->ml_priv;
824 p80211item_uint32_t mibitem;
825 p80211msg_dot11req_mibset_t msg;
829 msg.msgcode = DIDmsg_dot11req_mibget;
830 memset(&mibitem, 0, sizeof(mibitem));
831 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
832 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
833 result = p80211req_dorequest(wlandev, (u8 *) &msg);
840 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
842 rts->value = mibitem.data;
843 rts->disabled = (rts->value == 2347);
850 static int p80211wext_siwrts(netdevice_t *dev,
851 struct iw_request_info *info,
852 struct iw_param *rts, char *extra)
854 wlandevice_t *wlandev = dev->ml_priv;
855 p80211item_uint32_t mibitem;
856 p80211msg_dot11req_mibset_t msg;
860 if (!wlan_wext_write) {
865 msg.msgcode = DIDmsg_dot11req_mibget;
866 memset(&mibitem, 0, sizeof(mibitem));
867 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
871 mibitem.data = rts->value;
873 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
874 result = p80211req_dorequest(wlandev, (u8 *) &msg);
885 static int p80211wext_giwfrag(netdevice_t *dev,
886 struct iw_request_info *info,
887 struct iw_param *frag, char *extra)
889 wlandevice_t *wlandev = dev->ml_priv;
890 p80211item_uint32_t mibitem;
891 p80211msg_dot11req_mibset_t msg;
895 msg.msgcode = DIDmsg_dot11req_mibget;
896 memset(&mibitem, 0, sizeof(mibitem));
898 DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
899 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
900 result = p80211req_dorequest(wlandev, (u8 *) &msg);
907 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
909 frag->value = mibitem.data;
910 frag->disabled = (frag->value == 2346);
917 static int p80211wext_siwfrag(netdevice_t *dev,
918 struct iw_request_info *info,
919 struct iw_param *frag, char *extra)
921 wlandevice_t *wlandev = dev->ml_priv;
922 p80211item_uint32_t mibitem;
923 p80211msg_dot11req_mibset_t msg;
927 if (!wlan_wext_write) {
932 msg.msgcode = DIDmsg_dot11req_mibset;
933 memset(&mibitem, 0, sizeof(mibitem));
935 DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
940 mibitem.data = frag->value;
942 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
943 result = p80211req_dorequest(wlandev, (u8 *) &msg);
954 #ifndef IW_RETRY_LONG
955 #define IW_RETRY_LONG IW_RETRY_MAX
958 #ifndef IW_RETRY_SHORT
959 #define IW_RETRY_SHORT IW_RETRY_MIN
962 static int p80211wext_giwretry(netdevice_t *dev,
963 struct iw_request_info *info,
964 struct iw_param *rrq, char *extra)
966 wlandevice_t *wlandev = dev->ml_priv;
967 p80211item_uint32_t mibitem;
968 p80211msg_dot11req_mibset_t msg;
971 u16 shortretry, longretry, lifetime;
973 msg.msgcode = DIDmsg_dot11req_mibget;
974 memset(&mibitem, 0, sizeof(mibitem));
975 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
977 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
978 result = p80211req_dorequest(wlandev, (u8 *) &msg);
985 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
987 shortretry = mibitem.data;
989 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
991 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
992 result = p80211req_dorequest(wlandev, (u8 *) &msg);
999 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1001 longretry = mibitem.data;
1004 DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1006 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1007 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1014 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1016 lifetime = mibitem.data;
1020 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1021 rrq->flags = IW_RETRY_LIFETIME;
1022 rrq->value = lifetime * 1024;
1024 if (rrq->flags & IW_RETRY_LONG) {
1025 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1026 rrq->value = longretry;
1028 rrq->flags = IW_RETRY_LIMIT;
1029 rrq->value = shortretry;
1030 if (shortretry != longretry)
1031 rrq->flags |= IW_RETRY_SHORT;
1040 static int p80211wext_siwretry(netdevice_t *dev,
1041 struct iw_request_info *info,
1042 struct iw_param *rrq, char *extra)
1044 wlandevice_t *wlandev = dev->ml_priv;
1045 p80211item_uint32_t mibitem;
1046 p80211msg_dot11req_mibset_t msg;
1050 memset(&mibitem, 0, sizeof(mibitem));
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) {
1066 DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1067 mibitem.data = rrq->value /= 1024;
1069 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1070 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1077 if (rrq->flags & IW_RETRY_LONG) {
1079 DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1080 mibitem.data = rrq->value;
1082 memcpy(&msg.mibattribute.data, &mibitem,
1084 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1092 if (rrq->flags & IW_RETRY_SHORT) {
1094 DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1095 mibitem.data = rrq->value;
1097 memcpy(&msg.mibattribute.data, &mibitem,
1099 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1113 static int p80211wext_siwtxpow(netdevice_t *dev,
1114 struct iw_request_info *info,
1115 struct iw_param *rrq, char *extra)
1117 wlandevice_t *wlandev = dev->ml_priv;
1118 p80211item_uint32_t mibitem;
1119 p80211msg_dot11req_mibset_t msg;
1123 if (!wlan_wext_write) {
1124 err = (-EOPNOTSUPP);
1128 msg.msgcode = DIDmsg_dot11req_mibset;
1129 memset(&mibitem, 0, sizeof(mibitem));
1131 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1132 if (rrq->fixed == 0)
1135 mibitem.data = rrq->value;
1136 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1137 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1148 static int p80211wext_giwtxpow(netdevice_t *dev,
1149 struct iw_request_info *info,
1150 struct iw_param *rrq, char *extra)
1152 wlandevice_t *wlandev = dev->ml_priv;
1153 p80211item_uint32_t mibitem;
1154 p80211msg_dot11req_mibset_t msg;
1158 msg.msgcode = DIDmsg_dot11req_mibget;
1160 memset(&mibitem, 0, sizeof(mibitem));
1162 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1164 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1165 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1172 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1174 /* XXX handle OFF by setting disabled = 1; */
1176 rrq->flags = 0; /* IW_TXPOW_DBM; */
1179 rrq->value = mibitem.data;
1185 static int p80211wext_siwspy(netdevice_t *dev,
1186 struct iw_request_info *info,
1187 struct iw_point *srq, char *extra)
1189 wlandevice_t *wlandev = dev->ml_priv;
1190 struct sockaddr address[IW_MAX_SPY];
1191 int number = srq->length;
1194 /* Copy the data from the input buffer */
1195 memcpy(address, extra, sizeof(struct sockaddr) * number);
1197 wlandev->spy_number = 0;
1201 /* extract the addresses */
1202 for (i = 0; i < number; i++) {
1204 memcpy(wlandev->spy_address[i], address[i].sa_data,
1209 memset(wlandev->spy_stat, 0,
1210 sizeof(struct iw_quality) * IW_MAX_SPY);
1212 /* set number of addresses */
1213 wlandev->spy_number = number;
1219 /* jkriegl: from orinoco, modified */
1220 static int p80211wext_giwspy(netdevice_t *dev,
1221 struct iw_request_info *info,
1222 struct iw_point *srq, char *extra)
1224 wlandevice_t *wlandev = dev->ml_priv;
1226 struct sockaddr address[IW_MAX_SPY];
1227 struct iw_quality spy_stat[IW_MAX_SPY];
1231 number = wlandev->spy_number;
1235 /* populate address and spy struct's */
1236 for (i = 0; i < number; i++) {
1237 memcpy(address[i].sa_data, wlandev->spy_address[i],
1239 address[i].sa_family = AF_UNIX;
1240 memcpy(&spy_stat[i], &wlandev->spy_stat[i],
1241 sizeof(struct iw_quality));
1244 /* reset update flag */
1245 for (i = 0; i < number; i++)
1246 wlandev->spy_stat[i].updated = 0;
1249 /* push stuff to user space */
1250 srq->length = number;
1251 memcpy(extra, address, sizeof(struct sockaddr) * number);
1252 memcpy(extra + sizeof(struct sockaddr) * number, spy_stat,
1253 sizeof(struct iw_quality) * number);
1258 static int prism2_result2err(int prism2_result)
1262 switch (prism2_result) {
1263 case P80211ENUM_resultcode_invalid_parameters:
1266 case P80211ENUM_resultcode_implementation_failure:
1269 case P80211ENUM_resultcode_not_supported:
1280 static int p80211wext_siwscan(netdevice_t *dev,
1281 struct iw_request_info *info,
1282 struct iw_point *srq, char *extra)
1284 wlandevice_t *wlandev = dev->ml_priv;
1285 p80211msg_dot11req_scan_t msg;
1290 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1291 printk(KERN_ERR "Can't scan in AP mode\n");
1292 err = (-EOPNOTSUPP);
1296 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1297 msg.msgcode = DIDmsg_dot11req_scan;
1298 msg.bsstype.data = P80211ENUM_bsstype_any;
1300 memset(&(msg.bssid.data), 0xFF, sizeof(p80211item_pstr6_t));
1301 msg.bssid.data.len = 6;
1303 msg.scantype.data = P80211ENUM_scantype_active;
1304 msg.probedelay.data = 0;
1306 for (i = 1; i <= 14; i++)
1307 msg.channellist.data.data[i - 1] = i;
1308 msg.channellist.data.len = 14;
1310 msg.maxchanneltime.data = 250;
1311 msg.minchanneltime.data = 200;
1313 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1315 err = prism2_result2err(msg.resultcode.data);
1321 /* Helper to translate scan into Wireless Extensions scan results.
1322 * Inspired by the prism54 code, which was in turn inspired by the
1325 static char *wext_translate_bss(struct iw_request_info *info, char *current_ev,
1327 p80211msg_dot11req_scan_results_t *bss)
1329 struct iw_event iwe; /* Temporary buffer */
1331 /* The first entry must be the MAC address */
1332 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1333 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1334 iwe.cmd = SIOCGIWAP;
1336 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1339 /* The following entries will be displayed in the same order we give them */
1342 if (bss->ssid.data.len > 0) {
1343 char essid[IW_ESSID_MAX_SIZE + 1];
1347 min_t(unsigned short, IW_ESSID_MAX_SIZE,
1348 bss->ssid.data.len);
1349 memset(&essid, 0, sizeof(essid));
1350 memcpy(&essid, bss->ssid.data.data, size);
1351 pr_debug(" essid size = %d\n", size);
1352 iwe.u.data.length = size;
1353 iwe.u.data.flags = 1;
1354 iwe.cmd = SIOCGIWESSID;
1356 iwe_stream_add_point(info, current_ev, end_buf, &iwe,
1358 pr_debug(" essid size OK.\n");
1361 switch (bss->bsstype.data) {
1362 case P80211ENUM_bsstype_infrastructure:
1363 iwe.u.mode = IW_MODE_MASTER;
1366 case P80211ENUM_bsstype_independent:
1367 iwe.u.mode = IW_MODE_ADHOC;
1374 iwe.cmd = SIOCGIWMODE;
1377 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1380 /* Encryption capability */
1381 if (bss->privacy.data == P80211ENUM_truth_true)
1382 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1384 iwe.u.data.flags = IW_ENCODE_DISABLED;
1385 iwe.u.data.length = 0;
1386 iwe.cmd = SIOCGIWENCODE;
1388 iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1390 /* Add frequency. (short) bss->channel is the frequency in MHz */
1391 iwe.u.freq.m = bss->dschannel.data;
1393 iwe.cmd = SIOCGIWFREQ;
1395 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1398 /* Add quality statistics */
1399 iwe.u.qual.level = bss->signal.data;
1400 iwe.u.qual.noise = bss->noise.data;
1401 /* do a simple SNR for quality */
1402 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1405 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1411 static int p80211wext_giwscan(netdevice_t *dev,
1412 struct iw_request_info *info,
1413 struct iw_point *srq, char *extra)
1415 wlandevice_t *wlandev = dev->ml_priv;
1416 p80211msg_dot11req_scan_results_t msg;
1421 char *current_ev = extra;
1423 /* Since wireless tools doesn't really have a way of passing how
1424 * many scan results results there were back here, keep grabbing them
1428 memset(&msg, 0, sizeof(msg));
1429 msg.msgcode = DIDmsg_dot11req_scan_results;
1430 msg.bssindex.data = i;
1432 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1433 if ((result != 0) ||
1434 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1439 wext_translate_bss(info, current_ev,
1440 extra + IW_SCAN_MAX_DATA, &msg);
1443 } while (i < IW_MAX_AP);
1445 srq->length = (current_ev - extra);
1446 srq->flags = 0; /* todo */
1448 if (result && !scan_good)
1449 err = prism2_result2err(msg.resultcode.data);
1454 /* extra wireless extensions stuff to support NetworkManager (I hope) */
1456 /* SIOCSIWENCODEEXT */
1457 static int p80211wext_set_encodeext(struct net_device *dev,
1458 struct iw_request_info *info,
1459 union iwreq_data *wrqu, char *extra)
1461 wlandevice_t *wlandev = dev->ml_priv;
1462 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1463 p80211msg_dot11req_mibset_t msg;
1464 p80211item_pstr32_t *pstr;
1467 struct iw_point *encoding = &wrqu->encoding;
1468 int idx = encoding->flags & IW_ENCODE_INDEX;
1470 pr_debug("set_encode_ext flags[%d] alg[%d] keylen[%d]\n",
1471 ext->ext_flags, (int)ext->alg, (int)ext->key_len);
1473 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1474 /* set default key ? I'm not sure if this the the correct thing to do here */
1477 if (idx < 1 || idx > NUM_WEPKEYS)
1482 pr_debug("setting default key (%d)\n", idx);
1484 p80211wext_dorequest(wlandev,
1485 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
1491 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1492 if (ext->alg != IW_ENCODE_ALG_WEP) {
1493 pr_debug("asked to set a non wep key :(\n");
1497 if (idx < 1 || idx > NUM_WEPKEYS)
1502 pr_debug("Set WEP key (%d)\n", idx);
1503 wlandev->wep_keylens[idx] = ext->key_len;
1504 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1506 memset(&msg, 0, sizeof(msg));
1507 pstr = (p80211item_pstr32_t *) &msg.mibattribute.data;
1508 memcpy(pstr->data.data, ext->key, ext->key_len);
1509 pstr->data.len = ext->key_len;
1513 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1517 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1521 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1525 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1530 msg.msgcode = DIDmsg_dot11req_mibset;
1531 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1532 pr_debug("result (%d)\n", result);
1537 /* SIOCGIWENCODEEXT */
1538 static int p80211wext_get_encodeext(struct net_device *dev,
1539 struct iw_request_info *info,
1540 union iwreq_data *wrqu, char *extra)
1542 wlandevice_t *wlandev = dev->ml_priv;
1543 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1545 struct iw_point *encoding = &wrqu->encoding;
1550 pr_debug("get_encode_ext flags[%d] alg[%d] keylen[%d]\n",
1551 ext->ext_flags, (int)ext->alg, (int)ext->key_len);
1553 max_len = encoding->length - sizeof(*ext);
1555 pr_debug("get_encodeext max_len [%d] invalid\n", max_len);
1559 idx = encoding->flags & IW_ENCODE_INDEX;
1561 pr_debug("get_encode_ext index [%d]\n", idx);
1564 if (idx < 1 || idx > NUM_WEPKEYS) {
1565 pr_debug("get_encode_ext invalid key index [%d]\n",
1572 /* default key ? not sure what to do */
1573 /* will just use key[0] for now ! FIX ME */
1576 encoding->flags = idx + 1;
1577 memset(ext, 0, sizeof(*ext));
1579 ext->alg = IW_ENCODE_ALG_WEP;
1580 ext->key_len = wlandev->wep_keylens[idx];
1581 memcpy(ext->key, wlandev->wep_keys[idx], ext->key_len);
1583 encoding->flags |= IW_ENCODE_ENABLED;
1589 static int p80211_wext_set_iwauth(struct net_device *dev,
1590 struct iw_request_info *info,
1591 union iwreq_data *wrqu, char *extra)
1593 wlandevice_t *wlandev = dev->ml_priv;
1594 struct iw_param *param = &wrqu->param;
1597 pr_debug("set_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX);
1599 switch (param->flags & IW_AUTH_INDEX) {
1600 case IW_AUTH_DROP_UNENCRYPTED:
1601 pr_debug("drop_unencrypted %d\n", param->value);
1604 p80211wext_dorequest(wlandev,
1605 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
1606 P80211ENUM_truth_true);
1609 p80211wext_dorequest(wlandev,
1610 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
1611 P80211ENUM_truth_false);
1614 case IW_AUTH_PRIVACY_INVOKED:
1615 pr_debug("privacy invoked %d\n", param->value);
1618 p80211wext_dorequest(wlandev,
1619 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
1620 P80211ENUM_truth_true);
1623 p80211wext_dorequest(wlandev,
1624 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
1625 P80211ENUM_truth_false);
1629 case IW_AUTH_80211_AUTH_ALG:
1630 if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1631 pr_debug("set open_system\n");
1632 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1633 } else if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1634 pr_debug("set shared key\n");
1635 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1637 /* don't know what to do know */
1638 pr_debug("unknown AUTH_ALG (%d)\n", param->value);
1651 static int p80211_wext_get_iwauth(struct net_device *dev,
1652 struct iw_request_info *info,
1653 union iwreq_data *wrqu, char *extra)
1655 wlandevice_t *wlandev = dev->ml_priv;
1656 struct iw_param *param = &wrqu->param;
1659 pr_debug("get_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX);
1661 switch (param->flags & IW_AUTH_INDEX) {
1662 case IW_AUTH_DROP_UNENCRYPTED:
1664 wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED ? 1 : 0;
1667 case IW_AUTH_PRIVACY_INVOKED:
1669 wlandev->hostwep & HOSTWEP_PRIVACYINVOKED ? 1 : 0;
1672 case IW_AUTH_80211_AUTH_ALG:
1674 wlandev->hostwep & HOSTWEP_SHAREDKEY ?
1675 IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM;
1685 static iw_handler p80211wext_handlers[] = {
1686 (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
1687 (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
1688 (iw_handler) NULL, /* SIOCSIWNWID */
1689 (iw_handler) NULL, /* SIOCGIWNWID */
1690 (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
1691 (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
1692 (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
1693 (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
1694 (iw_handler) NULL, /* SIOCSIWSENS */
1695 (iw_handler) NULL, /* SIOCGIWSENS */
1696 (iw_handler) NULL, /* not used *//* SIOCSIWRANGE */
1697 (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
1698 (iw_handler) NULL, /* not used *//* SIOCSIWPRIV */
1699 (iw_handler) NULL, /* kernel code *//* SIOCGIWPRIV */
1700 (iw_handler) NULL, /* not used *//* SIOCSIWSTATS */
1701 (iw_handler) NULL, /* kernel code *//* SIOCGIWSTATS */
1702 (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
1703 (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
1704 (iw_handler) NULL, /* -- hole -- */
1705 (iw_handler) NULL, /* -- hole -- */
1706 (iw_handler) NULL, /* SIOCSIWAP */
1707 (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
1708 (iw_handler) NULL, /* -- hole -- */
1709 (iw_handler) NULL, /* SIOCGIWAPLIST */
1710 (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
1711 (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
1712 (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
1713 (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
1714 (iw_handler) NULL, /* SIOCSIWNICKN */
1715 (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
1716 (iw_handler) NULL, /* -- hole -- */
1717 (iw_handler) NULL, /* -- hole -- */
1718 (iw_handler) NULL, /* SIOCSIWRATE */
1719 (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
1720 (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
1721 (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
1722 (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
1723 (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
1724 (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
1725 (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
1726 (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
1727 (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
1728 (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
1729 (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
1730 (iw_handler) NULL, /* SIOCSIWPOWER */
1731 (iw_handler) NULL, /* SIOCGIWPOWER */
1732 /* WPA operations */
1733 (iw_handler) NULL, /* -- hole -- */
1734 (iw_handler) NULL, /* -- hole -- */
1735 (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
1736 (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
1737 (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
1738 (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
1740 (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
1741 (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
1742 (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
1745 struct iw_handler_def p80211wext_handler_def = {
1746 .num_standard = ARRAY_SIZE(p80211wext_handlers),
1747 .standard = p80211wext_handlers,
1748 .get_wireless_stats = p80211wext_get_wireless_stats
1751 int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
1753 union iwreq_data data;
1755 /* Send the association state first */
1756 data.ap_addr.sa_family = ARPHRD_ETHER;
1758 memcpy(data.ap_addr.sa_data, wlandev->bssid, ETH_ALEN);
1760 memset(data.ap_addr.sa_data, 0, ETH_ALEN);
1762 if (wlan_wext_write)
1763 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1768 /* XXX send association data, like IEs, etc etc. */