1 /* src/p80211/p80211wext.c
3 * Glue code to make linux-wlan-ng a happy wireless extension camper.
5 * original author: Reyk Floeter <reyk@synack.de>
6 * Completely re-written by Solomon Peachy <solomon@linux-wlan.com>
8 * Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved.
9 * --------------------------------------------------------------------
13 * The contents of this file are subject to the Mozilla Public
14 * License Version 1.1 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.mozilla.org/MPL/
18 * Software distributed under the License is distributed on an "AS
19 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
20 * implied. See the License for the specific language governing
21 * rights and limitations under the License.
23 * Alternatively, the contents of this file may be used under the
24 * terms of the GNU Public License version 2 (the "GPL"), in which
25 * case the provisions of the GPL are applicable instead of the
26 * above. If you wish to allow the use of your version of this file
27 * only under the terms of the GPL and not to allow others to use
28 * your version of this file under the MPL, indicate your decision
29 * by deleting the provisions above and replace them with the notice
30 * and other provisions required by the GPL. If you do not delete
31 * the provisions above, a recipient may use your version of this
32 * file under either the MPL or the GPL.
34 * --------------------------------------------------------------------
37 /*================================================================*/
41 #include <linux/version.h>
43 #include <linux/kernel.h>
44 #include <linux/sched.h>
45 #include <linux/types.h>
46 #include <linux/slab.h>
47 #include <linux/netdevice.h>
48 #include <linux/etherdevice.h>
49 #include <linux/wireless.h>
51 #include <net/iw_handler.h>
53 #include <linux/if_arp.h>
54 #include <asm/bitops.h>
55 #include <asm/uaccess.h>
56 #include <asm/byteorder.h>
58 /*================================================================*/
59 /* Project Includes */
62 #include "wlan_compat.h"
64 #include "p80211types.h"
65 #include "p80211hdr.h"
66 #include "p80211conv.h"
67 #include "p80211mgmt.h"
68 #include "p80211msg.h"
69 #include "p80211metastruct.h"
70 #include "p80211metadef.h"
71 #include "p80211netdev.h"
72 #include "p80211ioctl.h"
73 #include "p80211req.h"
75 static int p80211wext_giwrate(netdevice_t
*dev
,
76 struct iw_request_info
*info
,
77 struct iw_param
*rrq
, char *extra
);
78 static int p80211wext_giwessid(netdevice_t
*dev
,
79 struct iw_request_info
*info
,
80 struct iw_point
*data
, char *essid
);
81 /* compatibility to wireless extensions */
84 static UINT8
p80211_mhz_to_channel(UINT16 mhz
)
87 return ((mhz
- 5000) / 5);
94 return ((mhz
- 2407) / 5);
100 static UINT16
p80211_channel_to_mhz(UINT8 ch
, int dot11a
)
111 return (5000 + (5 * ch
));
119 if ((ch
< 14) && (ch
> 0)) {
120 return (2407 + (5 * ch
));
126 /* taken from orinoco.c ;-) */
127 static const long p80211wext_channel_freq
[] = {
128 2412, 2417, 2422, 2427, 2432, 2437, 2442,
129 2447, 2452, 2457, 2462, 2467, 2472, 2484
131 #define NUM_CHANNELS (sizeof(p80211wext_channel_freq) / sizeof(p80211wext_channel_freq[0]))
133 /* steal a spare bit to store the shared/opensystems state. should default to open if not set */
134 #define HOSTWEP_SHAREDKEY BIT3
137 /** function declarations =============== */
139 static int qual_as_percent(int snr
) {
150 static int p80211wext_dorequest(wlandevice_t
*wlandev
, UINT32 did
, UINT32 data
)
152 p80211msg_dot11req_mibset_t msg
;
153 p80211item_uint32_t mibitem
;
158 msg
.msgcode
= DIDmsg_dot11req_mibset
;
161 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
162 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
168 static int p80211wext_autojoin(wlandevice_t
*wlandev
)
170 p80211msg_lnxreq_autojoin_t msg
;
171 struct iw_point data
;
172 char ssid
[IW_ESSID_MAX_SIZE
];
180 result
= p80211wext_giwessid(wlandev
->netdev
, NULL
, &data
, ssid
);
187 if ( wlandev
->hostwep
& HOSTWEP_SHAREDKEY
)
188 msg
.authtype
.data
= P80211ENUM_authalg_sharedkey
;
190 msg
.authtype
.data
= P80211ENUM_authalg_opensystem
;
192 msg
.msgcode
= DIDmsg_lnxreq_autojoin
;
194 /* Trim the last '\0' to fit the SSID format */
196 if (data
.length
&& ssid
[data
.length
-1] == '\0') {
197 data
.length
= data
.length
- 1;
200 memcpy(msg
.ssid
.data
.data
, ssid
, data
.length
);
201 msg
.ssid
.data
.len
= data
.length
;
203 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
217 /* called by /proc/net/wireless */
218 struct iw_statistics
* p80211wext_get_wireless_stats (netdevice_t
*dev
)
220 p80211msg_lnxreq_commsquality_t quality
;
221 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
222 struct iw_statistics
* wstats
= &wlandev
->wstats
;
227 if ( (wlandev
== NULL
) || (wlandev
->msdstate
!= WLAN_MSD_RUNNING
) )
230 /* XXX Only valid in station mode */
233 /* build request message */
234 quality
.msgcode
= DIDmsg_lnxreq_commsquality
;
235 quality
.dbm
.data
= P80211ENUM_truth_true
;
236 quality
.dbm
.status
= P80211ENUM_msgitem_status_data_ok
;
238 /* send message to nsd */
239 if ( wlandev
->mlmerequest
== NULL
)
242 retval
= wlandev
->mlmerequest(wlandev
, (p80211msg_t
*) &quality
);
244 wstats
->qual
.qual
= qual_as_percent(quality
.link
.data
); /* overall link quality */
245 wstats
->qual
.level
= quality
.level
.data
; /* instant signal level */
246 wstats
->qual
.noise
= quality
.noise
.data
; /* instant noise level */
248 #if WIRELESS_EXT > 18
249 wstats
->qual
.updated
= IW_QUAL_ALL_UPDATED
| IW_QUAL_DBM
;
251 wstats
->qual
.updated
= 7;
253 wstats
->discard
.code
= wlandev
->rx
.decrypt_err
;
254 wstats
->discard
.nwid
= 0;
255 wstats
->discard
.misc
= 0;
257 #if WIRELESS_EXT > 11
258 wstats
->discard
.fragment
= 0; // incomplete fragments
259 wstats
->discard
.retries
= 0; // tx retries.
260 wstats
->miss
.beacon
= 0;
268 static int p80211wext_giwname(netdevice_t
*dev
,
269 struct iw_request_info
*info
,
270 char *name
, char *extra
)
272 struct iw_param rate
;
278 result
= p80211wext_giwrate(dev
, NULL
, &rate
, NULL
);
285 switch (rate
.value
) {
288 strcpy(name
, "IEEE 802.11-DS");
292 strcpy(name
, "IEEE 802.11-b");
300 static int p80211wext_giwfreq(netdevice_t
*dev
,
301 struct iw_request_info
*info
,
302 struct iw_freq
*freq
, char *extra
)
304 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
305 p80211item_uint32_t mibitem
;
306 p80211msg_dot11req_mibset_t msg
;
312 msg
.msgcode
= DIDmsg_dot11req_mibget
;
313 mibitem
.did
= DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel
;
314 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
315 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
322 memcpy(&mibitem
, &msg
.mibattribute
.data
, sizeof(mibitem
));
324 if (mibitem
.data
> NUM_CHANNELS
) {
329 /* convert into frequency instead of a channel */
331 freq
->m
= p80211_channel_to_mhz(mibitem
.data
, 0) * 100000;
338 static int p80211wext_siwfreq(netdevice_t
*dev
,
339 struct iw_request_info
*info
,
340 struct iw_freq
*freq
, char *extra
)
342 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
343 p80211item_uint32_t mibitem
;
344 p80211msg_dot11req_mibset_t msg
;
350 if (!wlan_wext_write
) {
355 msg
.msgcode
= DIDmsg_dot11req_mibset
;
356 mibitem
.did
= DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel
;
357 mibitem
.status
= P80211ENUM_msgitem_status_data_ok
;
359 if ( (freq
->e
== 0) && (freq
->m
<= 1000) )
360 mibitem
.data
= freq
->m
;
362 mibitem
.data
= p80211_mhz_to_channel(freq
->m
);
364 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
365 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
379 static int p80211wext_giwmode(netdevice_t
*dev
,
380 struct iw_request_info
*info
,
381 __u32
*mode
, char *extra
)
383 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
387 switch (wlandev
->macmode
) {
388 case WLAN_MACMODE_IBSS_STA
:
389 *mode
= IW_MODE_ADHOC
;
391 case WLAN_MACMODE_ESS_STA
:
392 *mode
= IW_MODE_INFRA
;
394 case WLAN_MACMODE_ESS_AP
:
395 *mode
= IW_MODE_MASTER
;
399 *mode
= IW_MODE_AUTO
;
406 static int p80211wext_siwmode(netdevice_t
*dev
,
407 struct iw_request_info
*info
,
408 __u32
*mode
, char *extra
)
410 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
411 p80211item_uint32_t mibitem
;
412 p80211msg_dot11req_mibset_t msg
;
418 if (!wlan_wext_write
) {
423 if (*mode
!= IW_MODE_ADHOC
&& *mode
!= IW_MODE_INFRA
&&
424 *mode
!= IW_MODE_MASTER
) {
429 /* Operation mode is the same with current mode */
430 if (*mode
== wlandev
->macmode
)
435 wlandev
->macmode
= WLAN_MACMODE_IBSS_STA
;
438 wlandev
->macmode
= WLAN_MACMODE_ESS_STA
;
441 wlandev
->macmode
= WLAN_MACMODE_ESS_AP
;
445 WLAN_LOG_INFO("Operation mode: %d not support\n", *mode
);
449 /* Set Operation mode to the PORT TYPE RID */
451 #warning "get rid of p2mib here"
453 msg
.msgcode
= DIDmsg_dot11req_mibset
;
454 mibitem
.did
= DIDmib_p2_p2Static_p2CnfPortType
;
455 mibitem
.data
= (*mode
== IW_MODE_ADHOC
) ? 0 : 1;
456 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
457 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
469 static int p80211wext_giwrange(netdevice_t
*dev
,
470 struct iw_request_info
*info
,
471 struct iw_point
*data
, char *extra
)
473 struct iw_range
*range
= (struct iw_range
*) extra
;
478 // for backward compatability set size & zero everything we don't understand
479 data
->length
= sizeof(*range
);
480 memset(range
,0,sizeof(*range
));
483 range
->txpower_capa
= IW_TXPOW_DBM
;
484 // XXX what about min/max_pmp, min/max_pmt, etc.
487 #if WIRELESS_EXT > 10
488 range
->we_version_compiled
= WIRELESS_EXT
;
489 range
->we_version_source
= 13;
491 range
->retry_capa
= IW_RETRY_LIMIT
;
492 range
->retry_flags
= IW_RETRY_LIMIT
;
493 range
->min_retry
= 0;
494 range
->max_retry
= 255;
495 #endif /* WIRELESS_EXT > 10 */
497 #if WIRELESS_EXT > 16
498 range
->event_capa
[0] = (IW_EVENT_CAPA_K_0
| //mode/freq/ssid
499 IW_EVENT_CAPA_MASK(SIOCGIWAP
) |
500 IW_EVENT_CAPA_MASK(SIOCGIWSCAN
));
501 range
->event_capa
[1] = IW_EVENT_CAPA_K_1
; //encode
502 range
->event_capa
[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL
) |
503 IW_EVENT_CAPA_MASK(IWEVCUSTOM
) );
506 range
->num_channels
= NUM_CHANNELS
;
508 /* XXX need to filter against the regulatory domain &| active set */
510 for (i
= 0; i
< NUM_CHANNELS
; i
++) {
511 range
->freq
[val
].i
= i
+ 1;
512 range
->freq
[val
].m
= p80211wext_channel_freq
[i
] * 100000;
513 range
->freq
[val
].e
= 1;
517 range
->num_frequency
= val
;
519 /* Max of /proc/net/wireless */
520 range
->max_qual
.qual
= 100;
521 range
->max_qual
.level
= 0;
522 range
->max_qual
.noise
= 0;
523 range
->sensitivity
= 3;
524 // XXX these need to be nsd-specific!
527 range
->max_rts
= 2347;
528 range
->min_frag
= 256;
529 range
->max_frag
= 2346;
531 range
->max_encoding_tokens
= NUM_WEPKEYS
;
532 range
->num_encoding_sizes
= 2;
533 range
->encoding_size
[0] = 5;
534 range
->encoding_size
[1] = 13;
536 // XXX what about num_bitrates/throughput?
537 range
->num_bitrates
= 0;
539 /* estimated max throughput */
540 // XXX need to cap it if we're running at ~2Mbps..
541 range
->throughput
= 5500000;
548 static int p80211wext_giwap(netdevice_t
*dev
,
549 struct iw_request_info
*info
,
550 struct sockaddr
*ap_addr
, char *extra
)
553 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
557 memcpy(ap_addr
->sa_data
, wlandev
->bssid
, WLAN_BSSID_LEN
);
558 ap_addr
->sa_family
= ARPHRD_ETHER
;
565 static int p80211wext_giwencode(netdevice_t
*dev
,
566 struct iw_request_info
*info
,
567 struct iw_point
*erq
, char *key
)
569 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
575 if (wlandev
->hostwep
& HOSTWEP_PRIVACYINVOKED
)
576 erq
->flags
= IW_ENCODE_ENABLED
;
578 erq
->flags
= IW_ENCODE_DISABLED
;
580 if (wlandev
->hostwep
& HOSTWEP_EXCLUDEUNENCRYPTED
)
581 erq
->flags
|= IW_ENCODE_RESTRICTED
;
583 erq
->flags
|= IW_ENCODE_OPEN
;
585 i
= (erq
->flags
& IW_ENCODE_INDEX
) - 1;
588 i
= wlandev
->hostwep
& HOSTWEP_DEFAULTKEY_MASK
;
590 if ((i
< 0) || (i
>= NUM_WEPKEYS
)) {
597 /* copy the key from the driver cache as the keys are read-only MIBs */
598 erq
->length
= wlandev
->wep_keylens
[i
];
599 memcpy(key
, wlandev
->wep_keys
[i
], erq
->length
);
606 static int p80211wext_siwencode(netdevice_t
*dev
,
607 struct iw_request_info
*info
,
608 struct iw_point
*erq
, char *key
)
610 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
611 p80211msg_dot11req_mibset_t msg
;
612 p80211item_pstr32_t pstr
;
620 if (!wlan_wext_write
) {
625 /* Check the Key index first. */
626 if((i
= (erq
->flags
& IW_ENCODE_INDEX
))) {
628 if ((i
< 1) || (i
> NUM_WEPKEYS
)) {
635 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID
, i
);
647 // Do not thing when no Key Index
650 /* Check if there is no key information in the iwconfig request */
651 if((erq
->flags
& IW_ENCODE_NOKEY
) == 0 && enable
== 1) {
653 /*------------------------------------------------------------
654 * If there is WEP Key for setting, check the Key Information
655 * and then set it to the firmware.
656 -------------------------------------------------------------*/
658 if (erq
->length
> 0) {
660 /* copy the key from the driver cache as the keys are read-only MIBs */
661 wlandev
->wep_keylens
[i
] = erq
->length
;
662 memcpy(wlandev
->wep_keys
[i
], key
, erq
->length
);
664 /* Prepare data struture for p80211req_dorequest. */
665 memcpy(pstr
.data
.data
, key
, erq
->length
);
666 pstr
.data
.len
= erq
->length
;
671 pstr
.did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0
;
675 pstr
.did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1
;
679 pstr
.did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2
;
683 pstr
.did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3
;
691 msg
.msgcode
= DIDmsg_dot11req_mibset
;
692 memcpy(&msg
.mibattribute
.data
, &pstr
, sizeof(pstr
));
693 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
703 /* Check the PrivacyInvoked flag */
704 if (erq
->flags
& IW_ENCODE_DISABLED
) {
705 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked
, P80211ENUM_truth_false
);
707 else if((erq
->flags
& IW_ENCODE_ENABLED
) || enable
== 1) {
708 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked
, P80211ENUM_truth_true
);
716 /* Check the ExcludeUnencrypted flag */
717 if (erq
->flags
& IW_ENCODE_RESTRICTED
) {
718 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted
, P80211ENUM_truth_true
);
720 else if (erq
->flags
& IW_ENCODE_OPEN
) {
721 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted
, P80211ENUM_truth_false
);
735 static int p80211wext_giwessid(netdevice_t
*dev
,
736 struct iw_request_info
*info
,
737 struct iw_point
*data
, char *essid
)
739 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
743 if (wlandev
->ssid
.len
) {
744 data
->length
= wlandev
->ssid
.len
;
746 memcpy(essid
, wlandev
->ssid
.data
, data
->length
);
747 essid
[data
->length
] = 0;
748 #if (WIRELESS_EXT < 21)
752 memset(essid
, 0, sizeof(wlandev
->ssid
.data
));
761 static int p80211wext_siwessid(netdevice_t
*dev
,
762 struct iw_request_info
*info
,
763 struct iw_point
*data
, char *essid
)
765 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
766 p80211msg_lnxreq_autojoin_t msg
;
770 int length
= data
->length
;
774 if (!wlan_wext_write
) {
780 if ( wlandev
->hostwep
& HOSTWEP_SHAREDKEY
)
781 msg
.authtype
.data
= P80211ENUM_authalg_sharedkey
;
783 msg
.authtype
.data
= P80211ENUM_authalg_opensystem
;
785 msg
.msgcode
= DIDmsg_lnxreq_autojoin
;
787 #if (WIRELESS_EXT < 21)
788 if (length
) length
--;
791 /* Trim the last '\0' to fit the SSID format */
793 if (length
&& essid
[length
-1] == '\0') {
797 memcpy(msg
.ssid
.data
.data
, essid
, length
);
798 msg
.ssid
.data
.len
= length
;
800 WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid
);
801 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
802 WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result
);
815 static int p80211wext_siwcommit(netdevice_t
*dev
,
816 struct iw_request_info
*info
,
817 struct iw_point
*data
, char *essid
)
819 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
824 if (!wlan_wext_write
) {
830 err
= p80211wext_autojoin(wlandev
);
838 static int p80211wext_giwrate(netdevice_t
*dev
,
839 struct iw_request_info
*info
,
840 struct iw_param
*rrq
, char *extra
)
842 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
843 p80211item_uint32_t mibitem
;
844 p80211msg_dot11req_mibset_t msg
;
850 msg
.msgcode
= DIDmsg_dot11req_mibget
;
851 mibitem
.did
= DIDmib_p2_p2MAC_p2CurrentTxRate
;
852 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
853 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
860 memcpy(&mibitem
, &msg
.mibattribute
.data
, sizeof(mibitem
));
862 rrq
->fixed
= 0; /* can it change? */
866 #define HFA384x_RATEBIT_1 ((UINT16)1)
867 #define HFA384x_RATEBIT_2 ((UINT16)2)
868 #define HFA384x_RATEBIT_5dot5 ((UINT16)4)
869 #define HFA384x_RATEBIT_11 ((UINT16)8)
871 switch (mibitem
.data
) {
872 case HFA384x_RATEBIT_1
:
873 rrq
->value
= 1000000;
875 case HFA384x_RATEBIT_2
:
876 rrq
->value
= 2000000;
878 case HFA384x_RATEBIT_5dot5
:
879 rrq
->value
= 5500000;
881 case HFA384x_RATEBIT_11
:
882 rrq
->value
= 11000000;
892 static int p80211wext_giwrts(netdevice_t
*dev
,
893 struct iw_request_info
*info
,
894 struct iw_param
*rts
, char *extra
)
896 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
897 p80211item_uint32_t mibitem
;
898 p80211msg_dot11req_mibset_t msg
;
904 msg
.msgcode
= DIDmsg_dot11req_mibget
;
905 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold
;
906 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
907 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
914 memcpy(&mibitem
, &msg
.mibattribute
.data
, sizeof(mibitem
));
916 rts
->value
= mibitem
.data
;
917 rts
->disabled
= (rts
->value
== 2347);
926 static int p80211wext_siwrts(netdevice_t
*dev
,
927 struct iw_request_info
*info
,
928 struct iw_param
*rts
, char *extra
)
930 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
931 p80211item_uint32_t mibitem
;
932 p80211msg_dot11req_mibset_t msg
;
938 if (!wlan_wext_write
) {
943 msg
.msgcode
= DIDmsg_dot11req_mibget
;
944 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold
;
948 mibitem
.data
= rts
->value
;
950 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
951 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
963 static int p80211wext_giwfrag(netdevice_t
*dev
,
964 struct iw_request_info
*info
,
965 struct iw_param
*frag
, char *extra
)
967 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
968 p80211item_uint32_t mibitem
;
969 p80211msg_dot11req_mibset_t msg
;
975 msg
.msgcode
= DIDmsg_dot11req_mibget
;
976 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold
;
977 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
978 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
985 memcpy(&mibitem
, &msg
.mibattribute
.data
, sizeof(mibitem
));
987 frag
->value
= mibitem
.data
;
988 frag
->disabled
= (frag
->value
== 2346);
996 static int p80211wext_siwfrag(netdevice_t
*dev
,
997 struct iw_request_info
*info
,
998 struct iw_param
*frag
, char *extra
)
1000 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1001 p80211item_uint32_t mibitem
;
1002 p80211msg_dot11req_mibset_t msg
;
1008 if (!wlan_wext_write
) {
1009 err
= (-EOPNOTSUPP
);
1013 msg
.msgcode
= DIDmsg_dot11req_mibset
;
1014 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold
;
1017 mibitem
.data
= 2346;
1019 mibitem
.data
= frag
->value
;
1021 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
1022 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1034 #endif /* WIRELESS_EXT > 8 */
1036 #if WIRELESS_EXT > 10
1038 #ifndef IW_RETRY_LONG
1039 #define IW_RETRY_LONG IW_RETRY_MAX
1042 #ifndef IW_RETRY_SHORT
1043 #define IW_RETRY_SHORT IW_RETRY_MIN
1046 static int p80211wext_giwretry(netdevice_t
*dev
,
1047 struct iw_request_info
*info
,
1048 struct iw_param
*rrq
, char *extra
)
1050 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1051 p80211item_uint32_t mibitem
;
1052 p80211msg_dot11req_mibset_t msg
;
1055 UINT16 shortretry
, longretry
, lifetime
;
1059 msg
.msgcode
= DIDmsg_dot11req_mibget
;
1060 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit
;
1062 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
1063 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1070 memcpy(&mibitem
, &msg
.mibattribute
.data
, sizeof(mibitem
));
1072 shortretry
= mibitem
.data
;
1074 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit
;
1076 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
1077 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1084 memcpy(&mibitem
, &msg
.mibattribute
.data
, sizeof(mibitem
));
1086 longretry
= mibitem
.data
;
1088 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime
;
1090 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
1091 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1098 memcpy(&mibitem
, &msg
.mibattribute
.data
, sizeof(mibitem
));
1100 lifetime
= mibitem
.data
;
1104 if ((rrq
->flags
& IW_RETRY_TYPE
) == IW_RETRY_LIFETIME
) {
1105 rrq
->flags
= IW_RETRY_LIFETIME
;
1106 rrq
->value
= lifetime
* 1024;
1108 if (rrq
->flags
& IW_RETRY_LONG
) {
1109 rrq
->flags
= IW_RETRY_LIMIT
| IW_RETRY_LONG
;
1110 rrq
->value
= longretry
;
1112 rrq
->flags
= IW_RETRY_LIMIT
;
1113 rrq
->value
= shortretry
;
1114 if (shortretry
!= longretry
)
1115 rrq
->flags
|= IW_RETRY_SHORT
;
1125 static int p80211wext_siwretry(netdevice_t
*dev
,
1126 struct iw_request_info
*info
,
1127 struct iw_param
*rrq
, char *extra
)
1129 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1130 p80211item_uint32_t mibitem
;
1131 p80211msg_dot11req_mibset_t msg
;
1137 if (!wlan_wext_write
) {
1138 err
= (-EOPNOTSUPP
);
1142 if (rrq
->disabled
) {
1147 msg
.msgcode
= DIDmsg_dot11req_mibset
;
1149 if ((rrq
->flags
& IW_RETRY_TYPE
) == IW_RETRY_LIFETIME
) {
1150 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime
;
1151 mibitem
.data
= rrq
->value
/= 1024;
1153 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
1154 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1161 if (rrq
->flags
& IW_RETRY_LONG
) {
1162 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit
;
1163 mibitem
.data
= rrq
->value
;
1165 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
1166 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1174 if (rrq
->flags
& IW_RETRY_SHORT
) {
1175 mibitem
.did
= DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit
;
1176 mibitem
.data
= rrq
->value
;
1178 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
1179 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1194 #endif /* WIRELESS_EXT > 10 */
1196 #if WIRELESS_EXT > 9
1197 static int p80211wext_siwtxpow(netdevice_t
*dev
,
1198 struct iw_request_info
*info
,
1199 struct iw_param
*rrq
, char *extra
)
1201 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1202 p80211item_uint32_t mibitem
;
1203 p80211msg_dot11req_mibset_t msg
;
1209 if (!wlan_wext_write
) {
1210 err
= (-EOPNOTSUPP
);
1214 msg
.msgcode
= DIDmsg_dot11req_mibset
;
1216 switch (rrq
->value
) {
1218 case 1 : mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1
; break;
1219 case 2 : mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2
; break;
1220 case 3 : mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3
; break;
1221 case 4 : mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4
; break;
1222 case 5 : mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5
; break;
1223 case 6 : mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6
; break;
1224 case 7 : mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7
; break;
1225 case 8 : mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8
; break;
1226 default: mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8
; break;
1229 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
1230 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1242 static int p80211wext_giwtxpow(netdevice_t
*dev
,
1243 struct iw_request_info
*info
,
1244 struct iw_param
*rrq
, char *extra
)
1246 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1247 p80211item_uint32_t mibitem
;
1248 p80211msg_dot11req_mibset_t msg
;
1254 msg
.msgcode
= DIDmsg_dot11req_mibget
;
1255 mibitem
.did
= DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel
;
1257 memcpy(&msg
.mibattribute
.data
, &mibitem
, sizeof(mibitem
));
1258 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1265 memcpy(&mibitem
, &msg
.mibattribute
.data
, sizeof(mibitem
));
1267 // XXX handle OFF by setting disabled = 1;
1269 rrq
->flags
= 0; // IW_TXPOW_DBM;
1272 rrq
->value
= mibitem
.data
;
1278 #endif /* WIRELESS_EXT > 9 */
1280 static int p80211wext_siwspy(netdevice_t
*dev
,
1281 struct iw_request_info
*info
,
1282 struct iw_point
*srq
, char *extra
)
1284 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1285 struct sockaddr address
[IW_MAX_SPY
];
1286 int number
= srq
->length
;
1291 /* Copy the data from the input buffer */
1292 memcpy(address
, extra
, sizeof(struct sockaddr
)*number
);
1294 wlandev
->spy_number
= 0;
1298 /* extract the addresses */
1299 for (i
= 0; i
< number
; i
++) {
1301 memcpy(wlandev
->spy_address
[i
], address
[i
].sa_data
, ETH_ALEN
);
1305 memset(wlandev
->spy_stat
, 0, sizeof(struct iw_quality
) * IW_MAX_SPY
);
1307 /* set number of addresses */
1308 wlandev
->spy_number
= number
;
1315 /* jkriegl: from orinoco, modified */
1316 static int p80211wext_giwspy(netdevice_t
*dev
,
1317 struct iw_request_info
*info
,
1318 struct iw_point
*srq
, char *extra
)
1320 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1322 struct sockaddr address
[IW_MAX_SPY
];
1323 struct iw_quality spy_stat
[IW_MAX_SPY
];
1329 number
= wlandev
->spy_number
;
1333 /* populate address and spy struct's */
1334 for (i
= 0; i
< number
; i
++) {
1335 memcpy(address
[i
].sa_data
, wlandev
->spy_address
[i
], ETH_ALEN
);
1336 address
[i
].sa_family
= AF_UNIX
;
1337 memcpy(&spy_stat
[i
], &wlandev
->spy_stat
[i
], sizeof(struct iw_quality
));
1340 /* reset update flag */
1341 for (i
=0; i
< number
; i
++)
1342 wlandev
->spy_stat
[i
].updated
= 0;
1345 /* push stuff to user space */
1346 srq
->length
= number
;
1347 memcpy(extra
, address
, sizeof(struct sockaddr
)*number
);
1348 memcpy(extra
+sizeof(struct sockaddr
)*number
, spy_stat
, sizeof(struct iw_quality
)*number
);
1354 static int prism2_result2err (int prism2_result
)
1358 switch (prism2_result
) {
1359 case P80211ENUM_resultcode_invalid_parameters
:
1362 case P80211ENUM_resultcode_implementation_failure
:
1365 case P80211ENUM_resultcode_not_supported
:
1376 #if WIRELESS_EXT > 13
1377 static int p80211wext_siwscan(netdevice_t
*dev
,
1378 struct iw_request_info
*info
,
1379 struct iw_point
*srq
, char *extra
)
1381 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1382 p80211msg_dot11req_scan_t msg
;
1389 if (wlandev
->macmode
== WLAN_MACMODE_ESS_AP
) {
1390 WLAN_LOG_ERROR("Can't scan in AP mode\n");
1391 err
= (-EOPNOTSUPP
);
1395 memset(&msg
, 0x00, sizeof(p80211msg_dot11req_scan_t
));
1396 msg
.msgcode
= DIDmsg_dot11req_scan
;
1397 msg
.bsstype
.data
= P80211ENUM_bsstype_any
;
1399 memset(&(msg
.bssid
.data
), 0xFF, sizeof (p80211item_pstr6_t
));
1400 msg
.bssid
.data
.len
= 6;
1402 msg
.scantype
.data
= P80211ENUM_scantype_active
;
1403 msg
.probedelay
.data
= 0;
1405 for (i
= 1; i
<= 14; i
++)
1406 msg
.channellist
.data
.data
[i
-1] = i
;
1407 msg
.channellist
.data
.len
= 14;
1409 msg
.maxchanneltime
.data
= 250;
1410 msg
.minchanneltime
.data
= 200;
1412 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1414 err
= prism2_result2err (msg
.resultcode
.data
);
1422 /* Helper to translate scan into Wireless Extensions scan results.
1423 * Inspired by the prism54 code, which was in turn inspired by the
1427 wext_translate_bss(struct iw_request_info
*info
, char *current_ev
,
1428 char *end_buf
, p80211msg_dot11req_scan_results_t
*bss
)
1430 struct iw_event iwe
; /* Temporary buffer */
1432 /* The first entry must be the MAC address */
1433 memcpy(iwe
.u
.ap_addr
.sa_data
, bss
->bssid
.data
.data
, WLAN_BSSID_LEN
);
1434 iwe
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
1435 iwe
.cmd
= SIOCGIWAP
;
1436 current_ev
= iwe_stream_add_event(info
, current_ev
, end_buf
, &iwe
, IW_EV_ADDR_LEN
);
1438 /* The following entries will be displayed in the same order we give them */
1441 if (bss
->ssid
.data
.len
> 0) {
1442 char essid
[IW_ESSID_MAX_SIZE
+ 1];
1445 size
= wlan_min(IW_ESSID_MAX_SIZE
, bss
->ssid
.data
.len
);
1446 memset(&essid
, 0, sizeof (essid
));
1447 memcpy(&essid
, bss
->ssid
.data
.data
, size
);
1448 WLAN_LOG_DEBUG(1, " essid size = %d\n", size
);
1449 iwe
.u
.data
.length
= size
;
1450 iwe
.u
.data
.flags
= 1;
1451 iwe
.cmd
= SIOCGIWESSID
;
1452 current_ev
= iwe_stream_add_point(info
, current_ev
, end_buf
, &iwe
, &essid
[0]);
1453 WLAN_LOG_DEBUG(1, " essid size OK.\n");
1456 switch (bss
->bsstype
.data
) {
1457 case P80211ENUM_bsstype_infrastructure
:
1458 iwe
.u
.mode
= IW_MODE_MASTER
;
1461 case P80211ENUM_bsstype_independent
:
1462 iwe
.u
.mode
= IW_MODE_ADHOC
;
1469 iwe
.cmd
= SIOCGIWMODE
;
1471 current_ev
= iwe_stream_add_event(info
, current_ev
, end_buf
, &iwe
, IW_EV_UINT_LEN
);
1473 /* Encryption capability */
1474 if (bss
->privacy
.data
== P80211ENUM_truth_true
)
1475 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
1477 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
1478 iwe
.u
.data
.length
= 0;
1479 iwe
.cmd
= SIOCGIWENCODE
;
1480 current_ev
= iwe_stream_add_point(info
, current_ev
, end_buf
, &iwe
, NULL
);
1482 /* Add frequency. (short) bss->channel is the frequency in MHz */
1483 iwe
.u
.freq
.m
= bss
->dschannel
.data
;
1485 iwe
.cmd
= SIOCGIWFREQ
;
1486 current_ev
= iwe_stream_add_event(info
, current_ev
, end_buf
, &iwe
, IW_EV_FREQ_LEN
);
1488 /* Add quality statistics */
1489 iwe
.u
.qual
.level
= bss
->signal
.data
;
1490 iwe
.u
.qual
.noise
= bss
->noise
.data
;
1491 /* do a simple SNR for quality */
1492 iwe
.u
.qual
.qual
= qual_as_percent(bss
->signal
.data
- bss
->noise
.data
);
1494 current_ev
= iwe_stream_add_event(info
, current_ev
, end_buf
, &iwe
, IW_EV_QUAL_LEN
);
1500 static int p80211wext_giwscan(netdevice_t
*dev
,
1501 struct iw_request_info
*info
,
1502 struct iw_point
*srq
, char *extra
)
1504 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1505 p80211msg_dot11req_scan_results_t msg
;
1510 char *current_ev
= extra
;
1514 /* Since wireless tools doesn't really have a way of passing how
1515 * many scan results results there were back here, keep grabbing them
1519 memset(&msg
, 0, sizeof(msg
));
1520 msg
.msgcode
= DIDmsg_dot11req_scan_results
;
1521 msg
.bssindex
.data
= i
;
1523 result
= p80211req_dorequest(wlandev
, (UINT8
*)&msg
);
1524 if ((result
!= 0) ||
1525 (msg
.resultcode
.data
!= P80211ENUM_resultcode_success
)) {
1529 current_ev
= wext_translate_bss(info
, current_ev
, extra
+ IW_SCAN_MAX_DATA
, &msg
);
1532 } while (i
< IW_MAX_AP
);
1534 srq
->length
= (current_ev
- extra
);
1535 srq
->flags
= 0; /* todo */
1537 if (result
&& !scan_good
)
1538 err
= prism2_result2err (msg
.resultcode
.data
);
1545 /*****************************************************/
1546 //extra wireless extensions stuff to support NetworkManager (I hope)
1548 #if WIRELESS_EXT > 17
1549 /* SIOCSIWENCODEEXT */
1550 static int p80211wext_set_encodeext(struct net_device
*dev
,
1551 struct iw_request_info
*info
,
1552 union iwreq_data
*wrqu
, char *extra
)
1554 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1555 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
1556 p80211msg_dot11req_mibset_t msg
;
1557 p80211item_pstr32_t
*pstr
;
1560 struct iw_point
*encoding
= &wrqu
->encoding
;
1561 int idx
= encoding
->flags
& IW_ENCODE_INDEX
;
1563 WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext
->ext_flags
,(int)ext
->alg
,(int)ext
->key_len
);
1566 if ( ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
1567 // set default key ? I'm not sure if this the the correct thing to do here
1570 if (idx
< 1 || idx
> NUM_WEPKEYS
) {
1575 WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx
);
1576 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID
, idx
);
1582 if ( ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
1583 if ( ! ext
->alg
& IW_ENCODE_ALG_WEP
) {
1584 WLAN_LOG_DEBUG(1,"asked to set a non wep key :(");
1588 if (idx
<1 || idx
> NUM_WEPKEYS
)
1593 WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx
);
1594 wlandev
->wep_keylens
[idx
] = ext
->key_len
;
1595 memcpy(wlandev
->wep_keys
[idx
], ext
->key
, ext
->key_len
);
1597 memset( &msg
,0,sizeof(msg
));
1598 pstr
= (p80211item_pstr32_t
*)&msg
.mibattribute
.data
;
1599 memcpy(pstr
->data
.data
, ext
->key
,ext
->key_len
);
1600 pstr
->data
.len
= ext
->key_len
;
1603 pstr
->did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0
;
1606 pstr
->did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1
;
1609 pstr
->did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2
;
1612 pstr
->did
= DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3
;
1617 msg
.msgcode
= DIDmsg_dot11req_mibset
;
1618 result
= p80211req_dorequest(wlandev
,(UINT8
*)&msg
);
1619 WLAN_LOG_DEBUG(1,"result (%d)\n",result
);
1624 /* SIOCGIWENCODEEXT */
1625 static int p80211wext_get_encodeext(struct net_device
*dev
,
1626 struct iw_request_info
*info
,
1627 union iwreq_data
*wrqu
, char *extra
)
1630 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1631 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
1633 struct iw_point
*encoding
= &wrqu
->encoding
;
1640 WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext
->ext_flags
,(int)ext
->alg
,(int)ext
->key_len
);
1643 max_len
= encoding
->length
- sizeof(*ext
);
1644 if ( max_len
<= 0) {
1645 WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len
);
1649 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
1651 WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx
);
1654 if (idx
< 1 || idx
> NUM_WEPKEYS
) {
1655 WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx
);
1661 /* default key ? not sure what to do */
1662 /* will just use key[0] for now ! FIX ME */
1665 encoding
->flags
= idx
+ 1;
1666 memset(ext
,0,sizeof(*ext
));
1668 ext
->alg
= IW_ENCODE_ALG_WEP
;
1669 ext
->key_len
= wlandev
->wep_keylens
[idx
];
1670 memcpy( ext
->key
, wlandev
->wep_keys
[idx
] , ext
->key_len
);
1672 encoding
->flags
|= IW_ENCODE_ENABLED
;
1681 static int p80211_wext_set_iwauth (struct net_device
*dev
,
1682 struct iw_request_info
*info
,
1683 union iwreq_data
*wrqu
, char *extra
)
1685 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1686 struct iw_param
*param
= &wrqu
->param
;
1689 WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param
->flags
& IW_AUTH_INDEX
);
1691 switch (param
->flags
& IW_AUTH_INDEX
) {
1692 case IW_AUTH_DROP_UNENCRYPTED
:
1693 WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param
->value
);
1695 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted
, P80211ENUM_truth_true
);
1697 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted
, P80211ENUM_truth_false
);
1700 case IW_AUTH_PRIVACY_INVOKED
:
1701 WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param
->value
);
1703 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked
, P80211ENUM_truth_true
);
1705 result
= p80211wext_dorequest(wlandev
, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked
, P80211ENUM_truth_false
);
1709 case IW_AUTH_80211_AUTH_ALG
:
1710 if ( param
->value
& IW_AUTH_ALG_OPEN_SYSTEM
) {
1711 WLAN_LOG_DEBUG(1,"set open_system\n");
1712 wlandev
->hostwep
&= ~HOSTWEP_SHAREDKEY
;
1713 } else if ( param
->value
& IW_AUTH_ALG_SHARED_KEY
) {
1714 WLAN_LOG_DEBUG(1,"set shared key\n");
1715 wlandev
->hostwep
|= HOSTWEP_SHAREDKEY
;
1717 /* don't know what to do know :( */
1718 WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param
->value
);
1733 static int p80211_wext_get_iwauth (struct net_device
*dev
,
1734 struct iw_request_info
*info
,
1735 union iwreq_data
*wrqu
, char *extra
)
1737 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1738 struct iw_param
*param
= &wrqu
->param
;
1741 WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param
->flags
& IW_AUTH_INDEX
);
1743 switch (param
->flags
& IW_AUTH_INDEX
) {
1744 case IW_AUTH_DROP_UNENCRYPTED
:
1745 param
->value
= wlandev
->hostwep
& HOSTWEP_EXCLUDEUNENCRYPTED
?1:0;
1748 case IW_AUTH_PRIVACY_INVOKED
:
1749 param
->value
= wlandev
->hostwep
& HOSTWEP_PRIVACYINVOKED
?1:0;
1752 case IW_AUTH_80211_AUTH_ALG
:
1753 param
->value
= wlandev
->hostwep
& HOSTWEP_SHAREDKEY
?IW_AUTH_ALG_SHARED_KEY
:IW_AUTH_ALG_OPEN_SYSTEM
;
1774 /*****************************************************/
1781 typedef int (*iw_handler)(netdevice_t *dev, struct iw_request_info *info,
1782 union iwreq_data *wrqu, char *extra);
1785 #if WIRELESS_EXT > 12
1786 static iw_handler p80211wext_handlers
[] = {
1787 (iw_handler
) p80211wext_siwcommit
, /* SIOCSIWCOMMIT */
1788 (iw_handler
) p80211wext_giwname
, /* SIOCGIWNAME */
1789 (iw_handler
) NULL
, /* SIOCSIWNWID */
1790 (iw_handler
) NULL
, /* SIOCGIWNWID */
1791 (iw_handler
) p80211wext_siwfreq
, /* SIOCSIWFREQ */
1792 (iw_handler
) p80211wext_giwfreq
, /* SIOCGIWFREQ */
1793 (iw_handler
) p80211wext_siwmode
, /* SIOCSIWMODE */
1794 (iw_handler
) p80211wext_giwmode
, /* SIOCGIWMODE */
1795 (iw_handler
) NULL
, /* SIOCSIWSENS */
1796 (iw_handler
) NULL
, /* SIOCGIWSENS */
1797 (iw_handler
) NULL
, /* not used */ /* SIOCSIWRANGE */
1798 (iw_handler
) p80211wext_giwrange
, /* SIOCGIWRANGE */
1799 (iw_handler
) NULL
, /* not used */ /* SIOCSIWPRIV */
1800 (iw_handler
) NULL
, /* kernel code */ /* SIOCGIWPRIV */
1801 (iw_handler
) NULL
, /* not used */ /* SIOCSIWSTATS */
1802 (iw_handler
) NULL
, /* kernel code */ /* SIOCGIWSTATS */
1803 (iw_handler
) p80211wext_siwspy
, /* SIOCSIWSPY */
1804 (iw_handler
) p80211wext_giwspy
, /* SIOCGIWSPY */
1805 (iw_handler
) NULL
, /* -- hole -- */
1806 (iw_handler
) NULL
, /* -- hole -- */
1807 (iw_handler
) NULL
, /* SIOCSIWAP */
1808 (iw_handler
) p80211wext_giwap
, /* SIOCGIWAP */
1809 (iw_handler
) NULL
, /* -- hole -- */
1810 (iw_handler
) NULL
, /* SIOCGIWAPLIST */
1811 #if WIRELESS_EXT > 13
1812 (iw_handler
) p80211wext_siwscan
, /* SIOCSIWSCAN */
1813 (iw_handler
) p80211wext_giwscan
, /* SIOCGIWSCAN */
1814 #else /* WIRELESS_EXT > 13 */
1815 (iw_handler
) NULL
, /* null */ /* SIOCSIWSCAN */
1816 (iw_handler
) NULL
, /* null */ /* SIOCGIWSCAN */
1817 #endif /* WIRELESS_EXT > 13 */
1818 (iw_handler
) p80211wext_siwessid
, /* SIOCSIWESSID */
1819 (iw_handler
) p80211wext_giwessid
, /* SIOCGIWESSID */
1820 (iw_handler
) NULL
, /* SIOCSIWNICKN */
1821 (iw_handler
) p80211wext_giwessid
, /* SIOCGIWNICKN */
1822 (iw_handler
) NULL
, /* -- hole -- */
1823 (iw_handler
) NULL
, /* -- hole -- */
1824 (iw_handler
) NULL
, /* SIOCSIWRATE */
1825 (iw_handler
) p80211wext_giwrate
, /* SIOCGIWRATE */
1826 (iw_handler
) p80211wext_siwrts
, /* SIOCSIWRTS */
1827 (iw_handler
) p80211wext_giwrts
, /* SIOCGIWRTS */
1828 (iw_handler
) p80211wext_siwfrag
, /* SIOCSIWFRAG */
1829 (iw_handler
) p80211wext_giwfrag
, /* SIOCGIWFRAG */
1830 (iw_handler
) p80211wext_siwtxpow
, /* SIOCSIWTXPOW */
1831 (iw_handler
) p80211wext_giwtxpow
, /* SIOCGIWTXPOW */
1832 (iw_handler
) p80211wext_siwretry
, /* SIOCSIWRETRY */
1833 (iw_handler
) p80211wext_giwretry
, /* SIOCGIWRETRY */
1834 (iw_handler
) p80211wext_siwencode
, /* SIOCSIWENCODE */
1835 (iw_handler
) p80211wext_giwencode
, /* SIOCGIWENCODE */
1836 (iw_handler
) NULL
, /* SIOCSIWPOWER */
1837 (iw_handler
) NULL
, /* SIOCGIWPOWER */
1838 #if WIRELESS_EXT > 17
1839 /* WPA operations */
1841 (iw_handler
) NULL
, /* -- hole -- */
1842 (iw_handler
) NULL
, /* -- hole -- */
1843 (iw_handler
) NULL
, /* SIOCSIWGENIE set generic IE */
1844 (iw_handler
) NULL
, /* SIOCGIWGENIE get generic IE */
1845 (iw_handler
) p80211_wext_set_iwauth
, /* SIOCSIWAUTH set authentication mode params */
1846 (iw_handler
) p80211_wext_get_iwauth
, /* SIOCGIWAUTH get authentication mode params */
1848 (iw_handler
) p80211wext_set_encodeext
, /* SIOCSIWENCODEEXT set encoding token & mode */
1849 (iw_handler
) p80211wext_get_encodeext
, /* SIOCGIWENCODEEXT get encoding token & mode */
1850 (iw_handler
) NULL
, /* SIOCSIWPMKSA PMKSA cache operation */
1854 struct iw_handler_def p80211wext_handler_def
= {
1855 .num_standard
= sizeof(p80211wext_handlers
) / sizeof(iw_handler
),
1857 .num_private_args
= 0,
1858 .standard
= p80211wext_handlers
,
1860 .private_args
= NULL
,
1861 #if WIRELESS_EXT > 16
1862 .get_wireless_stats
= p80211wext_get_wireless_stats
1868 /* wireless extensions' ioctls */
1869 int p80211wext_support_ioctl(netdevice_t
*dev
, struct ifreq
*ifr
, int cmd
)
1871 wlandevice_t
*wlandev
= (wlandevice_t
*)dev
->priv
;
1873 #if WIRELESS_EXT < 13
1874 struct iwreq
*iwr
= (struct iwreq
*)ifr
;
1877 p80211item_uint32_t mibitem
;
1882 mibitem
.status
= P80211ENUM_msgitem_status_data_ok
;
1884 if ( wlandev
->msdstate
!= WLAN_MSD_RUNNING
) {
1889 WLAN_LOG_DEBUG(1, "Received wireless extension ioctl #%d.\n", cmd
);
1892 #if WIRELESS_EXT < 13
1893 case SIOCSIWNAME
: /* unused */
1894 err
= (-EOPNOTSUPP
);
1896 case SIOCGIWNAME
: /* get name == wireless protocol */
1897 err
= p80211wext_giwname(dev
, NULL
, (char *) &iwr
->u
, NULL
);
1901 err
= (-EOPNOTSUPP
);
1903 case SIOCSIWFREQ
: /* set channel */
1904 err
= p80211wext_siwfreq(dev
, NULL
, &(iwr
->u
.freq
), NULL
);
1906 case SIOCGIWFREQ
: /* get channel */
1907 err
= p80211wext_giwfreq(dev
, NULL
, &(iwr
->u
.freq
), NULL
);
1911 case SIOCSIWAP
: /* set access point MAC addresses (BSSID) */
1912 err
= (-EOPNOTSUPP
);
1915 case SIOCGIWAP
: /* get access point MAC addresses (BSSID) */
1916 err
= p80211wext_giwap(dev
, NULL
, &(iwr
->u
.ap_addr
), NULL
);
1919 #if WIRELESS_EXT > 8
1920 case SIOCSIWMODE
: /* set operation mode */
1921 case SIOCSIWESSID
: /* set SSID (network name) */
1922 case SIOCSIWRATE
: /* set default bit rate (bps) */
1923 err
= (-EOPNOTSUPP
);
1926 case SIOCGIWMODE
: /* get operation mode */
1927 err
= p80211wext_giwmode(dev
, NULL
, &iwr
->u
.mode
, NULL
);
1930 case SIOCGIWNICKN
: /* get node name/nickname */
1931 case SIOCGIWESSID
: /* get SSID */
1932 if(iwr
->u
.essid
.pointer
) {
1933 char ssid
[IW_ESSID_MAX_SIZE
+1];
1934 memset(ssid
, 0, sizeof(ssid
));
1936 err
= p80211wext_giwessid(dev
, NULL
, &iwr
->u
.essid
, ssid
);
1937 if(copy_to_user(iwr
->u
.essid
.pointer
, ssid
, sizeof(ssid
)))
1942 err
= p80211wext_giwrate(dev
, NULL
, &iwr
->u
.bitrate
, NULL
);
1945 err
= p80211wext_giwrts(dev
, NULL
, &iwr
->u
.rts
, NULL
);
1948 err
= p80211wext_giwfrag(dev
, NULL
, &iwr
->u
.rts
, NULL
);
1951 if (!capable(CAP_NET_ADMIN
))
1953 else if (iwr
->u
.encoding
.pointer
) {
1954 char keybuf
[MAX_KEYLEN
];
1955 err
= p80211wext_giwencode(dev
, NULL
,
1956 &iwr
->u
.encoding
, keybuf
);
1957 if (copy_to_user(iwr
->u
.encoding
.pointer
, keybuf
,
1958 iwr
->u
.encoding
.length
))
1967 case SIOCSIWNICKN
: /* set node name/nickname */
1968 case SIOCSIWENCODE
: /* set encoding token & mode */
1974 err
= (-EOPNOTSUPP
);
1977 if(iwr
->u
.data
.pointer
!= NULL
) {
1978 struct iw_range range
;
1979 err
= p80211wext_giwrange(dev
, NULL
, &iwr
->u
.data
,
1981 /* Push that up to the caller */
1982 if (copy_to_user(iwr
->u
.data
.pointer
, &range
, sizeof(range
)))
1986 #endif /* WIRELESS_EXT > 8 */
1987 #if WIRELESS_EXT > 9
1989 err
= (-EOPNOTSUPP
);
1992 err
= p80211wext_giwtxpow(dev
, NULL
, &iwr
->u
.txpower
, NULL
);
1994 #endif /* WIRELESS_EXT > 9 */
1995 #if WIRELESS_EXT > 10
1997 err
= (-EOPNOTSUPP
);
2000 err
= p80211wext_giwretry(dev
, NULL
, &iwr
->u
.retry
, NULL
);
2002 #endif /* WIRELESS_EXT > 10 */
2004 #endif /* WIRELESS_EXT <= 12 */
2007 err
= (-EOPNOTSUPP
);
2016 int p80211wext_event_associated(wlandevice_t
*wlandev
, int assoc
)
2018 union iwreq_data data
;
2022 #if WIRELESS_EXT > 13
2023 /* Send the association state first */
2024 data
.ap_addr
.sa_family
= ARPHRD_ETHER
;
2026 memcpy(data
.ap_addr
.sa_data
, wlandev
->bssid
, WLAN_ADDR_LEN
);
2028 memset(data
.ap_addr
.sa_data
, 0, WLAN_ADDR_LEN
);
2031 if (wlan_wext_write
)
2032 wireless_send_event(wlandev
->netdev
, SIOCGIWAP
, &data
, NULL
);
2034 if (!assoc
) goto done
;
2036 // XXX send association data, like IEs, etc etc.
2044 #endif /* compatibility to wireless extensions */