Staging: wlan-ng: remove unused #include <version.h>
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / wlan-ng / p80211wext.c
blob762922c8f9186d484bc6828476705b1f52236479
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 * --------------------------------------------------------------------
11 * linux-wlan
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 /*================================================================*/
38 /* System Includes */
42 #include <linux/kernel.h>
43 #include <linux/sched.h>
44 #include <linux/types.h>
45 #include <linux/slab.h>
46 #include <linux/netdevice.h>
47 #include <linux/etherdevice.h>
48 #include <linux/wireless.h>
49 #include <net/iw_handler.h>
50 #include <linux/if_arp.h>
51 #include <asm/bitops.h>
52 #include <asm/uaccess.h>
53 #include <asm/byteorder.h>
55 /*================================================================*/
56 /* Project Includes */
58 #include "wlan_compat.h"
60 #include "p80211types.h"
61 #include "p80211hdr.h"
62 #include "p80211conv.h"
63 #include "p80211mgmt.h"
64 #include "p80211msg.h"
65 #include "p80211metastruct.h"
66 #include "p80211metadef.h"
67 #include "p80211netdev.h"
68 #include "p80211ioctl.h"
69 #include "p80211req.h"
71 static int p80211wext_giwrate(netdevice_t *dev,
72 struct iw_request_info *info,
73 struct iw_param *rrq, char *extra);
74 static int p80211wext_giwessid(netdevice_t *dev,
75 struct iw_request_info *info,
76 struct iw_point *data, char *essid);
78 static u8 p80211_mhz_to_channel(u16 mhz)
80 if (mhz >= 5000) {
81 return ((mhz - 5000) / 5);
84 if (mhz == 2482)
85 return 14;
87 if (mhz >= 2407) {
88 return ((mhz - 2407) / 5);
91 return 0;
94 static u16 p80211_channel_to_mhz(u8 ch, int dot11a)
97 if (ch == 0)
98 return 0;
99 if (ch > 200)
100 return 0;
102 /* 5G */
104 if (dot11a) {
105 return (5000 + (5 * ch));
108 /* 2.4G */
110 if (ch == 14)
111 return 2484;
113 if ((ch < 14) && (ch > 0)) {
114 return (2407 + (5 * ch));
117 return 0;
120 /* taken from orinoco.c ;-) */
121 static const long p80211wext_channel_freq[] = {
122 2412, 2417, 2422, 2427, 2432, 2437, 2442,
123 2447, 2452, 2457, 2462, 2467, 2472, 2484
125 #define NUM_CHANNELS (sizeof(p80211wext_channel_freq) / sizeof(p80211wext_channel_freq[0]))
127 /* steal a spare bit to store the shared/opensystems state. should default to open if not set */
128 #define HOSTWEP_SHAREDKEY BIT3
131 /** function declarations =============== */
133 static int qual_as_percent(int snr ) {
134 if ( snr <= 0 )
135 return 0;
136 if ( snr <= 40 )
137 return snr*5/2;
138 return 100;
144 static int p80211wext_dorequest(wlandevice_t *wlandev, u32 did, u32 data)
146 p80211msg_dot11req_mibset_t msg;
147 p80211item_uint32_t mibitem;
148 int result;
150 DBFENTER;
152 msg.msgcode = DIDmsg_dot11req_mibset;
153 mibitem.did = did;
154 mibitem.data = data;
155 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
156 result = p80211req_dorequest(wlandev, (u8*)&msg);
158 DBFEXIT;
159 return result;
162 static int p80211wext_autojoin(wlandevice_t *wlandev)
164 p80211msg_lnxreq_autojoin_t msg;
165 struct iw_point data;
166 char ssid[IW_ESSID_MAX_SIZE];
168 int result;
169 int err = 0;
171 DBFENTER;
173 /* Get ESSID */
174 result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid);
176 if (result) {
177 err = -EFAULT;
178 goto exit;
181 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
182 msg.authtype.data = P80211ENUM_authalg_sharedkey;
183 else
184 msg.authtype.data = P80211ENUM_authalg_opensystem;
186 msg.msgcode = DIDmsg_lnxreq_autojoin;
188 /* Trim the last '\0' to fit the SSID format */
190 if (data.length && ssid[data.length-1] == '\0') {
191 data.length = data.length - 1;
194 memcpy(msg.ssid.data.data, ssid, data.length);
195 msg.ssid.data.len = data.length;
197 result = p80211req_dorequest(wlandev, (u8*)&msg);
199 if (result) {
200 err = -EFAULT;
201 goto exit;
204 exit:
206 DBFEXIT;
207 return err;
211 /* called by /proc/net/wireless */
212 struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev)
214 p80211msg_lnxreq_commsquality_t quality;
215 wlandevice_t *wlandev = dev->ml_priv;
216 struct iw_statistics* wstats = &wlandev->wstats;
217 int retval;
219 DBFENTER;
220 /* Check */
221 if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) )
222 return NULL;
224 /* XXX Only valid in station mode */
225 wstats->status = 0;
227 /* build request message */
228 quality.msgcode = DIDmsg_lnxreq_commsquality;
229 quality.dbm.data = P80211ENUM_truth_true;
230 quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
232 /* send message to nsd */
233 if ( wlandev->mlmerequest == NULL )
234 return NULL;
236 retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality);
238 wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
239 wstats->qual.level = quality.level.data; /* instant signal level */
240 wstats->qual.noise = quality.noise.data; /* instant noise level */
242 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
243 wstats->discard.code = wlandev->rx.decrypt_err;
244 wstats->discard.nwid = 0;
245 wstats->discard.misc = 0;
247 wstats->discard.fragment = 0; // incomplete fragments
248 wstats->discard.retries = 0; // tx retries.
249 wstats->miss.beacon = 0;
251 DBFEXIT;
253 return wstats;
256 static int p80211wext_giwname(netdevice_t *dev,
257 struct iw_request_info *info,
258 char *name, char *extra)
260 struct iw_param rate;
261 int result;
262 int err = 0;
264 DBFENTER;
266 result = p80211wext_giwrate(dev, NULL, &rate, NULL);
268 if (result) {
269 err = -EFAULT;
270 goto exit;
273 switch (rate.value) {
274 case 1000000:
275 case 2000000:
276 strcpy(name, "IEEE 802.11-DS");
277 break;
278 case 5500000:
279 case 11000000:
280 strcpy(name, "IEEE 802.11-b");
281 break;
283 exit:
284 DBFEXIT;
285 return err;
288 static int p80211wext_giwfreq(netdevice_t *dev,
289 struct iw_request_info *info,
290 struct iw_freq *freq, char *extra)
292 wlandevice_t *wlandev = dev->ml_priv;
293 p80211item_uint32_t mibitem;
294 p80211msg_dot11req_mibset_t msg;
295 int result;
296 int err = 0;
298 DBFENTER;
300 msg.msgcode = DIDmsg_dot11req_mibget;
301 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
302 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
303 result = p80211req_dorequest(wlandev, (u8*)&msg);
305 if (result) {
306 err = -EFAULT;
307 goto exit;
310 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
312 if (mibitem.data > NUM_CHANNELS) {
313 err = -EFAULT;
314 goto exit;
317 /* convert into frequency instead of a channel */
318 freq->e = 1;
319 freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000;
321 exit:
322 DBFEXIT;
323 return err;
326 static int p80211wext_siwfreq(netdevice_t *dev,
327 struct iw_request_info *info,
328 struct iw_freq *freq, char *extra)
330 wlandevice_t *wlandev = dev->ml_priv;
331 p80211item_uint32_t mibitem;
332 p80211msg_dot11req_mibset_t msg;
333 int result;
334 int err = 0;
336 DBFENTER;
338 if (!wlan_wext_write) {
339 err = (-EOPNOTSUPP);
340 goto exit;
343 msg.msgcode = DIDmsg_dot11req_mibset;
344 mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
345 mibitem.status = P80211ENUM_msgitem_status_data_ok;
347 if ( (freq->e == 0) && (freq->m <= 1000) )
348 mibitem.data = freq->m;
349 else
350 mibitem.data = p80211_mhz_to_channel(freq->m);
352 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
353 result = p80211req_dorequest(wlandev, (u8*)&msg);
355 if (result) {
356 err = -EFAULT;
357 goto exit;
360 exit:
361 DBFEXIT;
362 return err;
365 static int p80211wext_giwmode(netdevice_t *dev,
366 struct iw_request_info *info,
367 __u32 *mode, char *extra)
369 wlandevice_t *wlandev = dev->ml_priv;
371 DBFENTER;
373 switch (wlandev->macmode) {
374 case WLAN_MACMODE_IBSS_STA:
375 *mode = IW_MODE_ADHOC;
376 break;
377 case WLAN_MACMODE_ESS_STA:
378 *mode = IW_MODE_INFRA;
379 break;
380 case WLAN_MACMODE_ESS_AP:
381 *mode = IW_MODE_MASTER;
382 break;
383 default:
384 /* Not set yet. */
385 *mode = IW_MODE_AUTO;
388 DBFEXIT;
389 return 0;
392 static int p80211wext_siwmode(netdevice_t *dev,
393 struct iw_request_info *info,
394 __u32 *mode, char *extra)
396 wlandevice_t *wlandev = dev->ml_priv;
397 p80211item_uint32_t mibitem;
398 p80211msg_dot11req_mibset_t msg;
399 int result;
400 int err = 0;
402 DBFENTER;
404 if (!wlan_wext_write) {
405 err = (-EOPNOTSUPP);
406 goto exit;
409 if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
410 *mode != IW_MODE_MASTER) {
411 err = (-EOPNOTSUPP);
412 goto exit;
415 /* Operation mode is the same with current mode */
416 if (*mode == wlandev->macmode)
417 goto exit;
419 switch (*mode) {
420 case IW_MODE_ADHOC:
421 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
422 break;
423 case IW_MODE_INFRA:
424 wlandev->macmode = WLAN_MACMODE_ESS_STA;
425 break;
426 case IW_MODE_MASTER:
427 wlandev->macmode = WLAN_MACMODE_ESS_AP;
428 break;
429 default:
430 /* Not set yet. */
431 WLAN_LOG_INFO("Operation mode: %d not support\n", *mode);
432 return -EOPNOTSUPP;
435 /* Set Operation mode to the PORT TYPE RID */
436 msg.msgcode = DIDmsg_dot11req_mibset;
437 mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
438 mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
439 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
440 result = p80211req_dorequest(wlandev, (u8*)&msg);
442 if (result)
443 err = -EFAULT;
445 exit:
446 DBFEXIT;
448 return err;
452 static int p80211wext_giwrange(netdevice_t *dev,
453 struct iw_request_info *info,
454 struct iw_point *data, char *extra)
456 struct iw_range *range = (struct iw_range *) extra;
457 int i, val;
459 DBFENTER;
461 // for backward compatability set size & zero everything we don't understand
462 data->length = sizeof(*range);
463 memset(range,0,sizeof(*range));
465 range->txpower_capa = IW_TXPOW_DBM;
466 // XXX what about min/max_pmp, min/max_pmt, etc.
468 range->we_version_compiled = WIRELESS_EXT;
469 range->we_version_source = 13;
471 range->retry_capa = IW_RETRY_LIMIT;
472 range->retry_flags = IW_RETRY_LIMIT;
473 range->min_retry = 0;
474 range->max_retry = 255;
476 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | //mode/freq/ssid
477 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
478 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
479 range->event_capa[1] = IW_EVENT_CAPA_K_1; //encode
480 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
481 IW_EVENT_CAPA_MASK(IWEVCUSTOM) );
483 range->num_channels = NUM_CHANNELS;
485 /* XXX need to filter against the regulatory domain &| active set */
486 val = 0;
487 for (i = 0; i < NUM_CHANNELS ; i++) {
488 range->freq[val].i = i + 1;
489 range->freq[val].m = p80211wext_channel_freq[i] * 100000;
490 range->freq[val].e = 1;
491 val++;
494 range->num_frequency = val;
496 /* Max of /proc/net/wireless */
497 range->max_qual.qual = 100;
498 range->max_qual.level = 0;
499 range->max_qual.noise = 0;
500 range->sensitivity = 3;
501 // XXX these need to be nsd-specific!
503 range->min_rts = 0;
504 range->max_rts = 2347;
505 range->min_frag = 256;
506 range->max_frag = 2346;
508 range->max_encoding_tokens = NUM_WEPKEYS;
509 range->num_encoding_sizes = 2;
510 range->encoding_size[0] = 5;
511 range->encoding_size[1] = 13;
513 // XXX what about num_bitrates/throughput?
514 range->num_bitrates = 0;
516 /* estimated max throughput */
517 // XXX need to cap it if we're running at ~2Mbps..
518 range->throughput = 5500000;
520 DBFEXIT;
521 return 0;
524 static int p80211wext_giwap(netdevice_t *dev,
525 struct iw_request_info *info,
526 struct sockaddr *ap_addr, char *extra)
529 wlandevice_t *wlandev = dev->ml_priv;
531 DBFENTER;
533 memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
534 ap_addr->sa_family = ARPHRD_ETHER;
536 DBFEXIT;
537 return 0;
540 static int p80211wext_giwencode(netdevice_t *dev,
541 struct iw_request_info *info,
542 struct iw_point *erq, char *key)
544 wlandevice_t *wlandev = dev->ml_priv;
545 int err = 0;
546 int i;
548 DBFENTER;
550 i = (erq->flags & IW_ENCODE_INDEX) - 1;
551 erq->flags = 0;
553 if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
554 erq->flags |= IW_ENCODE_ENABLED;
555 else
556 erq->flags |= IW_ENCODE_DISABLED;
558 if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
559 erq->flags |= IW_ENCODE_RESTRICTED;
560 else
561 erq->flags |= IW_ENCODE_OPEN;
563 i = (erq->flags & IW_ENCODE_INDEX) - 1;
565 if (i == -1)
566 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
568 if ((i < 0) || (i >= NUM_WEPKEYS)) {
569 err = -EINVAL;
570 goto exit;
573 erq->flags |= i + 1;
575 /* copy the key from the driver cache as the keys are read-only MIBs */
576 erq->length = wlandev->wep_keylens[i];
577 memcpy(key, wlandev->wep_keys[i], erq->length);
579 exit:
580 DBFEXIT;
581 return err;
584 static int p80211wext_siwencode(netdevice_t *dev,
585 struct iw_request_info *info,
586 struct iw_point *erq, char *key)
588 wlandevice_t *wlandev = dev->ml_priv;
589 p80211msg_dot11req_mibset_t msg;
590 p80211item_pstr32_t pstr;
592 int err = 0;
593 int result = 0;
594 int enable = 0;
595 int i;
597 DBFENTER;
598 if (!wlan_wext_write) {
599 err = (-EOPNOTSUPP);
600 goto exit;
603 /* Check the Key index first. */
604 if((i = (erq->flags & IW_ENCODE_INDEX))) {
606 if ((i < 1) || (i > NUM_WEPKEYS)) {
607 err = -EINVAL;
608 goto exit;
610 else
611 i--;
613 /* Set current key number only if no keys are given */
614 if (erq->flags & IW_ENCODE_NOKEY) {
615 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i);
617 if (result) {
618 err = -EFAULT;
619 goto exit;
623 } else {
624 // Use defaultkey if no Key Index
625 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
628 /* Check if there is no key information in the iwconfig request */
629 if((erq->flags & IW_ENCODE_NOKEY) == 0 ) {
631 /*------------------------------------------------------------
632 * If there is WEP Key for setting, check the Key Information
633 * and then set it to the firmware.
634 -------------------------------------------------------------*/
636 if (erq->length > 0) {
638 /* copy the key from the driver cache as the keys are read-only MIBs */
639 wlandev->wep_keylens[i] = erq->length;
640 memcpy(wlandev->wep_keys[i], key, erq->length);
642 /* Prepare data struture for p80211req_dorequest. */
643 memcpy(pstr.data.data, key, erq->length);
644 pstr.data.len = erq->length;
646 switch(i)
648 case 0:
649 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
650 break;
652 case 1:
653 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
654 break;
656 case 2:
657 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
658 break;
660 case 3:
661 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
662 break;
664 default:
665 err = -EINVAL;
666 goto exit;
669 msg.msgcode = DIDmsg_dot11req_mibset;
670 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
671 result = p80211req_dorequest(wlandev, (u8*)&msg);
673 if (result) {
674 err = -EFAULT;
675 goto exit;
681 /* Check the PrivacyInvoked flag */
682 if (erq->flags & IW_ENCODE_DISABLED) {
683 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
684 } else {
685 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
688 if (result) {
689 err = -EFAULT;
690 goto exit;
693 /* The security mode may be open or restricted, and its meaning
694 depends on the card used. With most cards, in open mode no
695 authentication is used and the card may also accept non-
696 encrypted sessions, whereas in restricted mode only encrypted
697 sessions are accepted and the card will use authentication if
698 available.
700 if (erq->flags & IW_ENCODE_RESTRICTED) {
701 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
703 else if (erq->flags & IW_ENCODE_OPEN) {
704 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
707 if (result) {
708 err = -EFAULT;
709 goto exit;
712 exit:
714 DBFEXIT;
715 return err;
718 static int p80211wext_giwessid(netdevice_t *dev,
719 struct iw_request_info *info,
720 struct iw_point *data, char *essid)
722 wlandevice_t *wlandev = dev->ml_priv;
724 DBFENTER;
726 if (wlandev->ssid.len) {
727 data->length = wlandev->ssid.len;
728 data->flags = 1;
729 memcpy(essid, wlandev->ssid.data, data->length);
730 essid[data->length] = 0;
731 #if (WIRELESS_EXT < 21)
732 data->length++;
733 #endif
734 } else {
735 memset(essid, 0, sizeof(wlandev->ssid.data));
736 data->length = 0;
737 data->flags = 0;
740 DBFEXIT;
741 return 0;
744 static int p80211wext_siwessid(netdevice_t *dev,
745 struct iw_request_info *info,
746 struct iw_point *data, char *essid)
748 wlandevice_t *wlandev = dev->ml_priv;
749 p80211msg_lnxreq_autojoin_t msg;
751 int result;
752 int err = 0;
753 int length = data->length;
755 DBFENTER;
757 if (!wlan_wext_write) {
758 err = (-EOPNOTSUPP);
759 goto exit;
763 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
764 msg.authtype.data = P80211ENUM_authalg_sharedkey;
765 else
766 msg.authtype.data = P80211ENUM_authalg_opensystem;
768 msg.msgcode = DIDmsg_lnxreq_autojoin;
770 #if (WIRELESS_EXT < 21)
771 if (length) length--;
772 #endif
774 /* Trim the last '\0' to fit the SSID format */
776 if (length && essid[length-1] == '\0') {
777 length--;
780 memcpy(msg.ssid.data.data, essid, length);
781 msg.ssid.data.len = length;
783 WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid);
784 result = p80211req_dorequest(wlandev, (u8*)&msg);
785 WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result);
787 if (result) {
788 err = -EFAULT;
789 goto exit;
792 exit:
793 DBFEXIT;
794 return err;
798 static int p80211wext_siwcommit(netdevice_t *dev,
799 struct iw_request_info *info,
800 struct iw_point *data, char *essid)
802 wlandevice_t *wlandev = dev->ml_priv;
803 int err = 0;
805 DBFENTER;
807 if (!wlan_wext_write) {
808 err = (-EOPNOTSUPP);
809 goto exit;
812 /* Auto Join */
813 err = p80211wext_autojoin(wlandev);
815 exit:
816 DBFEXIT;
817 return err;
821 static int p80211wext_giwrate(netdevice_t *dev,
822 struct iw_request_info *info,
823 struct iw_param *rrq, char *extra)
825 wlandevice_t *wlandev = dev->ml_priv;
826 p80211item_uint32_t mibitem;
827 p80211msg_dot11req_mibset_t msg;
828 int result;
829 int err = 0;
831 DBFENTER;
833 msg.msgcode = DIDmsg_dot11req_mibget;
834 mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
835 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
836 result = p80211req_dorequest(wlandev, (u8*)&msg);
838 if (result) {
839 err = -EFAULT;
840 goto exit;
843 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
845 rrq->fixed = 0; /* can it change? */
846 rrq->disabled = 0;
847 rrq->value = 0;
849 #define HFA384x_RATEBIT_1 ((u16)1)
850 #define HFA384x_RATEBIT_2 ((u16)2)
851 #define HFA384x_RATEBIT_5dot5 ((u16)4)
852 #define HFA384x_RATEBIT_11 ((u16)8)
854 switch (mibitem.data) {
855 case HFA384x_RATEBIT_1:
856 rrq->value = 1000000;
857 break;
858 case HFA384x_RATEBIT_2:
859 rrq->value = 2000000;
860 break;
861 case HFA384x_RATEBIT_5dot5:
862 rrq->value = 5500000;
863 break;
864 case HFA384x_RATEBIT_11:
865 rrq->value = 11000000;
866 break;
867 default:
868 err = -EINVAL;
870 exit:
871 DBFEXIT;
872 return err;
875 static int p80211wext_giwrts(netdevice_t *dev,
876 struct iw_request_info *info,
877 struct iw_param *rts, char *extra)
879 wlandevice_t *wlandev = dev->ml_priv;
880 p80211item_uint32_t mibitem;
881 p80211msg_dot11req_mibset_t msg;
882 int result;
883 int err = 0;
885 DBFENTER;
887 msg.msgcode = DIDmsg_dot11req_mibget;
888 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
889 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
890 result = p80211req_dorequest(wlandev, (u8*)&msg);
892 if (result) {
893 err = -EFAULT;
894 goto exit;
897 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
899 rts->value = mibitem.data;
900 rts->disabled = (rts->value == 2347);
901 rts->fixed = 1;
903 exit:
904 DBFEXIT;
905 return err;
909 static int p80211wext_siwrts(netdevice_t *dev,
910 struct iw_request_info *info,
911 struct iw_param *rts, char *extra)
913 wlandevice_t *wlandev = dev->ml_priv;
914 p80211item_uint32_t mibitem;
915 p80211msg_dot11req_mibset_t msg;
916 int result;
917 int err = 0;
919 DBFENTER;
921 if (!wlan_wext_write) {
922 err = (-EOPNOTSUPP);
923 goto exit;
926 msg.msgcode = DIDmsg_dot11req_mibget;
927 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
928 if (rts->disabled)
929 mibitem.data = 2347;
930 else
931 mibitem.data = rts->value;
933 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
934 result = p80211req_dorequest(wlandev, (u8*)&msg);
936 if (result) {
937 err = -EFAULT;
938 goto exit;
941 exit:
942 DBFEXIT;
943 return err;
946 static int p80211wext_giwfrag(netdevice_t *dev,
947 struct iw_request_info *info,
948 struct iw_param *frag, char *extra)
950 wlandevice_t *wlandev = dev->ml_priv;
951 p80211item_uint32_t mibitem;
952 p80211msg_dot11req_mibset_t msg;
953 int result;
954 int err = 0;
956 DBFENTER;
958 msg.msgcode = DIDmsg_dot11req_mibget;
959 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
960 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
961 result = p80211req_dorequest(wlandev, (u8*)&msg);
963 if (result) {
964 err = -EFAULT;
965 goto exit;
968 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
970 frag->value = mibitem.data;
971 frag->disabled = (frag->value == 2346);
972 frag->fixed = 1;
974 exit:
975 DBFEXIT;
976 return err;
979 static int p80211wext_siwfrag(netdevice_t *dev,
980 struct iw_request_info *info,
981 struct iw_param *frag, char *extra)
983 wlandevice_t *wlandev = dev->ml_priv;
984 p80211item_uint32_t mibitem;
985 p80211msg_dot11req_mibset_t msg;
986 int result;
987 int err = 0;
989 DBFENTER;
991 if (!wlan_wext_write) {
992 err = (-EOPNOTSUPP);
993 goto exit;
996 msg.msgcode = DIDmsg_dot11req_mibset;
997 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
999 if (frag->disabled)
1000 mibitem.data = 2346;
1001 else
1002 mibitem.data = frag->value;
1004 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1005 result = p80211req_dorequest(wlandev, (u8*)&msg);
1007 if (result) {
1008 err = -EFAULT;
1009 goto exit;
1012 exit:
1013 DBFEXIT;
1014 return err;
1017 #ifndef IW_RETRY_LONG
1018 #define IW_RETRY_LONG IW_RETRY_MAX
1019 #endif
1021 #ifndef IW_RETRY_SHORT
1022 #define IW_RETRY_SHORT IW_RETRY_MIN
1023 #endif
1025 static int p80211wext_giwretry(netdevice_t *dev,
1026 struct iw_request_info *info,
1027 struct iw_param *rrq, char *extra)
1029 wlandevice_t *wlandev = dev->ml_priv;
1030 p80211item_uint32_t mibitem;
1031 p80211msg_dot11req_mibset_t msg;
1032 int result;
1033 int err = 0;
1034 u16 shortretry, longretry, lifetime;
1036 DBFENTER;
1038 msg.msgcode = DIDmsg_dot11req_mibget;
1039 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1041 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1042 result = p80211req_dorequest(wlandev, (u8*)&msg);
1044 if (result) {
1045 err = -EFAULT;
1046 goto exit;
1049 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1051 shortretry = mibitem.data;
1053 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1055 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1056 result = p80211req_dorequest(wlandev, (u8*)&msg);
1058 if (result) {
1059 err = -EFAULT;
1060 goto exit;
1063 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1065 longretry = mibitem.data;
1067 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1069 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1070 result = p80211req_dorequest(wlandev, (u8*)&msg);
1072 if (result) {
1073 err = -EFAULT;
1074 goto exit;
1077 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1079 lifetime = mibitem.data;
1081 rrq->disabled = 0;
1083 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1084 rrq->flags = IW_RETRY_LIFETIME;
1085 rrq->value = lifetime * 1024;
1086 } else {
1087 if (rrq->flags & IW_RETRY_LONG) {
1088 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1089 rrq->value = longretry;
1090 } else {
1091 rrq->flags = IW_RETRY_LIMIT;
1092 rrq->value = shortretry;
1093 if (shortretry != longretry)
1094 rrq->flags |= IW_RETRY_SHORT;
1098 exit:
1099 DBFEXIT;
1100 return err;
1104 static int p80211wext_siwretry(netdevice_t *dev,
1105 struct iw_request_info *info,
1106 struct iw_param *rrq, char *extra)
1108 wlandevice_t *wlandev = dev->ml_priv;
1109 p80211item_uint32_t mibitem;
1110 p80211msg_dot11req_mibset_t msg;
1111 int result;
1112 int err = 0;
1114 DBFENTER;
1116 if (!wlan_wext_write) {
1117 err = (-EOPNOTSUPP);
1118 goto exit;
1121 if (rrq->disabled) {
1122 err = -EINVAL;
1123 goto exit;
1126 msg.msgcode = DIDmsg_dot11req_mibset;
1128 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1129 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1130 mibitem.data = rrq->value /= 1024;
1132 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1133 result = p80211req_dorequest(wlandev, (u8*)&msg);
1135 if (result) {
1136 err = -EFAULT;
1137 goto exit;
1139 } else {
1140 if (rrq->flags & IW_RETRY_LONG) {
1141 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1142 mibitem.data = rrq->value;
1144 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1145 result = p80211req_dorequest(wlandev, (u8*)&msg);
1147 if (result) {
1148 err = -EFAULT;
1149 goto exit;
1153 if (rrq->flags & IW_RETRY_SHORT) {
1154 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1155 mibitem.data = rrq->value;
1157 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1158 result = p80211req_dorequest(wlandev, (u8*)&msg);
1160 if (result) {
1161 err = -EFAULT;
1162 goto exit;
1167 exit:
1168 DBFEXIT;
1169 return err;
1173 static int p80211wext_siwtxpow(netdevice_t *dev,
1174 struct iw_request_info *info,
1175 struct iw_param *rrq, char *extra)
1177 wlandevice_t *wlandev = dev->ml_priv;
1178 p80211item_uint32_t mibitem;
1179 p80211msg_dot11req_mibset_t msg;
1180 int result;
1181 int err = 0;
1183 DBFENTER;
1185 if (!wlan_wext_write) {
1186 err = (-EOPNOTSUPP);
1187 goto exit;
1190 msg.msgcode = DIDmsg_dot11req_mibset;
1191 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1192 if (rrq->fixed == 0)
1193 mibitem.data = 30;
1194 else
1195 mibitem.data = rrq->value;
1196 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1197 result = p80211req_dorequest(wlandev, (u8*)&msg);
1199 if (result) {
1200 err = -EFAULT;
1201 goto exit;
1204 exit:
1205 DBFEXIT;
1206 return err;
1209 static int p80211wext_giwtxpow(netdevice_t *dev,
1210 struct iw_request_info *info,
1211 struct iw_param *rrq, char *extra)
1213 wlandevice_t *wlandev = dev->ml_priv;
1214 p80211item_uint32_t mibitem;
1215 p80211msg_dot11req_mibset_t msg;
1216 int result;
1217 int err = 0;
1219 DBFENTER;
1221 msg.msgcode = DIDmsg_dot11req_mibget;
1222 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1224 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1225 result = p80211req_dorequest(wlandev, (u8*)&msg);
1227 if (result) {
1228 err = -EFAULT;
1229 goto exit;
1232 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1234 // XXX handle OFF by setting disabled = 1;
1236 rrq->flags = 0; // IW_TXPOW_DBM;
1237 rrq->disabled = 0;
1238 rrq->fixed = 0;
1239 rrq->value = mibitem.data;
1241 exit:
1242 DBFEXIT;
1243 return err;
1246 static int p80211wext_siwspy(netdevice_t *dev,
1247 struct iw_request_info *info,
1248 struct iw_point *srq, char *extra)
1250 wlandevice_t *wlandev = dev->ml_priv;
1251 struct sockaddr address[IW_MAX_SPY];
1252 int number = srq->length;
1253 int i;
1255 DBFENTER;
1257 /* Copy the data from the input buffer */
1258 memcpy(address, extra, sizeof(struct sockaddr)*number);
1260 wlandev->spy_number = 0;
1262 if (number > 0) {
1264 /* extract the addresses */
1265 for (i = 0; i < number; i++) {
1267 memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN);
1270 /* reset stats */
1271 memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
1273 /* set number of addresses */
1274 wlandev->spy_number = number;
1277 DBFEXIT;
1278 return 0;
1281 /* jkriegl: from orinoco, modified */
1282 static int p80211wext_giwspy(netdevice_t *dev,
1283 struct iw_request_info *info,
1284 struct iw_point *srq, char *extra)
1286 wlandevice_t *wlandev = dev->ml_priv;
1288 struct sockaddr address[IW_MAX_SPY];
1289 struct iw_quality spy_stat[IW_MAX_SPY];
1290 int number;
1291 int i;
1293 DBFENTER;
1295 number = wlandev->spy_number;
1297 if (number > 0) {
1299 /* populate address and spy struct's */
1300 for (i = 0; i < number; i++) {
1301 memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN);
1302 address[i].sa_family = AF_UNIX;
1303 memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality));
1306 /* reset update flag */
1307 for (i=0; i < number; i++)
1308 wlandev->spy_stat[i].updated = 0;
1311 /* push stuff to user space */
1312 srq->length = number;
1313 memcpy(extra, address, sizeof(struct sockaddr)*number);
1314 memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number);
1316 DBFEXIT;
1317 return 0;
1320 static int prism2_result2err (int prism2_result)
1322 int err = 0;
1324 switch (prism2_result) {
1325 case P80211ENUM_resultcode_invalid_parameters:
1326 err = -EINVAL;
1327 break;
1328 case P80211ENUM_resultcode_implementation_failure:
1329 err = -EIO;
1330 break;
1331 case P80211ENUM_resultcode_not_supported:
1332 err = -EOPNOTSUPP;
1333 break;
1334 default:
1335 err = 0;
1336 break;
1339 return err;
1342 static int p80211wext_siwscan(netdevice_t *dev,
1343 struct iw_request_info *info,
1344 struct iw_point *srq, char *extra)
1346 wlandevice_t *wlandev = dev->ml_priv;
1347 p80211msg_dot11req_scan_t msg;
1348 int result;
1349 int err = 0;
1350 int i = 0;
1352 DBFENTER;
1354 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1355 WLAN_LOG_ERROR("Can't scan in AP mode\n");
1356 err = (-EOPNOTSUPP);
1357 goto exit;
1360 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1361 msg.msgcode = DIDmsg_dot11req_scan;
1362 msg.bsstype.data = P80211ENUM_bsstype_any;
1364 memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t));
1365 msg.bssid.data.len = 6;
1367 msg.scantype.data = P80211ENUM_scantype_active;
1368 msg.probedelay.data = 0;
1370 for (i = 1; i <= 14; i++)
1371 msg.channellist.data.data[i-1] = i;
1372 msg.channellist.data.len = 14;
1374 msg.maxchanneltime.data = 250;
1375 msg.minchanneltime.data = 200;
1377 result = p80211req_dorequest(wlandev, (u8*)&msg);
1378 if (result)
1379 err = prism2_result2err (msg.resultcode.data);
1381 exit:
1382 DBFEXIT;
1383 return err;
1387 /* Helper to translate scan into Wireless Extensions scan results.
1388 * Inspired by the prism54 code, which was in turn inspired by the
1389 * airo driver code.
1391 static char *
1392 wext_translate_bss(struct iw_request_info *info, char *current_ev,
1393 char *end_buf, p80211msg_dot11req_scan_results_t *bss)
1395 struct iw_event iwe; /* Temporary buffer */
1397 /* The first entry must be the MAC address */
1398 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1399 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1400 iwe.cmd = SIOCGIWAP;
1401 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
1403 /* The following entries will be displayed in the same order we give them */
1405 /* The ESSID. */
1406 if (bss->ssid.data.len > 0) {
1407 char essid[IW_ESSID_MAX_SIZE + 1];
1408 int size;
1410 size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len);
1411 memset(&essid, 0, sizeof (essid));
1412 memcpy(&essid, bss->ssid.data.data, size);
1413 WLAN_LOG_DEBUG(1, " essid size = %d\n", size);
1414 iwe.u.data.length = size;
1415 iwe.u.data.flags = 1;
1416 iwe.cmd = SIOCGIWESSID;
1417 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]);
1418 WLAN_LOG_DEBUG(1, " essid size OK.\n");
1421 switch (bss->bsstype.data) {
1422 case P80211ENUM_bsstype_infrastructure:
1423 iwe.u.mode = IW_MODE_MASTER;
1424 break;
1426 case P80211ENUM_bsstype_independent:
1427 iwe.u.mode = IW_MODE_ADHOC;
1428 break;
1430 default:
1431 iwe.u.mode = 0;
1432 break;
1434 iwe.cmd = SIOCGIWMODE;
1435 if (iwe.u.mode)
1436 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
1438 /* Encryption capability */
1439 if (bss->privacy.data == P80211ENUM_truth_true)
1440 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1441 else
1442 iwe.u.data.flags = IW_ENCODE_DISABLED;
1443 iwe.u.data.length = 0;
1444 iwe.cmd = SIOCGIWENCODE;
1445 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1447 /* Add frequency. (short) bss->channel is the frequency in MHz */
1448 iwe.u.freq.m = bss->dschannel.data;
1449 iwe.u.freq.e = 0;
1450 iwe.cmd = SIOCGIWFREQ;
1451 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
1453 /* Add quality statistics */
1454 iwe.u.qual.level = bss->signal.data;
1455 iwe.u.qual.noise = bss->noise.data;
1456 /* do a simple SNR for quality */
1457 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1458 iwe.cmd = IWEVQUAL;
1459 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
1461 return current_ev;
1465 static int p80211wext_giwscan(netdevice_t *dev,
1466 struct iw_request_info *info,
1467 struct iw_point *srq, char *extra)
1469 wlandevice_t *wlandev = dev->ml_priv;
1470 p80211msg_dot11req_scan_results_t msg;
1471 int result = 0;
1472 int err = 0;
1473 int i = 0;
1474 int scan_good = 0;
1475 char *current_ev = extra;
1477 DBFENTER;
1479 /* Since wireless tools doesn't really have a way of passing how
1480 * many scan results results there were back here, keep grabbing them
1481 * until we fail.
1483 do {
1484 memset(&msg, 0, sizeof(msg));
1485 msg.msgcode = DIDmsg_dot11req_scan_results;
1486 msg.bssindex.data = i;
1488 result = p80211req_dorequest(wlandev, (u8*)&msg);
1489 if ((result != 0) ||
1490 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1491 break;
1494 current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg);
1495 scan_good = 1;
1496 i++;
1497 } while (i < IW_MAX_AP);
1499 srq->length = (current_ev - extra);
1500 srq->flags = 0; /* todo */
1502 if (result && !scan_good)
1503 err = prism2_result2err (msg.resultcode.data);
1505 DBFEXIT;
1506 return err;
1509 /*****************************************************/
1510 //extra wireless extensions stuff to support NetworkManager (I hope)
1512 /* SIOCSIWENCODEEXT */
1513 static int p80211wext_set_encodeext(struct net_device *dev,
1514 struct iw_request_info *info,
1515 union iwreq_data *wrqu, char *extra)
1517 wlandevice_t *wlandev = dev->ml_priv;
1518 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1519 p80211msg_dot11req_mibset_t msg;
1520 p80211item_pstr32_t *pstr;
1522 int result = 0;
1523 struct iw_point *encoding = &wrqu->encoding;
1524 int idx = encoding->flags & IW_ENCODE_INDEX;
1526 WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1529 if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
1530 // set default key ? I'm not sure if this the the correct thing to do here
1532 if ( idx ) {
1533 if (idx < 1 || idx > NUM_WEPKEYS) {
1534 return -EINVAL;
1535 } else
1536 idx--;
1538 WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx);
1539 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx);
1540 if ( result )
1541 return -EFAULT;
1545 if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) {
1546 if (!(ext->alg & IW_ENCODE_ALG_WEP)) {
1547 WLAN_LOG_DEBUG(1,"asked to set a non wep key :(");
1548 return -EINVAL;
1550 if (idx) {
1551 if (idx <1 || idx > NUM_WEPKEYS)
1552 return -EINVAL;
1553 else
1554 idx--;
1556 WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx);
1557 wlandev->wep_keylens[idx] = ext->key_len;
1558 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1560 memset( &msg,0,sizeof(msg));
1561 pstr = (p80211item_pstr32_t*)&msg.mibattribute.data;
1562 memcpy(pstr->data.data, ext->key,ext->key_len);
1563 pstr->data.len = ext->key_len;
1564 switch (idx) {
1565 case 0:
1566 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1567 break;
1568 case 1:
1569 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1570 break;
1571 case 2:
1572 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1573 break;
1574 case 3:
1575 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1576 break;
1577 default:
1578 break;
1580 msg.msgcode = DIDmsg_dot11req_mibset;
1581 result = p80211req_dorequest(wlandev,(u8*)&msg);
1582 WLAN_LOG_DEBUG(1,"result (%d)\n",result);
1584 return result;
1587 /* SIOCGIWENCODEEXT */
1588 static int p80211wext_get_encodeext(struct net_device *dev,
1589 struct iw_request_info *info,
1590 union iwreq_data *wrqu, char *extra)
1593 wlandevice_t *wlandev = dev->ml_priv;
1594 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1596 struct iw_point *encoding = &wrqu->encoding;
1597 int result = 0;
1598 int max_len;
1599 int idx;
1601 DBFENTER;
1603 WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1606 max_len = encoding->length - sizeof(*ext);
1607 if ( max_len <= 0) {
1608 WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len);
1609 result = -EINVAL;
1610 goto exit;
1612 idx = encoding->flags & IW_ENCODE_INDEX;
1614 WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx);
1616 if (idx) {
1617 if (idx < 1 || idx > NUM_WEPKEYS ) {
1618 WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx);
1619 result = -EINVAL;
1620 goto exit;
1622 idx--;
1623 } else {
1624 /* default key ? not sure what to do */
1625 /* will just use key[0] for now ! FIX ME */
1628 encoding->flags = idx + 1;
1629 memset(ext,0,sizeof(*ext));
1631 ext->alg = IW_ENCODE_ALG_WEP;
1632 ext->key_len = wlandev->wep_keylens[idx];
1633 memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len );
1635 encoding->flags |= IW_ENCODE_ENABLED;
1636 exit:
1637 DBFEXIT;
1639 return result;
1643 /* SIOCSIWAUTH */
1644 static int p80211_wext_set_iwauth (struct net_device *dev,
1645 struct iw_request_info *info,
1646 union iwreq_data *wrqu, char *extra)
1648 wlandevice_t *wlandev = dev->ml_priv;
1649 struct iw_param *param = &wrqu->param;
1650 int result =0;
1652 WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1654 switch (param->flags & IW_AUTH_INDEX) {
1655 case IW_AUTH_DROP_UNENCRYPTED:
1656 WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value);
1657 if (param->value)
1658 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
1659 else
1660 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
1661 break;
1663 case IW_AUTH_PRIVACY_INVOKED:
1664 WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value);
1665 if ( param->value)
1666 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
1667 else
1668 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
1670 break;
1672 case IW_AUTH_80211_AUTH_ALG:
1673 if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) {
1674 WLAN_LOG_DEBUG(1,"set open_system\n");
1675 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1676 } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) {
1677 WLAN_LOG_DEBUG(1,"set shared key\n");
1678 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1679 } else {
1680 /* don't know what to do know :( */
1681 WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value);
1682 result = -EINVAL;
1684 break;
1686 default:
1687 break;
1692 return result;
1695 /* SIOCSIWAUTH */
1696 static int p80211_wext_get_iwauth (struct net_device *dev,
1697 struct iw_request_info *info,
1698 union iwreq_data *wrqu, char *extra)
1700 wlandevice_t *wlandev = dev->ml_priv;
1701 struct iw_param *param = &wrqu->param;
1702 int result =0;
1704 WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1706 switch (param->flags & IW_AUTH_INDEX) {
1707 case IW_AUTH_DROP_UNENCRYPTED:
1708 param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0;
1709 break;
1711 case IW_AUTH_PRIVACY_INVOKED:
1712 param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0;
1713 break;
1715 case IW_AUTH_80211_AUTH_ALG:
1716 param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM;
1717 break;
1720 default:
1721 break;
1726 return result;
1729 static iw_handler p80211wext_handlers[] = {
1730 (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
1731 (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
1732 (iw_handler) NULL, /* SIOCSIWNWID */
1733 (iw_handler) NULL, /* SIOCGIWNWID */
1734 (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
1735 (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
1736 (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
1737 (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
1738 (iw_handler) NULL, /* SIOCSIWSENS */
1739 (iw_handler) NULL, /* SIOCGIWSENS */
1740 (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */
1741 (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
1742 (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */
1743 (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */
1744 (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */
1745 (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */
1746 (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
1747 (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
1748 (iw_handler) NULL, /* -- hole -- */
1749 (iw_handler) NULL, /* -- hole -- */
1750 (iw_handler) NULL, /* SIOCSIWAP */
1751 (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
1752 (iw_handler) NULL, /* -- hole -- */
1753 (iw_handler) NULL, /* SIOCGIWAPLIST */
1754 (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
1755 (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
1756 (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
1757 (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
1758 (iw_handler) NULL, /* SIOCSIWNICKN */
1759 (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
1760 (iw_handler) NULL, /* -- hole -- */
1761 (iw_handler) NULL, /* -- hole -- */
1762 (iw_handler) NULL, /* SIOCSIWRATE */
1763 (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
1764 (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
1765 (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
1766 (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
1767 (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
1768 (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
1769 (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
1770 (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
1771 (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
1772 (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
1773 (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
1774 (iw_handler) NULL, /* SIOCSIWPOWER */
1775 (iw_handler) NULL, /* SIOCGIWPOWER */
1776 /* WPA operations */
1777 (iw_handler) NULL, /* -- hole -- */
1778 (iw_handler) NULL, /* -- hole -- */
1779 (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
1780 (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
1781 (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
1782 (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
1784 (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
1785 (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
1786 (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
1789 struct iw_handler_def p80211wext_handler_def = {
1790 .num_standard = sizeof(p80211wext_handlers) / sizeof(iw_handler),
1791 .num_private = 0,
1792 .num_private_args = 0,
1793 .standard = p80211wext_handlers,
1794 .private = NULL,
1795 .private_args = NULL,
1796 .get_wireless_stats = p80211wext_get_wireless_stats
1800 int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
1802 union iwreq_data data;
1804 DBFENTER;
1806 /* Send the association state first */
1807 data.ap_addr.sa_family = ARPHRD_ETHER;
1808 if (assoc) {
1809 memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN);
1810 } else {
1811 memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN);
1814 if (wlan_wext_write)
1815 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1817 if (!assoc) goto done;
1819 // XXX send association data, like IEs, etc etc.
1821 done:
1822 DBFEXIT;
1823 return 0;