3w-xxxx: scsi_dma_unmap fix
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / wlan-ng / p80211wext.c
blob0d570f1f378cd2274df70c0a43c596e5de686e27
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 ARRAY_SIZE(p80211wext_channel_freq)
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 i;
596 DBFENTER;
597 if (!wlan_wext_write) {
598 err = (-EOPNOTSUPP);
599 goto exit;
602 /* Check the Key index first. */
603 if((i = (erq->flags & IW_ENCODE_INDEX))) {
605 if ((i < 1) || (i > NUM_WEPKEYS)) {
606 err = -EINVAL;
607 goto exit;
609 else
610 i--;
612 /* Set current key number only if no keys are given */
613 if (erq->flags & IW_ENCODE_NOKEY) {
614 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i);
616 if (result) {
617 err = -EFAULT;
618 goto exit;
622 } else {
623 // Use defaultkey if no Key Index
624 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
627 /* Check if there is no key information in the iwconfig request */
628 if((erq->flags & IW_ENCODE_NOKEY) == 0 ) {
630 /*------------------------------------------------------------
631 * If there is WEP Key for setting, check the Key Information
632 * and then set it to the firmware.
633 -------------------------------------------------------------*/
635 if (erq->length > 0) {
637 /* copy the key from the driver cache as the keys are read-only MIBs */
638 wlandev->wep_keylens[i] = erq->length;
639 memcpy(wlandev->wep_keys[i], key, erq->length);
641 /* Prepare data struture for p80211req_dorequest. */
642 memcpy(pstr.data.data, key, erq->length);
643 pstr.data.len = erq->length;
645 switch(i)
647 case 0:
648 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
649 break;
651 case 1:
652 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
653 break;
655 case 2:
656 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
657 break;
659 case 3:
660 pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
661 break;
663 default:
664 err = -EINVAL;
665 goto exit;
668 msg.msgcode = DIDmsg_dot11req_mibset;
669 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
670 result = p80211req_dorequest(wlandev, (u8*)&msg);
672 if (result) {
673 err = -EFAULT;
674 goto exit;
680 /* Check the PrivacyInvoked flag */
681 if (erq->flags & IW_ENCODE_DISABLED) {
682 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
683 } else {
684 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
687 if (result) {
688 err = -EFAULT;
689 goto exit;
692 /* The security mode may be open or restricted, and its meaning
693 depends on the card used. With most cards, in open mode no
694 authentication is used and the card may also accept non-
695 encrypted sessions, whereas in restricted mode only encrypted
696 sessions are accepted and the card will use authentication if
697 available.
699 if (erq->flags & IW_ENCODE_RESTRICTED) {
700 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
702 else if (erq->flags & IW_ENCODE_OPEN) {
703 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
706 if (result) {
707 err = -EFAULT;
708 goto exit;
711 exit:
713 DBFEXIT;
714 return err;
717 static int p80211wext_giwessid(netdevice_t *dev,
718 struct iw_request_info *info,
719 struct iw_point *data, char *essid)
721 wlandevice_t *wlandev = dev->ml_priv;
723 DBFENTER;
725 if (wlandev->ssid.len) {
726 data->length = wlandev->ssid.len;
727 data->flags = 1;
728 memcpy(essid, wlandev->ssid.data, data->length);
729 essid[data->length] = 0;
730 #if (WIRELESS_EXT < 21)
731 data->length++;
732 #endif
733 } else {
734 memset(essid, 0, sizeof(wlandev->ssid.data));
735 data->length = 0;
736 data->flags = 0;
739 DBFEXIT;
740 return 0;
743 static int p80211wext_siwessid(netdevice_t *dev,
744 struct iw_request_info *info,
745 struct iw_point *data, char *essid)
747 wlandevice_t *wlandev = dev->ml_priv;
748 p80211msg_lnxreq_autojoin_t msg;
750 int result;
751 int err = 0;
752 int length = data->length;
754 DBFENTER;
756 if (!wlan_wext_write) {
757 err = (-EOPNOTSUPP);
758 goto exit;
762 if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
763 msg.authtype.data = P80211ENUM_authalg_sharedkey;
764 else
765 msg.authtype.data = P80211ENUM_authalg_opensystem;
767 msg.msgcode = DIDmsg_lnxreq_autojoin;
769 #if (WIRELESS_EXT < 21)
770 if (length) length--;
771 #endif
773 /* Trim the last '\0' to fit the SSID format */
775 if (length && essid[length-1] == '\0') {
776 length--;
779 memcpy(msg.ssid.data.data, essid, length);
780 msg.ssid.data.len = length;
782 WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid);
783 result = p80211req_dorequest(wlandev, (u8*)&msg);
784 WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result);
786 if (result) {
787 err = -EFAULT;
788 goto exit;
791 exit:
792 DBFEXIT;
793 return err;
797 static int p80211wext_siwcommit(netdevice_t *dev,
798 struct iw_request_info *info,
799 struct iw_point *data, char *essid)
801 wlandevice_t *wlandev = dev->ml_priv;
802 int err = 0;
804 DBFENTER;
806 if (!wlan_wext_write) {
807 err = (-EOPNOTSUPP);
808 goto exit;
811 /* Auto Join */
812 err = p80211wext_autojoin(wlandev);
814 exit:
815 DBFEXIT;
816 return err;
820 static int p80211wext_giwrate(netdevice_t *dev,
821 struct iw_request_info *info,
822 struct iw_param *rrq, char *extra)
824 wlandevice_t *wlandev = dev->ml_priv;
825 p80211item_uint32_t mibitem;
826 p80211msg_dot11req_mibset_t msg;
827 int result;
828 int err = 0;
830 DBFENTER;
832 msg.msgcode = DIDmsg_dot11req_mibget;
833 mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
834 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
835 result = p80211req_dorequest(wlandev, (u8*)&msg);
837 if (result) {
838 err = -EFAULT;
839 goto exit;
842 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
844 rrq->fixed = 0; /* can it change? */
845 rrq->disabled = 0;
846 rrq->value = 0;
848 #define HFA384x_RATEBIT_1 ((u16)1)
849 #define HFA384x_RATEBIT_2 ((u16)2)
850 #define HFA384x_RATEBIT_5dot5 ((u16)4)
851 #define HFA384x_RATEBIT_11 ((u16)8)
853 switch (mibitem.data) {
854 case HFA384x_RATEBIT_1:
855 rrq->value = 1000000;
856 break;
857 case HFA384x_RATEBIT_2:
858 rrq->value = 2000000;
859 break;
860 case HFA384x_RATEBIT_5dot5:
861 rrq->value = 5500000;
862 break;
863 case HFA384x_RATEBIT_11:
864 rrq->value = 11000000;
865 break;
866 default:
867 err = -EINVAL;
869 exit:
870 DBFEXIT;
871 return err;
874 static int p80211wext_giwrts(netdevice_t *dev,
875 struct iw_request_info *info,
876 struct iw_param *rts, char *extra)
878 wlandevice_t *wlandev = dev->ml_priv;
879 p80211item_uint32_t mibitem;
880 p80211msg_dot11req_mibset_t msg;
881 int result;
882 int err = 0;
884 DBFENTER;
886 msg.msgcode = DIDmsg_dot11req_mibget;
887 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
888 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
889 result = p80211req_dorequest(wlandev, (u8*)&msg);
891 if (result) {
892 err = -EFAULT;
893 goto exit;
896 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
898 rts->value = mibitem.data;
899 rts->disabled = (rts->value == 2347);
900 rts->fixed = 1;
902 exit:
903 DBFEXIT;
904 return err;
908 static int p80211wext_siwrts(netdevice_t *dev,
909 struct iw_request_info *info,
910 struct iw_param *rts, char *extra)
912 wlandevice_t *wlandev = dev->ml_priv;
913 p80211item_uint32_t mibitem;
914 p80211msg_dot11req_mibset_t msg;
915 int result;
916 int err = 0;
918 DBFENTER;
920 if (!wlan_wext_write) {
921 err = (-EOPNOTSUPP);
922 goto exit;
925 msg.msgcode = DIDmsg_dot11req_mibget;
926 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
927 if (rts->disabled)
928 mibitem.data = 2347;
929 else
930 mibitem.data = rts->value;
932 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
933 result = p80211req_dorequest(wlandev, (u8*)&msg);
935 if (result) {
936 err = -EFAULT;
937 goto exit;
940 exit:
941 DBFEXIT;
942 return err;
945 static int p80211wext_giwfrag(netdevice_t *dev,
946 struct iw_request_info *info,
947 struct iw_param *frag, char *extra)
949 wlandevice_t *wlandev = dev->ml_priv;
950 p80211item_uint32_t mibitem;
951 p80211msg_dot11req_mibset_t msg;
952 int result;
953 int err = 0;
955 DBFENTER;
957 msg.msgcode = DIDmsg_dot11req_mibget;
958 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
959 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
960 result = p80211req_dorequest(wlandev, (u8*)&msg);
962 if (result) {
963 err = -EFAULT;
964 goto exit;
967 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
969 frag->value = mibitem.data;
970 frag->disabled = (frag->value == 2346);
971 frag->fixed = 1;
973 exit:
974 DBFEXIT;
975 return err;
978 static int p80211wext_siwfrag(netdevice_t *dev,
979 struct iw_request_info *info,
980 struct iw_param *frag, char *extra)
982 wlandevice_t *wlandev = dev->ml_priv;
983 p80211item_uint32_t mibitem;
984 p80211msg_dot11req_mibset_t msg;
985 int result;
986 int err = 0;
988 DBFENTER;
990 if (!wlan_wext_write) {
991 err = (-EOPNOTSUPP);
992 goto exit;
995 msg.msgcode = DIDmsg_dot11req_mibset;
996 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
998 if (frag->disabled)
999 mibitem.data = 2346;
1000 else
1001 mibitem.data = frag->value;
1003 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1004 result = p80211req_dorequest(wlandev, (u8*)&msg);
1006 if (result) {
1007 err = -EFAULT;
1008 goto exit;
1011 exit:
1012 DBFEXIT;
1013 return err;
1016 #ifndef IW_RETRY_LONG
1017 #define IW_RETRY_LONG IW_RETRY_MAX
1018 #endif
1020 #ifndef IW_RETRY_SHORT
1021 #define IW_RETRY_SHORT IW_RETRY_MIN
1022 #endif
1024 static int p80211wext_giwretry(netdevice_t *dev,
1025 struct iw_request_info *info,
1026 struct iw_param *rrq, char *extra)
1028 wlandevice_t *wlandev = dev->ml_priv;
1029 p80211item_uint32_t mibitem;
1030 p80211msg_dot11req_mibset_t msg;
1031 int result;
1032 int err = 0;
1033 u16 shortretry, longretry, lifetime;
1035 DBFENTER;
1037 msg.msgcode = DIDmsg_dot11req_mibget;
1038 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1040 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1041 result = p80211req_dorequest(wlandev, (u8*)&msg);
1043 if (result) {
1044 err = -EFAULT;
1045 goto exit;
1048 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1050 shortretry = mibitem.data;
1052 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1054 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1055 result = p80211req_dorequest(wlandev, (u8*)&msg);
1057 if (result) {
1058 err = -EFAULT;
1059 goto exit;
1062 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1064 longretry = mibitem.data;
1066 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1068 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1069 result = p80211req_dorequest(wlandev, (u8*)&msg);
1071 if (result) {
1072 err = -EFAULT;
1073 goto exit;
1076 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1078 lifetime = mibitem.data;
1080 rrq->disabled = 0;
1082 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1083 rrq->flags = IW_RETRY_LIFETIME;
1084 rrq->value = lifetime * 1024;
1085 } else {
1086 if (rrq->flags & IW_RETRY_LONG) {
1087 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1088 rrq->value = longretry;
1089 } else {
1090 rrq->flags = IW_RETRY_LIMIT;
1091 rrq->value = shortretry;
1092 if (shortretry != longretry)
1093 rrq->flags |= IW_RETRY_SHORT;
1097 exit:
1098 DBFEXIT;
1099 return err;
1103 static int p80211wext_siwretry(netdevice_t *dev,
1104 struct iw_request_info *info,
1105 struct iw_param *rrq, char *extra)
1107 wlandevice_t *wlandev = dev->ml_priv;
1108 p80211item_uint32_t mibitem;
1109 p80211msg_dot11req_mibset_t msg;
1110 int result;
1111 int err = 0;
1113 DBFENTER;
1115 if (!wlan_wext_write) {
1116 err = (-EOPNOTSUPP);
1117 goto exit;
1120 if (rrq->disabled) {
1121 err = -EINVAL;
1122 goto exit;
1125 msg.msgcode = DIDmsg_dot11req_mibset;
1127 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1128 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1129 mibitem.data = rrq->value /= 1024;
1131 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1132 result = p80211req_dorequest(wlandev, (u8*)&msg);
1134 if (result) {
1135 err = -EFAULT;
1136 goto exit;
1138 } else {
1139 if (rrq->flags & IW_RETRY_LONG) {
1140 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1141 mibitem.data = rrq->value;
1143 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1144 result = p80211req_dorequest(wlandev, (u8*)&msg);
1146 if (result) {
1147 err = -EFAULT;
1148 goto exit;
1152 if (rrq->flags & IW_RETRY_SHORT) {
1153 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1154 mibitem.data = rrq->value;
1156 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1157 result = p80211req_dorequest(wlandev, (u8*)&msg);
1159 if (result) {
1160 err = -EFAULT;
1161 goto exit;
1166 exit:
1167 DBFEXIT;
1168 return err;
1172 static int p80211wext_siwtxpow(netdevice_t *dev,
1173 struct iw_request_info *info,
1174 struct iw_param *rrq, char *extra)
1176 wlandevice_t *wlandev = dev->ml_priv;
1177 p80211item_uint32_t mibitem;
1178 p80211msg_dot11req_mibset_t msg;
1179 int result;
1180 int err = 0;
1182 DBFENTER;
1184 if (!wlan_wext_write) {
1185 err = (-EOPNOTSUPP);
1186 goto exit;
1189 msg.msgcode = DIDmsg_dot11req_mibset;
1190 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1191 if (rrq->fixed == 0)
1192 mibitem.data = 30;
1193 else
1194 mibitem.data = rrq->value;
1195 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1196 result = p80211req_dorequest(wlandev, (u8*)&msg);
1198 if (result) {
1199 err = -EFAULT;
1200 goto exit;
1203 exit:
1204 DBFEXIT;
1205 return err;
1208 static int p80211wext_giwtxpow(netdevice_t *dev,
1209 struct iw_request_info *info,
1210 struct iw_param *rrq, char *extra)
1212 wlandevice_t *wlandev = dev->ml_priv;
1213 p80211item_uint32_t mibitem;
1214 p80211msg_dot11req_mibset_t msg;
1215 int result;
1216 int err = 0;
1218 DBFENTER;
1220 msg.msgcode = DIDmsg_dot11req_mibget;
1221 mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1223 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1224 result = p80211req_dorequest(wlandev, (u8*)&msg);
1226 if (result) {
1227 err = -EFAULT;
1228 goto exit;
1231 memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1233 // XXX handle OFF by setting disabled = 1;
1235 rrq->flags = 0; // IW_TXPOW_DBM;
1236 rrq->disabled = 0;
1237 rrq->fixed = 0;
1238 rrq->value = mibitem.data;
1240 exit:
1241 DBFEXIT;
1242 return err;
1245 static int p80211wext_siwspy(netdevice_t *dev,
1246 struct iw_request_info *info,
1247 struct iw_point *srq, char *extra)
1249 wlandevice_t *wlandev = dev->ml_priv;
1250 struct sockaddr address[IW_MAX_SPY];
1251 int number = srq->length;
1252 int i;
1254 DBFENTER;
1256 /* Copy the data from the input buffer */
1257 memcpy(address, extra, sizeof(struct sockaddr)*number);
1259 wlandev->spy_number = 0;
1261 if (number > 0) {
1263 /* extract the addresses */
1264 for (i = 0; i < number; i++) {
1266 memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN);
1269 /* reset stats */
1270 memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
1272 /* set number of addresses */
1273 wlandev->spy_number = number;
1276 DBFEXIT;
1277 return 0;
1280 /* jkriegl: from orinoco, modified */
1281 static int p80211wext_giwspy(netdevice_t *dev,
1282 struct iw_request_info *info,
1283 struct iw_point *srq, char *extra)
1285 wlandevice_t *wlandev = dev->ml_priv;
1287 struct sockaddr address[IW_MAX_SPY];
1288 struct iw_quality spy_stat[IW_MAX_SPY];
1289 int number;
1290 int i;
1292 DBFENTER;
1294 number = wlandev->spy_number;
1296 if (number > 0) {
1298 /* populate address and spy struct's */
1299 for (i = 0; i < number; i++) {
1300 memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN);
1301 address[i].sa_family = AF_UNIX;
1302 memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality));
1305 /* reset update flag */
1306 for (i=0; i < number; i++)
1307 wlandev->spy_stat[i].updated = 0;
1310 /* push stuff to user space */
1311 srq->length = number;
1312 memcpy(extra, address, sizeof(struct sockaddr)*number);
1313 memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number);
1315 DBFEXIT;
1316 return 0;
1319 static int prism2_result2err (int prism2_result)
1321 int err = 0;
1323 switch (prism2_result) {
1324 case P80211ENUM_resultcode_invalid_parameters:
1325 err = -EINVAL;
1326 break;
1327 case P80211ENUM_resultcode_implementation_failure:
1328 err = -EIO;
1329 break;
1330 case P80211ENUM_resultcode_not_supported:
1331 err = -EOPNOTSUPP;
1332 break;
1333 default:
1334 err = 0;
1335 break;
1338 return err;
1341 static int p80211wext_siwscan(netdevice_t *dev,
1342 struct iw_request_info *info,
1343 struct iw_point *srq, char *extra)
1345 wlandevice_t *wlandev = dev->ml_priv;
1346 p80211msg_dot11req_scan_t msg;
1347 int result;
1348 int err = 0;
1349 int i = 0;
1351 DBFENTER;
1353 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1354 WLAN_LOG_ERROR("Can't scan in AP mode\n");
1355 err = (-EOPNOTSUPP);
1356 goto exit;
1359 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1360 msg.msgcode = DIDmsg_dot11req_scan;
1361 msg.bsstype.data = P80211ENUM_bsstype_any;
1363 memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t));
1364 msg.bssid.data.len = 6;
1366 msg.scantype.data = P80211ENUM_scantype_active;
1367 msg.probedelay.data = 0;
1369 for (i = 1; i <= 14; i++)
1370 msg.channellist.data.data[i-1] = i;
1371 msg.channellist.data.len = 14;
1373 msg.maxchanneltime.data = 250;
1374 msg.minchanneltime.data = 200;
1376 result = p80211req_dorequest(wlandev, (u8*)&msg);
1377 if (result)
1378 err = prism2_result2err (msg.resultcode.data);
1380 exit:
1381 DBFEXIT;
1382 return err;
1386 /* Helper to translate scan into Wireless Extensions scan results.
1387 * Inspired by the prism54 code, which was in turn inspired by the
1388 * airo driver code.
1390 static char *
1391 wext_translate_bss(struct iw_request_info *info, char *current_ev,
1392 char *end_buf, p80211msg_dot11req_scan_results_t *bss)
1394 struct iw_event iwe; /* Temporary buffer */
1396 /* The first entry must be the MAC address */
1397 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1398 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1399 iwe.cmd = SIOCGIWAP;
1400 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
1402 /* The following entries will be displayed in the same order we give them */
1404 /* The ESSID. */
1405 if (bss->ssid.data.len > 0) {
1406 char essid[IW_ESSID_MAX_SIZE + 1];
1407 int size;
1409 size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len);
1410 memset(&essid, 0, sizeof (essid));
1411 memcpy(&essid, bss->ssid.data.data, size);
1412 WLAN_LOG_DEBUG(1, " essid size = %d\n", size);
1413 iwe.u.data.length = size;
1414 iwe.u.data.flags = 1;
1415 iwe.cmd = SIOCGIWESSID;
1416 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]);
1417 WLAN_LOG_DEBUG(1, " essid size OK.\n");
1420 switch (bss->bsstype.data) {
1421 case P80211ENUM_bsstype_infrastructure:
1422 iwe.u.mode = IW_MODE_MASTER;
1423 break;
1425 case P80211ENUM_bsstype_independent:
1426 iwe.u.mode = IW_MODE_ADHOC;
1427 break;
1429 default:
1430 iwe.u.mode = 0;
1431 break;
1433 iwe.cmd = SIOCGIWMODE;
1434 if (iwe.u.mode)
1435 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
1437 /* Encryption capability */
1438 if (bss->privacy.data == P80211ENUM_truth_true)
1439 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1440 else
1441 iwe.u.data.flags = IW_ENCODE_DISABLED;
1442 iwe.u.data.length = 0;
1443 iwe.cmd = SIOCGIWENCODE;
1444 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1446 /* Add frequency. (short) bss->channel is the frequency in MHz */
1447 iwe.u.freq.m = bss->dschannel.data;
1448 iwe.u.freq.e = 0;
1449 iwe.cmd = SIOCGIWFREQ;
1450 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
1452 /* Add quality statistics */
1453 iwe.u.qual.level = bss->signal.data;
1454 iwe.u.qual.noise = bss->noise.data;
1455 /* do a simple SNR for quality */
1456 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1457 iwe.cmd = IWEVQUAL;
1458 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
1460 return current_ev;
1464 static int p80211wext_giwscan(netdevice_t *dev,
1465 struct iw_request_info *info,
1466 struct iw_point *srq, char *extra)
1468 wlandevice_t *wlandev = dev->ml_priv;
1469 p80211msg_dot11req_scan_results_t msg;
1470 int result = 0;
1471 int err = 0;
1472 int i = 0;
1473 int scan_good = 0;
1474 char *current_ev = extra;
1476 DBFENTER;
1478 /* Since wireless tools doesn't really have a way of passing how
1479 * many scan results results there were back here, keep grabbing them
1480 * until we fail.
1482 do {
1483 memset(&msg, 0, sizeof(msg));
1484 msg.msgcode = DIDmsg_dot11req_scan_results;
1485 msg.bssindex.data = i;
1487 result = p80211req_dorequest(wlandev, (u8*)&msg);
1488 if ((result != 0) ||
1489 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1490 break;
1493 current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg);
1494 scan_good = 1;
1495 i++;
1496 } while (i < IW_MAX_AP);
1498 srq->length = (current_ev - extra);
1499 srq->flags = 0; /* todo */
1501 if (result && !scan_good)
1502 err = prism2_result2err (msg.resultcode.data);
1504 DBFEXIT;
1505 return err;
1508 /*****************************************************/
1509 //extra wireless extensions stuff to support NetworkManager (I hope)
1511 /* SIOCSIWENCODEEXT */
1512 static int p80211wext_set_encodeext(struct net_device *dev,
1513 struct iw_request_info *info,
1514 union iwreq_data *wrqu, char *extra)
1516 wlandevice_t *wlandev = dev->ml_priv;
1517 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1518 p80211msg_dot11req_mibset_t msg;
1519 p80211item_pstr32_t *pstr;
1521 int result = 0;
1522 struct iw_point *encoding = &wrqu->encoding;
1523 int idx = encoding->flags & IW_ENCODE_INDEX;
1525 WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1528 if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
1529 // set default key ? I'm not sure if this the the correct thing to do here
1531 if ( idx ) {
1532 if (idx < 1 || idx > NUM_WEPKEYS) {
1533 return -EINVAL;
1534 } else
1535 idx--;
1537 WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx);
1538 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx);
1539 if ( result )
1540 return -EFAULT;
1544 if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) {
1545 if (!(ext->alg & IW_ENCODE_ALG_WEP)) {
1546 WLAN_LOG_DEBUG(1,"asked to set a non wep key :(");
1547 return -EINVAL;
1549 if (idx) {
1550 if (idx <1 || idx > NUM_WEPKEYS)
1551 return -EINVAL;
1552 else
1553 idx--;
1555 WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx);
1556 wlandev->wep_keylens[idx] = ext->key_len;
1557 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1559 memset( &msg,0,sizeof(msg));
1560 pstr = (p80211item_pstr32_t*)&msg.mibattribute.data;
1561 memcpy(pstr->data.data, ext->key,ext->key_len);
1562 pstr->data.len = ext->key_len;
1563 switch (idx) {
1564 case 0:
1565 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1566 break;
1567 case 1:
1568 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1569 break;
1570 case 2:
1571 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1572 break;
1573 case 3:
1574 pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1575 break;
1576 default:
1577 break;
1579 msg.msgcode = DIDmsg_dot11req_mibset;
1580 result = p80211req_dorequest(wlandev,(u8*)&msg);
1581 WLAN_LOG_DEBUG(1,"result (%d)\n",result);
1583 return result;
1586 /* SIOCGIWENCODEEXT */
1587 static int p80211wext_get_encodeext(struct net_device *dev,
1588 struct iw_request_info *info,
1589 union iwreq_data *wrqu, char *extra)
1592 wlandevice_t *wlandev = dev->ml_priv;
1593 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1595 struct iw_point *encoding = &wrqu->encoding;
1596 int result = 0;
1597 int max_len;
1598 int idx;
1600 DBFENTER;
1602 WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1605 max_len = encoding->length - sizeof(*ext);
1606 if ( max_len <= 0) {
1607 WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len);
1608 result = -EINVAL;
1609 goto exit;
1611 idx = encoding->flags & IW_ENCODE_INDEX;
1613 WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx);
1615 if (idx) {
1616 if (idx < 1 || idx > NUM_WEPKEYS ) {
1617 WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx);
1618 result = -EINVAL;
1619 goto exit;
1621 idx--;
1622 } else {
1623 /* default key ? not sure what to do */
1624 /* will just use key[0] for now ! FIX ME */
1627 encoding->flags = idx + 1;
1628 memset(ext,0,sizeof(*ext));
1630 ext->alg = IW_ENCODE_ALG_WEP;
1631 ext->key_len = wlandev->wep_keylens[idx];
1632 memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len );
1634 encoding->flags |= IW_ENCODE_ENABLED;
1635 exit:
1636 DBFEXIT;
1638 return result;
1642 /* SIOCSIWAUTH */
1643 static int p80211_wext_set_iwauth (struct net_device *dev,
1644 struct iw_request_info *info,
1645 union iwreq_data *wrqu, char *extra)
1647 wlandevice_t *wlandev = dev->ml_priv;
1648 struct iw_param *param = &wrqu->param;
1649 int result =0;
1651 WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1653 switch (param->flags & IW_AUTH_INDEX) {
1654 case IW_AUTH_DROP_UNENCRYPTED:
1655 WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value);
1656 if (param->value)
1657 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
1658 else
1659 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
1660 break;
1662 case IW_AUTH_PRIVACY_INVOKED:
1663 WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value);
1664 if ( param->value)
1665 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
1666 else
1667 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
1669 break;
1671 case IW_AUTH_80211_AUTH_ALG:
1672 if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) {
1673 WLAN_LOG_DEBUG(1,"set open_system\n");
1674 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1675 } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) {
1676 WLAN_LOG_DEBUG(1,"set shared key\n");
1677 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1678 } else {
1679 /* don't know what to do know :( */
1680 WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value);
1681 result = -EINVAL;
1683 break;
1685 default:
1686 break;
1691 return result;
1694 /* SIOCSIWAUTH */
1695 static int p80211_wext_get_iwauth (struct net_device *dev,
1696 struct iw_request_info *info,
1697 union iwreq_data *wrqu, char *extra)
1699 wlandevice_t *wlandev = dev->ml_priv;
1700 struct iw_param *param = &wrqu->param;
1701 int result =0;
1703 WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1705 switch (param->flags & IW_AUTH_INDEX) {
1706 case IW_AUTH_DROP_UNENCRYPTED:
1707 param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0;
1708 break;
1710 case IW_AUTH_PRIVACY_INVOKED:
1711 param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0;
1712 break;
1714 case IW_AUTH_80211_AUTH_ALG:
1715 param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM;
1716 break;
1719 default:
1720 break;
1725 return result;
1728 static iw_handler p80211wext_handlers[] = {
1729 (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */
1730 (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */
1731 (iw_handler) NULL, /* SIOCSIWNWID */
1732 (iw_handler) NULL, /* SIOCGIWNWID */
1733 (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */
1734 (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */
1735 (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */
1736 (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */
1737 (iw_handler) NULL, /* SIOCSIWSENS */
1738 (iw_handler) NULL, /* SIOCGIWSENS */
1739 (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */
1740 (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */
1741 (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */
1742 (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */
1743 (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */
1744 (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */
1745 (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */
1746 (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */
1747 (iw_handler) NULL, /* -- hole -- */
1748 (iw_handler) NULL, /* -- hole -- */
1749 (iw_handler) NULL, /* SIOCSIWAP */
1750 (iw_handler) p80211wext_giwap, /* SIOCGIWAP */
1751 (iw_handler) NULL, /* -- hole -- */
1752 (iw_handler) NULL, /* SIOCGIWAPLIST */
1753 (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */
1754 (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */
1755 (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */
1756 (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */
1757 (iw_handler) NULL, /* SIOCSIWNICKN */
1758 (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */
1759 (iw_handler) NULL, /* -- hole -- */
1760 (iw_handler) NULL, /* -- hole -- */
1761 (iw_handler) NULL, /* SIOCSIWRATE */
1762 (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */
1763 (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */
1764 (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */
1765 (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */
1766 (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */
1767 (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */
1768 (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */
1769 (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */
1770 (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */
1771 (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */
1772 (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */
1773 (iw_handler) NULL, /* SIOCSIWPOWER */
1774 (iw_handler) NULL, /* SIOCGIWPOWER */
1775 /* WPA operations */
1776 (iw_handler) NULL, /* -- hole -- */
1777 (iw_handler) NULL, /* -- hole -- */
1778 (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */
1779 (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */
1780 (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */
1781 (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */
1783 (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */
1784 (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */
1785 (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */
1788 struct iw_handler_def p80211wext_handler_def = {
1789 .num_standard = ARRAY_SIZE(p80211wext_handlers),
1790 .num_private = 0,
1791 .num_private_args = 0,
1792 .standard = p80211wext_handlers,
1793 .private = NULL,
1794 .private_args = NULL,
1795 .get_wireless_stats = p80211wext_get_wireless_stats
1799 int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
1801 union iwreq_data data;
1803 DBFENTER;
1805 /* Send the association state first */
1806 data.ap_addr.sa_family = ARPHRD_ETHER;
1807 if (assoc) {
1808 memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN);
1809 } else {
1810 memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN);
1813 if (wlan_wext_write)
1814 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1816 if (!assoc) goto done;
1818 // XXX send association data, like IEs, etc etc.
1820 done:
1821 DBFEXIT;
1822 return 0;