Staging: wlan-ng: refactor p80211wext.c to reduce text size.
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / wlan-ng / p80211wext.c
blob387194d4a6ebce102b30e76a4cb9f996ddf650c0
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 */
40 #include <linux/kernel.h>
41 #include <linux/sched.h>
42 #include <linux/types.h>
43 #include <linux/netdevice.h>
44 #include <linux/etherdevice.h>
45 #include <linux/wireless.h>
46 #include <net/iw_handler.h>
47 #include <linux/if_arp.h>
48 #include <linux/bitops.h>
49 #include <linux/uaccess.h>
50 #include <asm/byteorder.h>
51 #include <linux/if_ether.h>
53 #include "p80211types.h"
54 #include "p80211hdr.h"
55 #include "p80211conv.h"
56 #include "p80211mgmt.h"
57 #include "p80211msg.h"
58 #include "p80211metastruct.h"
59 #include "p80211metadef.h"
60 #include "p80211netdev.h"
61 #include "p80211ioctl.h"
62 #include "p80211req.h"
64 static int p80211wext_giwrate(netdevice_t *dev,
65 struct iw_request_info *info,
66 struct iw_param *rrq, char *extra);
67 static int p80211wext_giwessid(netdevice_t *dev,
68 struct iw_request_info *info,
69 struct iw_point *data, char *essid);
71 static u8 p80211_mhz_to_channel(u16 mhz)
73 if (mhz >= 5000)
74 return (mhz - 5000) / 5;
76 if (mhz == 2484)
77 return 14;
79 if (mhz >= 2407)
80 return (mhz - 2407) / 5;
82 return 0;
85 static u16 p80211_channel_to_mhz(u8 ch, int dot11a)
88 if (ch == 0)
89 return 0;
90 if (ch > 200)
91 return 0;
93 /* 5G */
94 if (dot11a)
95 return 5000 + (5 * ch);
97 /* 2.4G */
98 if (ch == 14)
99 return 2484;
101 if ((ch < 14) && (ch > 0))
102 return 2407 + (5 * ch);
104 return 0;
107 /* taken from orinoco.c ;-) */
108 static const long p80211wext_channel_freq[] = {
109 2412, 2417, 2422, 2427, 2432, 2437, 2442,
110 2447, 2452, 2457, 2462, 2467, 2472, 2484
113 #define NUM_CHANNELS ARRAY_SIZE(p80211wext_channel_freq)
115 /* steal a spare bit to store the shared/opensystems state.
116 should default to open if not set */
117 #define HOSTWEP_SHAREDKEY BIT(3)
119 static int qual_as_percent(int snr)
121 if (snr <= 0)
122 return 0;
123 if (snr <= 40)
124 return snr * 5 / 2;
125 return 100;
128 static int p80211wext_setmib(wlandevice_t *wlandev, u32 did, u32 data)
130 p80211msg_dot11req_mibset_t msg;
131 p80211item_uint32_t *mibitem =
132 (p80211item_uint32_t *)&msg.mibattribute.data;
133 int result;
135 msg.msgcode = DIDmsg_dot11req_mibset;
136 memset(mibitem, 0, sizeof(*mibitem));
137 mibitem->did = did;
138 mibitem->data = data;
139 result = p80211req_dorequest(wlandev, (u8 *) &msg);
141 return result;
145 * get a 32 bit mib value
147 static int p80211wext_getmib(wlandevice_t *wlandev, u32 did, u32 *data)
149 p80211msg_dot11req_mibset_t msg;
150 p80211item_uint32_t *mibitem =
151 (p80211item_uint32_t *)&msg.mibattribute.data;
152 int result;
154 msg.msgcode = DIDmsg_dot11req_mibget;
155 memset(mibitem, 0, sizeof(*mibitem));
156 mibitem->did = did;
157 result = p80211req_dorequest(wlandev, (u8 *) &msg);
158 if (!result)
159 *data = mibitem->data;
161 return result;
164 static int p80211wext_autojoin(wlandevice_t *wlandev)
166 p80211msg_lnxreq_autojoin_t msg;
167 struct iw_point data;
168 char ssid[IW_ESSID_MAX_SIZE];
170 int result;
171 int err = 0;
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;
193 memcpy(msg.ssid.data.data, ssid, data.length);
194 msg.ssid.data.len = data.length;
196 result = p80211req_dorequest(wlandev, (u8 *) &msg);
198 if (result) {
199 err = -EFAULT;
200 goto exit;
203 exit:
205 return err;
209 /* called by /proc/net/wireless */
210 struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t *dev)
212 p80211msg_lnxreq_commsquality_t quality;
213 wlandevice_t *wlandev = dev->ml_priv;
214 struct iw_statistics *wstats = &wlandev->wstats;
215 int retval;
217 /* Check */
218 if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING))
219 return NULL;
221 /* XXX Only valid in station mode */
222 wstats->status = 0;
224 /* build request message */
225 quality.msgcode = DIDmsg_lnxreq_commsquality;
226 quality.dbm.data = P80211ENUM_truth_true;
227 quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
229 /* send message to nsd */
230 if (wlandev->mlmerequest == NULL)
231 return NULL;
233 retval = wlandev->mlmerequest(wlandev, (p80211msg_t *) &quality);
235 wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
236 wstats->qual.level = quality.level.data; /* instant signal level */
237 wstats->qual.noise = quality.noise.data; /* instant noise level */
239 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
240 wstats->discard.code = wlandev->rx.decrypt_err;
241 wstats->discard.nwid = 0;
242 wstats->discard.misc = 0;
244 wstats->discard.fragment = 0; /* incomplete fragments */
245 wstats->discard.retries = 0; /* tx retries. */
246 wstats->miss.beacon = 0;
248 return wstats;
251 static int p80211wext_giwname(netdevice_t *dev,
252 struct iw_request_info *info,
253 char *name, char *extra)
255 struct iw_param rate;
256 int result;
257 int err = 0;
259 result = p80211wext_giwrate(dev, NULL, &rate, NULL);
261 if (result) {
262 err = -EFAULT;
263 goto exit;
266 switch (rate.value) {
267 case 1000000:
268 case 2000000:
269 strcpy(name, "IEEE 802.11-DS");
270 break;
271 case 5500000:
272 case 11000000:
273 strcpy(name, "IEEE 802.11-b");
274 break;
276 exit:
277 return err;
280 static int p80211wext_giwfreq(netdevice_t *dev,
281 struct iw_request_info *info,
282 struct iw_freq *freq, char *extra)
284 wlandevice_t *wlandev = dev->ml_priv;
285 int result;
286 int err = 0;
287 unsigned int value;
289 result = p80211wext_getmib(wlandev,
290 DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
291 &value);
292 if (result) {
293 err = -EFAULT;
294 goto exit;
297 if (value > NUM_CHANNELS) {
298 err = -EFAULT;
299 goto exit;
302 /* convert into frequency instead of a channel */
303 freq->e = 1;
304 freq->m = p80211_channel_to_mhz(value, 0) * 100000;
306 exit:
307 return err;
310 static int p80211wext_siwfreq(netdevice_t *dev,
311 struct iw_request_info *info,
312 struct iw_freq *freq, char *extra)
314 wlandevice_t *wlandev = dev->ml_priv;
315 int result;
316 int err = 0;
317 unsigned int value;
319 if (!wlan_wext_write) {
320 err = -EOPNOTSUPP;
321 goto exit;
324 if ((freq->e == 0) && (freq->m <= 1000))
325 value = freq->m;
326 else
327 value = p80211_mhz_to_channel(freq->m);
329 result = p80211wext_setmib(wlandev,
330 DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel,
331 value);
333 if (result) {
334 err = -EFAULT;
335 goto exit;
338 exit:
339 return err;
342 static int p80211wext_giwmode(netdevice_t *dev,
343 struct iw_request_info *info,
344 __u32 *mode, char *extra)
346 wlandevice_t *wlandev = dev->ml_priv;
348 switch (wlandev->macmode) {
349 case WLAN_MACMODE_IBSS_STA:
350 *mode = IW_MODE_ADHOC;
351 break;
352 case WLAN_MACMODE_ESS_STA:
353 *mode = IW_MODE_INFRA;
354 break;
355 case WLAN_MACMODE_ESS_AP:
356 *mode = IW_MODE_MASTER;
357 break;
358 default:
359 /* Not set yet. */
360 *mode = IW_MODE_AUTO;
363 return 0;
366 static int p80211wext_siwmode(netdevice_t *dev,
367 struct iw_request_info *info,
368 __u32 *mode, char *extra)
370 wlandevice_t *wlandev = dev->ml_priv;
371 int result;
372 int err = 0;
374 if (!wlan_wext_write) {
375 err = -EOPNOTSUPP;
376 goto exit;
379 if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
380 *mode != IW_MODE_MASTER) {
381 err = (-EOPNOTSUPP);
382 goto exit;
385 /* Operation mode is the same with current mode */
386 if (*mode == wlandev->macmode)
387 goto exit;
389 switch (*mode) {
390 case IW_MODE_ADHOC:
391 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
392 break;
393 case IW_MODE_INFRA:
394 wlandev->macmode = WLAN_MACMODE_ESS_STA;
395 break;
396 case IW_MODE_MASTER:
397 wlandev->macmode = WLAN_MACMODE_ESS_AP;
398 break;
399 default:
400 /* Not set yet. */
401 printk(KERN_INFO "Operation mode: %d not support\n", *mode);
402 return -EOPNOTSUPP;
405 /* Set Operation mode to the PORT TYPE RID */
406 result = p80211wext_setmib(wlandev,
407 DIDmib_p2_p2Static_p2CnfPortType,
408 (*mode == IW_MODE_ADHOC) ? 0 : 1);
409 if (result)
410 err = -EFAULT;
411 exit:
412 return err;
415 static int p80211wext_giwrange(netdevice_t *dev,
416 struct iw_request_info *info,
417 struct iw_point *data, char *extra)
419 struct iw_range *range = (struct iw_range *)extra;
420 int i, val;
422 /* for backward compatability set size and zero everything we don't understand */
423 data->length = sizeof(*range);
424 memset(range, 0, sizeof(*range));
426 range->txpower_capa = IW_TXPOW_DBM;
427 /* XXX what about min/max_pmp, min/max_pmt, etc. */
429 range->we_version_compiled = WIRELESS_EXT;
430 range->we_version_source = 13;
432 range->retry_capa = IW_RETRY_LIMIT;
433 range->retry_flags = IW_RETRY_LIMIT;
434 range->min_retry = 0;
435 range->max_retry = 255;
437 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | /* mode/freq/ssid */
438 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
439 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
440 range->event_capa[1] = IW_EVENT_CAPA_K_1; /* encode */
441 range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
442 IW_EVENT_CAPA_MASK(IWEVCUSTOM));
444 range->num_channels = NUM_CHANNELS;
446 /* XXX need to filter against the regulatory domain &| active set */
447 val = 0;
448 for (i = 0; i < NUM_CHANNELS; i++) {
449 range->freq[val].i = i + 1;
450 range->freq[val].m = p80211wext_channel_freq[i] * 100000;
451 range->freq[val].e = 1;
452 val++;
455 range->num_frequency = val;
457 /* Max of /proc/net/wireless */
458 range->max_qual.qual = 100;
459 range->max_qual.level = 0;
460 range->max_qual.noise = 0;
461 range->sensitivity = 3;
462 /* XXX these need to be nsd-specific! */
464 range->min_rts = 0;
465 range->max_rts = 2347;
466 range->min_frag = 256;
467 range->max_frag = 2346;
469 range->max_encoding_tokens = NUM_WEPKEYS;
470 range->num_encoding_sizes = 2;
471 range->encoding_size[0] = 5;
472 range->encoding_size[1] = 13;
474 /* XXX what about num_bitrates/throughput? */
475 range->num_bitrates = 0;
477 /* estimated max throughput */
478 /* XXX need to cap it if we're running at ~2Mbps.. */
479 range->throughput = 5500000;
481 return 0;
484 static int p80211wext_giwap(netdevice_t *dev,
485 struct iw_request_info *info,
486 struct sockaddr *ap_addr, char *extra)
489 wlandevice_t *wlandev = dev->ml_priv;
491 memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
492 ap_addr->sa_family = ARPHRD_ETHER;
494 return 0;
497 static int p80211wext_giwencode(netdevice_t *dev,
498 struct iw_request_info *info,
499 struct iw_point *erq, char *key)
501 wlandevice_t *wlandev = dev->ml_priv;
502 int err = 0;
503 int i;
505 i = (erq->flags & IW_ENCODE_INDEX) - 1;
506 erq->flags = 0;
508 if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
509 erq->flags |= IW_ENCODE_ENABLED;
510 else
511 erq->flags |= IW_ENCODE_DISABLED;
513 if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
514 erq->flags |= IW_ENCODE_RESTRICTED;
515 else
516 erq->flags |= IW_ENCODE_OPEN;
518 i = (erq->flags & IW_ENCODE_INDEX) - 1;
520 if (i == -1)
521 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
523 if ((i < 0) || (i >= NUM_WEPKEYS)) {
524 err = -EINVAL;
525 goto exit;
528 erq->flags |= i + 1;
530 /* copy the key from the driver cache as the keys are read-only MIBs */
531 erq->length = wlandev->wep_keylens[i];
532 memcpy(key, wlandev->wep_keys[i], erq->length);
534 exit:
535 return err;
538 static int p80211wext_siwencode(netdevice_t *dev,
539 struct iw_request_info *info,
540 struct iw_point *erq, char *key)
542 wlandevice_t *wlandev = dev->ml_priv;
543 p80211msg_dot11req_mibset_t msg;
544 p80211item_pstr32_t pstr;
546 int err = 0;
547 int result = 0;
548 int i;
550 if (!wlan_wext_write) {
551 err = (-EOPNOTSUPP);
552 goto exit;
555 /* Check the Key index first. */
556 i = (erq->flags & IW_ENCODE_INDEX);
557 if (i) {
558 if ((i < 1) || (i > NUM_WEPKEYS)) {
559 err = -EINVAL;
560 goto exit;
561 } else {
562 i--;
564 /* Set current key number only if no keys are given */
565 if (erq->flags & IW_ENCODE_NOKEY) {
566 result =
567 p80211wext_setmib(wlandev,
568 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
571 if (result) {
572 err = -EFAULT;
573 goto exit;
577 } else {
578 /* Use defaultkey if no Key Index */
579 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
582 /* Check if there is no key information in the iwconfig request */
583 if ((erq->flags & IW_ENCODE_NOKEY) == 0) {
585 /*------------------------------------------------------------
586 * If there is WEP Key for setting, check the Key Information
587 * and then set it to the firmware.
588 -------------------------------------------------------------*/
590 if (erq->length > 0) {
591 /* copy the key from the driver cache as the keys are read-only MIBs */
592 wlandev->wep_keylens[i] = erq->length;
593 memcpy(wlandev->wep_keys[i], key, erq->length);
595 /* Prepare data struture for p80211req_dorequest. */
596 memcpy(pstr.data.data, key, erq->length);
597 pstr.data.len = erq->length;
599 switch (i) {
600 case 0:
601 pstr.did =
602 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
603 break;
605 case 1:
606 pstr.did =
607 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
608 break;
610 case 2:
611 pstr.did =
612 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
613 break;
615 case 3:
616 pstr.did =
617 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
618 break;
620 default:
621 err = -EINVAL;
622 goto exit;
625 msg.msgcode = DIDmsg_dot11req_mibset;
626 memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
627 result = p80211req_dorequest(wlandev, (u8 *) &msg);
629 if (result) {
630 err = -EFAULT;
631 goto exit;
637 /* Check the PrivacyInvoked flag */
638 if (erq->flags & IW_ENCODE_DISABLED) {
639 result =
640 p80211wext_setmib(wlandev,
641 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
642 P80211ENUM_truth_false);
643 } else {
644 result =
645 p80211wext_setmib(wlandev,
646 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
647 P80211ENUM_truth_true);
650 if (result) {
651 err = -EFAULT;
652 goto exit;
655 /* The security mode may be open or restricted, and its meaning
656 depends on the card used. With most cards, in open mode no
657 authentication is used and the card may also accept non-
658 encrypted sessions, whereas in restricted mode only encrypted
659 sessions are accepted and the card will use authentication if
660 available.
662 if (erq->flags & IW_ENCODE_RESTRICTED) {
663 result =
664 p80211wext_setmib(wlandev,
665 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
666 P80211ENUM_truth_true);
667 } else if (erq->flags & IW_ENCODE_OPEN) {
668 result =
669 p80211wext_setmib(wlandev,
670 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
671 P80211ENUM_truth_false);
674 if (result) {
675 err = -EFAULT;
676 goto exit;
679 exit:
681 return err;
684 static int p80211wext_giwessid(netdevice_t *dev,
685 struct iw_request_info *info,
686 struct iw_point *data, char *essid)
688 wlandevice_t *wlandev = dev->ml_priv;
690 if (wlandev->ssid.len) {
691 data->length = wlandev->ssid.len;
692 data->flags = 1;
693 memcpy(essid, wlandev->ssid.data, data->length);
694 essid[data->length] = 0;
695 } else {
696 memset(essid, 0, sizeof(wlandev->ssid.data));
697 data->length = 0;
698 data->flags = 0;
701 return 0;
704 static int p80211wext_siwessid(netdevice_t *dev,
705 struct iw_request_info *info,
706 struct iw_point *data, char *essid)
708 wlandevice_t *wlandev = dev->ml_priv;
709 p80211msg_lnxreq_autojoin_t msg;
711 int result;
712 int err = 0;
713 int length = data->length;
715 if (!wlan_wext_write) {
716 err = (-EOPNOTSUPP);
717 goto exit;
720 if (wlandev->hostwep & HOSTWEP_SHAREDKEY)
721 msg.authtype.data = P80211ENUM_authalg_sharedkey;
722 else
723 msg.authtype.data = P80211ENUM_authalg_opensystem;
725 msg.msgcode = DIDmsg_lnxreq_autojoin;
727 /* Trim the last '\0' to fit the SSID format */
728 if (length && essid[length - 1] == '\0')
729 length--;
731 memcpy(msg.ssid.data.data, essid, length);
732 msg.ssid.data.len = length;
734 pr_debug("autojoin_ssid for %s \n", essid);
735 result = p80211req_dorequest(wlandev, (u8 *) &msg);
736 pr_debug("autojoin_ssid %d\n", result);
738 if (result) {
739 err = -EFAULT;
740 goto exit;
743 exit:
744 return err;
747 static int p80211wext_siwcommit(netdevice_t *dev,
748 struct iw_request_info *info,
749 struct iw_point *data, char *essid)
751 wlandevice_t *wlandev = dev->ml_priv;
752 int err = 0;
754 if (!wlan_wext_write) {
755 err = (-EOPNOTSUPP);
756 goto exit;
759 /* Auto Join */
760 err = p80211wext_autojoin(wlandev);
762 exit:
763 return err;
766 static int p80211wext_giwrate(netdevice_t *dev,
767 struct iw_request_info *info,
768 struct iw_param *rrq, char *extra)
770 wlandevice_t *wlandev = dev->ml_priv;
771 int result;
772 int err = 0;
773 unsigned int value;
775 result = p80211wext_getmib(wlandev, DIDmib_p2_p2MAC_p2CurrentTxRate, &value);
776 if (result) {
777 err = -EFAULT;
778 goto exit;
781 rrq->fixed = 0; /* can it change? */
782 rrq->disabled = 0;
783 rrq->value = 0;
785 #define HFA384x_RATEBIT_1 ((u16)1)
786 #define HFA384x_RATEBIT_2 ((u16)2)
787 #define HFA384x_RATEBIT_5dot5 ((u16)4)
788 #define HFA384x_RATEBIT_11 ((u16)8)
790 switch (value) {
791 case HFA384x_RATEBIT_1:
792 rrq->value = 1000000;
793 break;
794 case HFA384x_RATEBIT_2:
795 rrq->value = 2000000;
796 break;
797 case HFA384x_RATEBIT_5dot5:
798 rrq->value = 5500000;
799 break;
800 case HFA384x_RATEBIT_11:
801 rrq->value = 11000000;
802 break;
803 default:
804 err = -EINVAL;
806 exit:
807 return err;
810 static int p80211wext_giwrts(netdevice_t *dev,
811 struct iw_request_info *info,
812 struct iw_param *rts, char *extra)
814 wlandevice_t *wlandev = dev->ml_priv;
815 int result;
816 int err = 0;
817 unsigned int value;
819 result = p80211wext_getmib(wlandev,
820 DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold,
821 &value);
822 if (result) {
823 err = -EFAULT;
824 goto exit;
827 rts->value = value;
828 rts->disabled = (rts->value == 2347);
829 rts->fixed = 1;
831 exit:
832 return err;
835 static int p80211wext_siwrts(netdevice_t *dev,
836 struct iw_request_info *info,
837 struct iw_param *rts, char *extra)
839 wlandevice_t *wlandev = dev->ml_priv;
840 int result;
841 int err = 0;
842 unsigned int value;
844 if (!wlan_wext_write) {
845 err = -EOPNOTSUPP;
846 goto exit;
849 if (rts->disabled)
850 value = 2347;
851 else
852 value = rts->value;
854 result = p80211wext_setmib(wlandev,
855 DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold,
856 value);
857 if (result) {
858 err = -EFAULT;
859 goto exit;
862 exit:
863 return err;
866 static int p80211wext_giwfrag(netdevice_t *dev,
867 struct iw_request_info *info,
868 struct iw_param *frag, char *extra)
870 wlandevice_t *wlandev = dev->ml_priv;
871 int result;
872 int err = 0;
873 unsigned int value;
875 result = p80211wext_getmib(wlandev,
876 DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold,
877 &value);
878 if (result) {
879 err = -EFAULT;
880 goto exit;
883 frag->value = value;
884 frag->disabled = (frag->value == 2346);
885 frag->fixed = 1;
887 exit:
888 return err;
891 static int p80211wext_siwfrag(netdevice_t *dev,
892 struct iw_request_info *info,
893 struct iw_param *frag, char *extra)
895 wlandevice_t *wlandev = dev->ml_priv;
896 int result;
897 int err = 0;
898 int value;
900 if (!wlan_wext_write) {
901 err = (-EOPNOTSUPP);
902 goto exit;
905 if (frag->disabled)
906 value = 2346;
907 else
908 value = frag->value;
910 result = p80211wext_setmib(wlandev,
911 DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold,
912 value);
914 if (result) {
915 err = -EFAULT;
916 goto exit;
919 exit:
920 return err;
923 #ifndef IW_RETRY_LONG
924 #define IW_RETRY_LONG IW_RETRY_MAX
925 #endif
927 #ifndef IW_RETRY_SHORT
928 #define IW_RETRY_SHORT IW_RETRY_MIN
929 #endif
931 static int p80211wext_giwretry(netdevice_t *dev,
932 struct iw_request_info *info,
933 struct iw_param *rrq, char *extra)
935 wlandevice_t *wlandev = dev->ml_priv;
936 int result;
937 int err = 0;
938 u16 shortretry, longretry, lifetime;
939 unsigned int value;
941 result = p80211wext_getmib(wlandev,
942 DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit,
943 &value);
944 if (result) {
945 err = -EFAULT;
946 goto exit;
949 shortretry = value;
951 result = p80211wext_getmib(wlandev,
952 DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit,
953 &value);
954 if (result) {
955 err = -EFAULT;
956 goto exit;
959 longretry = value;
961 result = p80211wext_getmib(wlandev,
962 DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime,
963 &value);
964 if (result) {
965 err = -EFAULT;
966 goto exit;
969 lifetime = value;
971 rrq->disabled = 0;
973 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
974 rrq->flags = IW_RETRY_LIFETIME;
975 rrq->value = lifetime * 1024;
976 } else {
977 if (rrq->flags & IW_RETRY_LONG) {
978 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
979 rrq->value = longretry;
980 } else {
981 rrq->flags = IW_RETRY_LIMIT;
982 rrq->value = shortretry;
983 if (shortretry != longretry)
984 rrq->flags |= IW_RETRY_SHORT;
988 exit:
989 return err;
993 static int p80211wext_siwretry(netdevice_t *dev,
994 struct iw_request_info *info,
995 struct iw_param *rrq, char *extra)
997 wlandevice_t *wlandev = dev->ml_priv;
998 p80211item_uint32_t mibitem;
999 p80211msg_dot11req_mibset_t msg;
1000 int result;
1001 int err = 0;
1002 unsigned int value;
1004 if (!wlan_wext_write) {
1005 err = (-EOPNOTSUPP);
1006 goto exit;
1009 if (rrq->disabled) {
1010 err = -EINVAL;
1011 goto exit;
1014 msg.msgcode = DIDmsg_dot11req_mibset;
1016 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1018 value = rrq->value /= 1024;
1019 result = p80211wext_setmib(wlandev,
1020 DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime,
1021 value);
1022 if (result) {
1023 err = -EFAULT;
1024 goto exit;
1026 } else {
1027 if (rrq->flags & IW_RETRY_LONG) {
1028 result = p80211wext_setmib(wlandev,
1029 DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit,
1030 rrq->value);
1032 if (result) {
1033 err = -EFAULT;
1034 goto exit;
1038 if (rrq->flags & IW_RETRY_SHORT) {
1039 result = p80211wext_setmib(wlandev,
1040 DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit,
1041 rrq->value);
1043 if (result) {
1044 err = -EFAULT;
1045 goto exit;
1050 exit:
1051 return err;
1055 static int p80211wext_siwtxpow(netdevice_t *dev,
1056 struct iw_request_info *info,
1057 struct iw_param *rrq, char *extra)
1059 wlandevice_t *wlandev = dev->ml_priv;
1060 p80211item_uint32_t mibitem;
1061 p80211msg_dot11req_mibset_t msg;
1062 int result;
1063 int err = 0;
1064 unsigned int value;
1066 if (!wlan_wext_write) {
1067 err = (-EOPNOTSUPP);
1068 goto exit;
1071 if (rrq->fixed == 0)
1072 value = 30;
1073 else
1074 value = rrq->value;
1075 result = p80211wext_setmib(wlandev,
1076 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel,
1077 value);
1079 if (result) {
1080 err = -EFAULT;
1081 goto exit;
1084 exit:
1085 return err;
1088 static int p80211wext_giwtxpow(netdevice_t *dev,
1089 struct iw_request_info *info,
1090 struct iw_param *rrq, char *extra)
1092 wlandevice_t *wlandev = dev->ml_priv;
1093 int result;
1094 int err = 0;
1095 unsigned int value;
1097 result = p80211wext_getmib(wlandev,
1098 DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel,
1099 &value);
1101 if (result) {
1102 err = -EFAULT;
1103 goto exit;
1106 /* XXX handle OFF by setting disabled = 1; */
1108 rrq->flags = 0; /* IW_TXPOW_DBM; */
1109 rrq->disabled = 0;
1110 rrq->fixed = 0;
1111 rrq->value = value;
1113 exit:
1114 return err;
1117 static int p80211wext_siwspy(netdevice_t *dev,
1118 struct iw_request_info *info,
1119 struct iw_point *srq, char *extra)
1121 wlandevice_t *wlandev = dev->ml_priv;
1122 struct sockaddr address[IW_MAX_SPY];
1123 int number = srq->length;
1124 int i;
1126 /* Copy the data from the input buffer */
1127 memcpy(address, extra, sizeof(struct sockaddr) * number);
1129 wlandev->spy_number = 0;
1131 if (number > 0) {
1133 /* extract the addresses */
1134 for (i = 0; i < number; i++) {
1136 memcpy(wlandev->spy_address[i], address[i].sa_data,
1137 ETH_ALEN);
1140 /* reset stats */
1141 memset(wlandev->spy_stat, 0,
1142 sizeof(struct iw_quality) * IW_MAX_SPY);
1144 /* set number of addresses */
1145 wlandev->spy_number = number;
1148 return 0;
1151 /* jkriegl: from orinoco, modified */
1152 static int p80211wext_giwspy(netdevice_t *dev,
1153 struct iw_request_info *info,
1154 struct iw_point *srq, char *extra)
1156 wlandevice_t *wlandev = dev->ml_priv;
1158 struct sockaddr address[IW_MAX_SPY];
1159 struct iw_quality spy_stat[IW_MAX_SPY];
1160 int number;
1161 int i;
1163 number = wlandev->spy_number;
1165 if (number > 0) {
1167 /* populate address and spy struct's */
1168 for (i = 0; i < number; i++) {
1169 memcpy(address[i].sa_data, wlandev->spy_address[i],
1170 ETH_ALEN);
1171 address[i].sa_family = AF_UNIX;
1172 memcpy(&spy_stat[i], &wlandev->spy_stat[i],
1173 sizeof(struct iw_quality));
1176 /* reset update flag */
1177 for (i = 0; i < number; i++)
1178 wlandev->spy_stat[i].updated = 0;
1181 /* push stuff to user space */
1182 srq->length = number;
1183 memcpy(extra, address, sizeof(struct sockaddr) * number);
1184 memcpy(extra + sizeof(struct sockaddr) * number, spy_stat,
1185 sizeof(struct iw_quality) * number);
1187 return 0;
1190 static int prism2_result2err(int prism2_result)
1192 int err = 0;
1194 switch (prism2_result) {
1195 case P80211ENUM_resultcode_invalid_parameters:
1196 err = -EINVAL;
1197 break;
1198 case P80211ENUM_resultcode_implementation_failure:
1199 err = -EIO;
1200 break;
1201 case P80211ENUM_resultcode_not_supported:
1202 err = -EOPNOTSUPP;
1203 break;
1204 default:
1205 err = 0;
1206 break;
1209 return err;
1212 static int p80211wext_siwscan(netdevice_t *dev,
1213 struct iw_request_info *info,
1214 struct iw_point *srq, char *extra)
1216 wlandevice_t *wlandev = dev->ml_priv;
1217 p80211msg_dot11req_scan_t msg;
1218 int result;
1219 int err = 0;
1220 int i = 0;
1222 if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1223 printk(KERN_ERR "Can't scan in AP mode\n");
1224 err = (-EOPNOTSUPP);
1225 goto exit;
1228 memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1229 msg.msgcode = DIDmsg_dot11req_scan;
1230 msg.bsstype.data = P80211ENUM_bsstype_any;
1232 memset(&(msg.bssid.data), 0xFF, sizeof(p80211item_pstr6_t));
1233 msg.bssid.data.len = 6;
1235 msg.scantype.data = P80211ENUM_scantype_active;
1236 msg.probedelay.data = 0;
1238 for (i = 1; i <= 14; i++)
1239 msg.channellist.data.data[i - 1] = i;
1240 msg.channellist.data.len = 14;
1242 msg.maxchanneltime.data = 250;
1243 msg.minchanneltime.data = 200;
1245 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1246 if (result)
1247 err = prism2_result2err(msg.resultcode.data);
1249 exit:
1250 return err;
1253 /* Helper to translate scan into Wireless Extensions scan results.
1254 * Inspired by the prism54 code, which was in turn inspired by the
1255 * airo driver code.
1257 static char *wext_translate_bss(struct iw_request_info *info, char *current_ev,
1258 char *end_buf,
1259 p80211msg_dot11req_scan_results_t *bss)
1261 struct iw_event iwe; /* Temporary buffer */
1263 /* The first entry must be the MAC address */
1264 memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1265 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1266 iwe.cmd = SIOCGIWAP;
1267 current_ev =
1268 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1269 IW_EV_ADDR_LEN);
1271 /* The following entries will be displayed in the same order we give them */
1273 /* The ESSID. */
1274 if (bss->ssid.data.len > 0) {
1275 char essid[IW_ESSID_MAX_SIZE + 1];
1276 int size;
1278 size =
1279 min_t(unsigned short, IW_ESSID_MAX_SIZE,
1280 bss->ssid.data.len);
1281 memset(&essid, 0, sizeof(essid));
1282 memcpy(&essid, bss->ssid.data.data, size);
1283 pr_debug(" essid size = %d\n", size);
1284 iwe.u.data.length = size;
1285 iwe.u.data.flags = 1;
1286 iwe.cmd = SIOCGIWESSID;
1287 current_ev =
1288 iwe_stream_add_point(info, current_ev, end_buf, &iwe,
1289 &essid[0]);
1290 pr_debug(" essid size OK.\n");
1293 switch (bss->bsstype.data) {
1294 case P80211ENUM_bsstype_infrastructure:
1295 iwe.u.mode = IW_MODE_MASTER;
1296 break;
1298 case P80211ENUM_bsstype_independent:
1299 iwe.u.mode = IW_MODE_ADHOC;
1300 break;
1302 default:
1303 iwe.u.mode = 0;
1304 break;
1306 iwe.cmd = SIOCGIWMODE;
1307 if (iwe.u.mode)
1308 current_ev =
1309 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1310 IW_EV_UINT_LEN);
1312 /* Encryption capability */
1313 if (bss->privacy.data == P80211ENUM_truth_true)
1314 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1315 else
1316 iwe.u.data.flags = IW_ENCODE_DISABLED;
1317 iwe.u.data.length = 0;
1318 iwe.cmd = SIOCGIWENCODE;
1319 current_ev =
1320 iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1322 /* Add frequency. (short) bss->channel is the frequency in MHz */
1323 iwe.u.freq.m = bss->dschannel.data;
1324 iwe.u.freq.e = 0;
1325 iwe.cmd = SIOCGIWFREQ;
1326 current_ev =
1327 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1328 IW_EV_FREQ_LEN);
1330 /* Add quality statistics */
1331 iwe.u.qual.level = bss->signal.data;
1332 iwe.u.qual.noise = bss->noise.data;
1333 /* do a simple SNR for quality */
1334 iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1335 iwe.cmd = IWEVQUAL;
1336 current_ev =
1337 iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1338 IW_EV_QUAL_LEN);
1340 return current_ev;
1343 static int p80211wext_giwscan(netdevice_t *dev,
1344 struct iw_request_info *info,
1345 struct iw_point *srq, char *extra)
1347 wlandevice_t *wlandev = dev->ml_priv;
1348 p80211msg_dot11req_scan_results_t msg;
1349 int result = 0;
1350 int err = 0;
1351 int i = 0;
1352 int scan_good = 0;
1353 char *current_ev = extra;
1355 /* Since wireless tools doesn't really have a way of passing how
1356 * many scan results results there were back here, keep grabbing them
1357 * until we fail.
1359 do {
1360 memset(&msg, 0, sizeof(msg));
1361 msg.msgcode = DIDmsg_dot11req_scan_results;
1362 msg.bssindex.data = i;
1364 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1365 if ((result != 0) ||
1366 (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1367 break;
1370 current_ev =
1371 wext_translate_bss(info, current_ev,
1372 extra + IW_SCAN_MAX_DATA, &msg);
1373 scan_good = 1;
1374 i++;
1375 } while (i < IW_MAX_AP);
1377 srq->length = (current_ev - extra);
1378 srq->flags = 0; /* todo */
1380 if (result && !scan_good)
1381 err = prism2_result2err(msg.resultcode.data);
1383 return err;
1386 /* extra wireless extensions stuff to support NetworkManager (I hope) */
1388 /* SIOCSIWENCODEEXT */
1389 static int p80211wext_set_encodeext(struct net_device *dev,
1390 struct iw_request_info *info,
1391 union iwreq_data *wrqu, char *extra)
1393 wlandevice_t *wlandev = dev->ml_priv;
1394 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1395 p80211msg_dot11req_mibset_t msg;
1396 p80211item_pstr32_t *pstr;
1398 int result = 0;
1399 struct iw_point *encoding = &wrqu->encoding;
1400 int idx = encoding->flags & IW_ENCODE_INDEX;
1402 pr_debug("set_encode_ext flags[%d] alg[%d] keylen[%d]\n",
1403 ext->ext_flags, (int)ext->alg, (int)ext->key_len);
1405 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1406 /* set default key ? I'm not sure if this the the correct thing to do here */
1408 if (idx) {
1409 if (idx < 1 || idx > NUM_WEPKEYS)
1410 return -EINVAL;
1411 else
1412 idx--;
1414 pr_debug("setting default key (%d)\n", idx);
1415 result =
1416 p80211wext_setmib(wlandev,
1417 DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
1418 idx);
1419 if (result)
1420 return -EFAULT;
1423 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1424 if (ext->alg != IW_ENCODE_ALG_WEP) {
1425 pr_debug("asked to set a non wep key :(\n");
1426 return -EINVAL;
1428 if (idx) {
1429 if (idx < 1 || idx > NUM_WEPKEYS)
1430 return -EINVAL;
1431 else
1432 idx--;
1434 pr_debug("Set WEP key (%d)\n", idx);
1435 wlandev->wep_keylens[idx] = ext->key_len;
1436 memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1438 memset(&msg, 0, sizeof(msg));
1439 pstr = (p80211item_pstr32_t *) &msg.mibattribute.data;
1440 memcpy(pstr->data.data, ext->key, ext->key_len);
1441 pstr->data.len = ext->key_len;
1442 switch (idx) {
1443 case 0:
1444 pstr->did =
1445 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1446 break;
1447 case 1:
1448 pstr->did =
1449 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1450 break;
1451 case 2:
1452 pstr->did =
1453 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1454 break;
1455 case 3:
1456 pstr->did =
1457 DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1458 break;
1459 default:
1460 break;
1462 msg.msgcode = DIDmsg_dot11req_mibset;
1463 result = p80211req_dorequest(wlandev, (u8 *) &msg);
1464 pr_debug("result (%d)\n", result);
1466 return result;
1469 /* SIOCGIWENCODEEXT */
1470 static int p80211wext_get_encodeext(struct net_device *dev,
1471 struct iw_request_info *info,
1472 union iwreq_data *wrqu, char *extra)
1474 wlandevice_t *wlandev = dev->ml_priv;
1475 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1477 struct iw_point *encoding = &wrqu->encoding;
1478 int result = 0;
1479 int max_len;
1480 int idx;
1482 pr_debug("get_encode_ext flags[%d] alg[%d] keylen[%d]\n",
1483 ext->ext_flags, (int)ext->alg, (int)ext->key_len);
1485 max_len = encoding->length - sizeof(*ext);
1486 if (max_len <= 0) {
1487 pr_debug("get_encodeext max_len [%d] invalid\n", max_len);
1488 result = -EINVAL;
1489 goto exit;
1491 idx = encoding->flags & IW_ENCODE_INDEX;
1493 pr_debug("get_encode_ext index [%d]\n", idx);
1495 if (idx) {
1496 if (idx < 1 || idx > NUM_WEPKEYS) {
1497 pr_debug("get_encode_ext invalid key index [%d]\n",
1498 idx);
1499 result = -EINVAL;
1500 goto exit;
1502 idx--;
1503 } else {
1504 /* default key ? not sure what to do */
1505 /* will just use key[0] for now ! FIX ME */
1508 encoding->flags = idx + 1;
1509 memset(ext, 0, sizeof(*ext));
1511 ext->alg = IW_ENCODE_ALG_WEP;
1512 ext->key_len = wlandev->wep_keylens[idx];
1513 memcpy(ext->key, wlandev->wep_keys[idx], ext->key_len);
1515 encoding->flags |= IW_ENCODE_ENABLED;
1516 exit:
1517 return result;
1520 /* SIOCSIWAUTH */
1521 static int p80211_wext_set_iwauth(struct net_device *dev,
1522 struct iw_request_info *info,
1523 union iwreq_data *wrqu, char *extra)
1525 wlandevice_t *wlandev = dev->ml_priv;
1526 struct iw_param *param = &wrqu->param;
1527 int result = 0;
1529 pr_debug("set_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX);
1531 switch (param->flags & IW_AUTH_INDEX) {
1532 case IW_AUTH_DROP_UNENCRYPTED:
1533 pr_debug("drop_unencrypted %d\n", param->value);
1534 if (param->value)
1535 result =
1536 p80211wext_setmib(wlandev,
1537 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
1538 P80211ENUM_truth_true);
1539 else
1540 result =
1541 p80211wext_setmib(wlandev,
1542 DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted,
1543 P80211ENUM_truth_false);
1544 break;
1546 case IW_AUTH_PRIVACY_INVOKED:
1547 pr_debug("privacy invoked %d\n", param->value);
1548 if (param->value)
1549 result =
1550 p80211wext_setmib(wlandev,
1551 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
1552 P80211ENUM_truth_true);
1553 else
1554 result =
1555 p80211wext_setmib(wlandev,
1556 DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
1557 P80211ENUM_truth_false);
1559 break;
1561 case IW_AUTH_80211_AUTH_ALG:
1562 if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1563 pr_debug("set open_system\n");
1564 wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1565 } else if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1566 pr_debug("set shared key\n");
1567 wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1568 } else {
1569 /* don't know what to do know */
1570 pr_debug("unknown AUTH_ALG (%d)\n", param->value);
1571 result = -EINVAL;
1573 break;
1575 default:
1576 break;
1579 return result;
1582 /* SIOCSIWAUTH */
1583 static int p80211_wext_get_iwauth(struct net_device *dev,
1584 struct iw_request_info *info,
1585 union iwreq_data *wrqu, char *extra)
1587 wlandevice_t *wlandev = dev->ml_priv;
1588 struct iw_param *param = &wrqu->param;
1589 int result = 0;
1591 pr_debug("get_iwauth flags[%d]\n", (int)param->flags & IW_AUTH_INDEX);
1593 switch (param->flags & IW_AUTH_INDEX) {
1594 case IW_AUTH_DROP_UNENCRYPTED:
1595 param->value =
1596 wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED ? 1 : 0;
1597 break;
1599 case IW_AUTH_PRIVACY_INVOKED:
1600 param->value =
1601 wlandev->hostwep & HOSTWEP_PRIVACYINVOKED ? 1 : 0;
1602 break;
1604 case IW_AUTH_80211_AUTH_ALG:
1605 param->value =
1606 wlandev->hostwep & HOSTWEP_SHAREDKEY ?
1607 IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM;
1608 break;
1610 default:
1611 break;
1614 return result;
1617 #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
1619 static iw_handler p80211wext_handlers[] = {
1620 IW_IOCTL(SIOCSIWCOMMIT) = (iw_handler) p80211wext_siwcommit,
1621 IW_IOCTL(SIOCGIWNAME) = (iw_handler) p80211wext_giwname,
1622 /* SIOCSIWNWID,SIOCGIWNWID */
1623 IW_IOCTL(SIOCSIWFREQ) = (iw_handler) p80211wext_siwfreq,
1624 IW_IOCTL(SIOCGIWFREQ) = (iw_handler) p80211wext_giwfreq,
1625 IW_IOCTL(SIOCSIWMODE) = (iw_handler) p80211wext_siwmode,
1626 IW_IOCTL(SIOCGIWMODE) = (iw_handler) p80211wext_giwmode,
1627 /* SIOCSIWSENS,SIOCGIWSENS,SIOCSIWRANGE */
1628 IW_IOCTL(SIOCGIWRANGE) = (iw_handler) p80211wext_giwrange,
1629 /* SIOCSIWPRIV,SIOCGIWPRIV,SIOCSIWSTATS,SIOCGIWSTATS */
1630 IW_IOCTL(SIOCSIWSPY) = (iw_handler) p80211wext_siwspy,
1631 IW_IOCTL(SIOCGIWSPY) = (iw_handler) p80211wext_giwspy,
1632 /* SIOCSIWAP */
1633 IW_IOCTL(SIOCGIWAP) = (iw_handler) p80211wext_giwap,
1634 /* SIOCGIWAPLIST */
1635 IW_IOCTL(SIOCSIWSCAN) = (iw_handler) p80211wext_siwscan,
1636 IW_IOCTL(SIOCGIWSCAN) = (iw_handler) p80211wext_giwscan,
1637 IW_IOCTL(SIOCSIWESSID) = (iw_handler) p80211wext_siwessid,
1638 IW_IOCTL(SIOCGIWESSID) = (iw_handler) p80211wext_giwessid,
1639 /* SIOCSIWNICKN */
1640 IW_IOCTL(SIOCGIWNICKN) = (iw_handler) p80211wext_giwessid,
1641 /* SIOCSIWRATE */
1642 IW_IOCTL(SIOCGIWRATE) = (iw_handler) p80211wext_giwrate,
1643 IW_IOCTL(SIOCSIWRTS) = (iw_handler) p80211wext_siwrts,
1644 IW_IOCTL(SIOCGIWRTS) = (iw_handler) p80211wext_giwrts,
1645 IW_IOCTL(SIOCSIWFRAG) = (iw_handler) p80211wext_siwfrag,
1646 IW_IOCTL(SIOCGIWFRAG) = (iw_handler) p80211wext_giwfrag,
1647 IW_IOCTL(SIOCSIWTXPOW) = (iw_handler) p80211wext_siwtxpow,
1648 IW_IOCTL(SIOCGIWTXPOW) = (iw_handler) p80211wext_giwtxpow,
1649 IW_IOCTL(SIOCSIWRETRY) = (iw_handler) p80211wext_siwretry,
1650 IW_IOCTL(SIOCGIWRETRY) = (iw_handler) p80211wext_giwretry,
1651 IW_IOCTL(SIOCSIWENCODE) = (iw_handler) p80211wext_siwencode,
1652 IW_IOCTL(SIOCGIWENCODE) = (iw_handler) p80211wext_giwencode,
1653 /* SIOCSIWPOWER,SIOCGIWPOWER */
1654 /* WPA operations */
1655 /* SIOCSIWGENIE,SIOCGIWGENIE generic IE */
1656 IW_IOCTL(SIOCSIWAUTH) = (iw_handler) p80211_wext_set_iwauth, /*set authentication mode params */
1657 IW_IOCTL(SIOCGIWAUTH) = (iw_handler) p80211_wext_get_iwauth, /*get authentication mode params */
1658 IW_IOCTL(SIOCSIWENCODEEXT) = (iw_handler) p80211wext_set_encodeext, /*set encoding token & mode */
1659 IW_IOCTL(SIOCGIWENCODEEXT) = (iw_handler) p80211wext_get_encodeext, /*get encoding token & mode */
1660 /* SIOCSIWPMKSA PMKSA cache operation */
1663 struct iw_handler_def p80211wext_handler_def = {
1664 .num_standard = ARRAY_SIZE(p80211wext_handlers),
1665 .standard = p80211wext_handlers,
1666 .get_wireless_stats = p80211wext_get_wireless_stats
1669 int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
1671 union iwreq_data data;
1673 /* Send the association state first */
1674 data.ap_addr.sa_family = ARPHRD_ETHER;
1675 if (assoc)
1676 memcpy(data.ap_addr.sa_data, wlandev->bssid, ETH_ALEN);
1677 else
1678 memset(data.ap_addr.sa_data, 0, ETH_ALEN);
1680 if (wlan_wext_write)
1681 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
1683 if (!assoc)
1684 goto done;
1686 /* XXX send association data, like IEs, etc etc. */
1688 done:
1689 return 0;