1 /******************************************************************************
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 The full GNU General Public License is included in this distribution in the
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
31 ******************************************************************************/
32 #include <linux/wireless.h>
33 #include <linux/kmod.h>
34 #include <linux/module.h>
41 static struct modes_unit rtllib_modes
[] = {
50 #define MAX_CUSTOM_LEN 64
51 static inline char *rtl819x_translate_scan(struct rtllib_device
*ieee
,
52 char *start
, char *stop
,
53 struct rtllib_network
*network
,
54 struct iw_request_info
*info
)
56 char custom
[MAX_CUSTOM_LEN
];
57 char proto_name
[IFNAMSIZ
];
58 char *pname
= proto_name
;
63 static u8 EWC11NHTCap
[] = {0x00, 0x90, 0x4c, 0x33};
65 /* First entry *MUST* be the AP MAC address */
67 iwe
.u
.ap_addr
.sa_family
= ARPHRD_ETHER
;
68 memcpy(iwe
.u
.ap_addr
.sa_data
, network
->bssid
, ETH_ALEN
);
69 start
= iwe_stream_add_event_rsl(info
, start
, stop
,
70 &iwe
, IW_EV_ADDR_LEN
);
71 /* Remaining entries will be displayed in the order we provide them */
74 iwe
.cmd
= SIOCGIWESSID
;
76 if (network
->ssid_len
> 0) {
77 iwe
.u
.data
.length
= min(network
->ssid_len
, (u8
)32);
78 start
= iwe_stream_add_point_rsl(info
, start
, stop
, &iwe
,
80 } else if (network
->hidden_ssid_len
== 0) {
81 iwe
.u
.data
.length
= sizeof("<hidden>");
82 start
= iwe_stream_add_point_rsl(info
, start
, stop
,
85 iwe
.u
.data
.length
= min(network
->hidden_ssid_len
, (u8
)32);
86 start
= iwe_stream_add_point_rsl(info
, start
, stop
, &iwe
,
87 network
->hidden_ssid
);
89 /* Add the protocol name */
90 iwe
.cmd
= SIOCGIWNAME
;
91 for (i
= 0; i
< ARRAY_SIZE(rtllib_modes
); i
++) {
92 if (network
->mode
&(1<<i
)) {
93 sprintf(pname
, rtllib_modes
[i
].mode_string
,
94 rtllib_modes
[i
].mode_size
);
95 pname
+= rtllib_modes
[i
].mode_size
;
99 snprintf(iwe
.u
.name
, IFNAMSIZ
, "IEEE802.11%s", proto_name
);
100 start
= iwe_stream_add_event_rsl(info
, start
, stop
,
101 &iwe
, IW_EV_CHAR_LEN
);
103 iwe
.cmd
= SIOCGIWMODE
;
104 if (network
->capability
&
105 (WLAN_CAPABILITY_ESS
| WLAN_CAPABILITY_IBSS
)) {
106 if (network
->capability
& WLAN_CAPABILITY_ESS
)
107 iwe
.u
.mode
= IW_MODE_MASTER
;
109 iwe
.u
.mode
= IW_MODE_ADHOC
;
110 start
= iwe_stream_add_event_rsl(info
, start
, stop
,
111 &iwe
, IW_EV_UINT_LEN
);
114 /* Add frequency/channel */
115 iwe
.cmd
= SIOCGIWFREQ
;
116 /* iwe.u.freq.m = rtllib_frequency(network->channel, network->mode);
118 iwe
.u
.freq
.m
= network
->channel
;
121 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
,
124 /* Add encryption capability */
125 iwe
.cmd
= SIOCGIWENCODE
;
126 if (network
->capability
& WLAN_CAPABILITY_PRIVACY
)
127 iwe
.u
.data
.flags
= IW_ENCODE_ENABLED
| IW_ENCODE_NOKEY
;
129 iwe
.u
.data
.flags
= IW_ENCODE_DISABLED
;
130 iwe
.u
.data
.length
= 0;
131 start
= iwe_stream_add_point_rsl(info
, start
, stop
,
132 &iwe
, network
->ssid
);
133 /* Add basic and extended rates */
136 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
), " Rates (Mb/s): ");
137 for (i
= 0, j
= 0; i
< network
->rates_len
;) {
138 if (j
< network
->rates_ex_len
&&
139 ((network
->rates_ex
[j
] & 0x7F) <
140 (network
->rates
[i
] & 0x7F)))
141 rate
= network
->rates_ex
[j
++] & 0x7F;
143 rate
= network
->rates
[i
++] & 0x7F;
146 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
147 "%d%s ", rate
>> 1, (rate
& 1) ? ".5" : "");
149 for (; j
< network
->rates_ex_len
; j
++) {
150 rate
= network
->rates_ex
[j
] & 0x7F;
151 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
152 "%d%s ", rate
>> 1, (rate
& 1) ? ".5" : "");
157 if (network
->mode
>= IEEE_N_24G
) {
158 struct ht_capab_ele
*ht_cap
= NULL
;
159 bool is40M
= false, isShortGI
= false;
162 if (!memcmp(network
->bssht
.bdHTCapBuf
, EWC11NHTCap
, 4))
163 ht_cap
= (struct ht_capab_ele
*)
164 &network
->bssht
.bdHTCapBuf
[4];
166 ht_cap
= (struct ht_capab_ele
*)
167 &network
->bssht
.bdHTCapBuf
[0];
168 is40M
= (ht_cap
->ChlWidth
) ? 1 : 0;
169 isShortGI
= (ht_cap
->ChlWidth
) ?
170 ((ht_cap
->ShortGI40Mhz
) ? 1 : 0) :
171 ((ht_cap
->ShortGI20Mhz
) ? 1 : 0);
173 max_mcs
= HTGetHighestMCSRate(ieee
, ht_cap
->MCS
,
175 rate
= MCS_DATA_RATE
[is40M
][isShortGI
][max_mcs
& 0x7f];
179 iwe
.cmd
= SIOCGIWRATE
;
180 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
181 iwe
.u
.bitrate
.value
= max_rate
* 500000;
182 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
,
184 iwe
.cmd
= IWEVCUSTOM
;
185 iwe
.u
.data
.length
= p
- custom
;
186 if (iwe
.u
.data
.length
)
187 start
= iwe_stream_add_point_rsl(info
, start
, stop
,
189 /* Add quality statistics */
190 /* TODO: Fix these values... */
192 iwe
.u
.qual
.qual
= network
->stats
.signal
;
193 iwe
.u
.qual
.level
= network
->stats
.rssi
;
194 iwe
.u
.qual
.noise
= network
->stats
.noise
;
195 iwe
.u
.qual
.updated
= network
->stats
.mask
& RTLLIB_STATMASK_WEMASK
;
196 if (!(network
->stats
.mask
& RTLLIB_STATMASK_RSSI
))
197 iwe
.u
.qual
.updated
|= IW_QUAL_LEVEL_INVALID
;
198 if (!(network
->stats
.mask
& RTLLIB_STATMASK_NOISE
))
199 iwe
.u
.qual
.updated
|= IW_QUAL_NOISE_INVALID
;
200 if (!(network
->stats
.mask
& RTLLIB_STATMASK_SIGNAL
))
201 iwe
.u
.qual
.updated
|= IW_QUAL_QUAL_INVALID
;
202 iwe
.u
.qual
.updated
= 7;
203 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
,
206 iwe
.cmd
= IWEVCUSTOM
;
208 iwe
.u
.data
.length
= p
- custom
;
209 if (iwe
.u
.data
.length
)
210 start
= iwe_stream_add_point_rsl(info
, start
, stop
,
213 memset(&iwe
, 0, sizeof(iwe
));
214 if (network
->wpa_ie_len
) {
215 char buf
[MAX_WPA_IE_LEN
];
217 memcpy(buf
, network
->wpa_ie
, network
->wpa_ie_len
);
219 iwe
.u
.data
.length
= network
->wpa_ie_len
;
220 start
= iwe_stream_add_point_rsl(info
, start
, stop
, &iwe
, buf
);
222 memset(&iwe
, 0, sizeof(iwe
));
223 if (network
->rsn_ie_len
) {
224 char buf
[MAX_WPA_IE_LEN
];
226 memcpy(buf
, network
->rsn_ie
, network
->rsn_ie_len
);
228 iwe
.u
.data
.length
= network
->rsn_ie_len
;
229 start
= iwe_stream_add_point_rsl(info
, start
, stop
, &iwe
, buf
);
232 /* add info for WZC */
233 memset(&iwe
, 0, sizeof(iwe
));
234 if (network
->wzc_ie_len
) {
235 char buf
[MAX_WZC_IE_LEN
];
237 memcpy(buf
, network
->wzc_ie
, network
->wzc_ie_len
);
239 iwe
.u
.data
.length
= network
->wzc_ie_len
;
240 start
= iwe_stream_add_point_rsl(info
, start
, stop
, &iwe
, buf
);
243 /* Add EXTRA: Age to display seconds since last beacon/probe response
244 * for given network. */
245 iwe
.cmd
= IWEVCUSTOM
;
247 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
248 " Last beacon: %lums ago",
249 (jiffies
- network
->last_scanned
) / (HZ
/ 100));
250 iwe
.u
.data
.length
= p
- custom
;
251 if (iwe
.u
.data
.length
)
252 start
= iwe_stream_add_point_rsl(info
, start
, stop
,
258 int rtllib_wx_get_scan(struct rtllib_device
*ieee
,
259 struct iw_request_info
*info
,
260 union iwreq_data
*wrqu
, char *extra
)
262 struct rtllib_network
*network
;
266 char *stop
= ev
+ wrqu
->data
.length
;
270 RTLLIB_DEBUG_WX("Getting scan\n");
272 spin_lock_irqsave(&ieee
->lock
, flags
);
274 list_for_each_entry(network
, &ieee
->network_list
, list
) {
276 if ((stop
- ev
) < 200) {
280 if (ieee
->scan_age
== 0 ||
281 time_after(network
->last_scanned
+ ieee
->scan_age
, jiffies
))
282 ev
= rtl819x_translate_scan(ieee
, ev
, stop
, network
,
285 RTLLIB_DEBUG_SCAN("Not showing network '%s ("
286 " %pM)' due to age (%lums).\n",
287 escape_essid(network
->ssid
,
290 (jiffies
- network
->last_scanned
) / (HZ
/ 100));
293 spin_unlock_irqrestore(&ieee
->lock
, flags
);
295 wrqu
->data
.length
= ev
- extra
;
296 wrqu
->data
.flags
= 0;
298 RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i
);
302 EXPORT_SYMBOL(rtllib_wx_get_scan
);
304 int rtllib_wx_set_encode(struct rtllib_device
*ieee
,
305 struct iw_request_info
*info
,
306 union iwreq_data
*wrqu
, char *keybuf
)
308 struct iw_point
*erq
= &(wrqu
->encoding
);
309 struct net_device
*dev
= ieee
->dev
;
310 struct rtllib_security sec
= {
313 int i
, key
, key_provided
, len
;
314 struct lib80211_crypt_data
**crypt
;
316 RTLLIB_DEBUG_WX("SET_ENCODE\n");
318 key
= erq
->flags
& IW_ENCODE_INDEX
;
320 if (key
> NUM_WEP_KEYS
)
326 key
= ieee
->crypt_info
.tx_keyidx
;
329 RTLLIB_DEBUG_WX("Key: %d [%s]\n", key
, key_provided
?
330 "provided" : "default");
331 crypt
= &ieee
->crypt_info
.crypt
[key
];
332 if (erq
->flags
& IW_ENCODE_DISABLED
) {
333 if (key_provided
&& *crypt
) {
334 RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
336 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
338 RTLLIB_DEBUG_WX("Disabling encryption.\n");
340 /* Check all the keys to see if any are still configured,
341 * and if no key index was provided, de-init them all */
342 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
343 if (ieee
->crypt_info
.crypt
[i
] != NULL
) {
346 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
,
347 &ieee
->crypt_info
.crypt
[i
]);
351 if (i
== NUM_WEP_KEYS
) {
353 sec
.level
= SEC_LEVEL_0
;
354 sec
.flags
|= SEC_ENABLED
| SEC_LEVEL
;
363 sec
.flags
|= SEC_ENABLED
;
365 if (*crypt
!= NULL
&& (*crypt
)->ops
!= NULL
&&
366 strcmp((*crypt
)->ops
->name
, "R-WEP") != 0) {
367 /* changing to use WEP; deinit previously used algorithm
369 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
372 if (*crypt
== NULL
) {
373 struct lib80211_crypt_data
*new_crypt
;
375 /* take WEP into use */
376 new_crypt
= kzalloc(sizeof(struct lib80211_crypt_data
),
378 if (new_crypt
== NULL
)
380 new_crypt
->ops
= lib80211_get_crypto_ops("R-WEP");
381 if (!new_crypt
->ops
) {
382 request_module("rtllib_crypt_wep");
383 new_crypt
->ops
= lib80211_get_crypto_ops("R-WEP");
387 new_crypt
->priv
= new_crypt
->ops
->init(key
);
389 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
393 printk(KERN_WARNING
"%s: could not initialize WEP: "
394 "load module rtllib_crypt_wep\n",
401 /* If a new key was provided, set it up */
402 if (erq
->length
> 0) {
403 len
= erq
->length
<= 5 ? 5 : 13;
404 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
405 if (len
> erq
->length
)
406 memset(sec
.keys
[key
] + erq
->length
, 0,
408 RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
409 key
, escape_essid(sec
.keys
[key
], len
),
411 sec
.key_sizes
[key
] = len
;
412 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
414 sec
.flags
|= (1 << key
);
415 /* This ensures a key will be activated if no key is
417 if (key
== sec
.active_key
)
418 sec
.flags
|= SEC_ACTIVE_KEY
;
419 ieee
->crypt_info
.tx_keyidx
= key
;
422 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
423 NULL
, (*crypt
)->priv
);
425 /* Set a default key of all 0 */
426 printk(KERN_INFO
"Setting key %d to all zero.\n",
429 RTLLIB_DEBUG_WX("Setting key %d to all zero.\n",
431 memset(sec
.keys
[key
], 0, 13);
432 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
434 sec
.key_sizes
[key
] = 13;
435 sec
.flags
|= (1 << key
);
438 /* No key data - just set the default TX key index */
441 "Setting key %d to default Tx key.\n", key
);
442 ieee
->crypt_info
.tx_keyidx
= key
;
443 sec
.active_key
= key
;
444 sec
.flags
|= SEC_ACTIVE_KEY
;
448 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
449 ieee
->auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
:
450 WLAN_AUTH_SHARED_KEY
;
451 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
: WLAN_AUTH_SHARED_KEY
;
452 sec
.flags
|= SEC_AUTH_MODE
;
453 RTLLIB_DEBUG_WX("Auth: %s\n", sec
.auth_mode
== WLAN_AUTH_OPEN
?
454 "OPEN" : "SHARED KEY");
456 /* For now we just support WEP, so only set that security level...
457 * TODO: When WPA is added this is one place that needs to change */
458 sec
.flags
|= SEC_LEVEL
;
459 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
461 if (ieee
->set_security
)
462 ieee
->set_security(dev
, &sec
);
464 /* Do not reset port if card is in Managed mode since resetting will
465 * generate new IEEE 802.11 authentication which may end up in looping
466 * with IEEE 802.1X. If your hardware requires a reset after WEP
467 * configuration (for example... Prism2), implement the reset_port in
468 * the callbacks structures used to initialize the 802.11 stack. */
469 if (ieee
->reset_on_keychange
&&
470 ieee
->iw_mode
!= IW_MODE_INFRA
&&
471 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
472 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
477 EXPORT_SYMBOL(rtllib_wx_set_encode
);
479 int rtllib_wx_get_encode(struct rtllib_device
*ieee
,
480 struct iw_request_info
*info
,
481 union iwreq_data
*wrqu
, char *keybuf
)
483 struct iw_point
*erq
= &(wrqu
->encoding
);
485 struct lib80211_crypt_data
*crypt
;
487 RTLLIB_DEBUG_WX("GET_ENCODE\n");
489 if (ieee
->iw_mode
== IW_MODE_MONITOR
)
492 key
= erq
->flags
& IW_ENCODE_INDEX
;
494 if (key
> NUM_WEP_KEYS
)
498 key
= ieee
->crypt_info
.tx_keyidx
;
500 crypt
= ieee
->crypt_info
.crypt
[key
];
502 erq
->flags
= key
+ 1;
504 if (crypt
== NULL
|| crypt
->ops
== NULL
) {
506 erq
->flags
|= IW_ENCODE_DISABLED
;
509 len
= crypt
->ops
->get_key(keybuf
, SCM_KEY_LEN
, NULL
, crypt
->priv
);
510 erq
->length
= (len
>= 0 ? len
: 0);
512 erq
->flags
|= IW_ENCODE_ENABLED
;
515 erq
->flags
|= IW_ENCODE_OPEN
;
517 erq
->flags
|= IW_ENCODE_RESTRICTED
;
521 EXPORT_SYMBOL(rtllib_wx_get_encode
);
523 int rtllib_wx_set_encode_ext(struct rtllib_device
*ieee
,
524 struct iw_request_info
*info
,
525 union iwreq_data
*wrqu
, char *extra
)
528 struct net_device
*dev
= ieee
->dev
;
529 struct iw_point
*encoding
= &wrqu
->encoding
;
530 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
533 const char *alg
, *module
;
534 struct lib80211_crypto_ops
*ops
;
535 struct lib80211_crypt_data
**crypt
;
537 struct rtllib_security sec
= {
540 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
542 if (idx
< 1 || idx
> NUM_WEP_KEYS
)
546 idx
= ieee
->crypt_info
.tx_keyidx
;
548 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
549 crypt
= &ieee
->crypt_info
.crypt
[idx
];
552 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
553 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
555 if (ieee
->iw_mode
== IW_MODE_INFRA
)
556 crypt
= &ieee
->crypt_info
.crypt
[idx
];
561 sec
.flags
|= SEC_ENABLED
;
562 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
563 ext
->alg
== IW_ENCODE_ALG_NONE
) {
565 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
567 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
568 if (ieee
->crypt_info
.crypt
[i
] != NULL
)
571 if (i
== NUM_WEP_KEYS
) {
573 sec
.level
= SEC_LEVEL_0
;
574 sec
.flags
|= SEC_LEVEL
;
581 case IW_ENCODE_ALG_WEP
:
583 module
= "rtllib_crypt_wep";
585 case IW_ENCODE_ALG_TKIP
:
587 module
= "rtllib_crypt_tkip";
589 case IW_ENCODE_ALG_CCMP
:
591 module
= "rtllib_crypt_ccmp";
594 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
595 dev
->name
, ext
->alg
);
599 printk(KERN_INFO
"alg name:%s\n", alg
);
601 ops
= lib80211_get_crypto_ops(alg
);
605 memset(tempbuf
, 0x00, 100);
606 sprintf(tempbuf
, "%s", module
);
607 request_module("%s", tempbuf
);
608 ops
= lib80211_get_crypto_ops(alg
);
611 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
612 dev
->name
, ext
->alg
);
613 printk(KERN_INFO
"========>unknown crypto alg %d\n", ext
->alg
);
618 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
619 struct lib80211_crypt_data
*new_crypt
;
621 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
623 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
624 if (new_crypt
== NULL
) {
628 new_crypt
->ops
= ops
;
630 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
632 if (new_crypt
->priv
== NULL
) {
641 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
642 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
643 (*crypt
)->priv
) < 0) {
644 RTLLIB_DEBUG_WX("%s: key setting failed\n", dev
->name
);
645 printk(KERN_INFO
"key setting failed\n");
649 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
650 ieee
->crypt_info
.tx_keyidx
= idx
;
651 sec
.active_key
= idx
;
652 sec
.flags
|= SEC_ACTIVE_KEY
;
654 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
655 sec
.key_sizes
[idx
] = ext
->key_len
;
656 sec
.flags
|= (1 << idx
);
657 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
658 sec
.flags
|= SEC_LEVEL
;
659 sec
.level
= SEC_LEVEL_1
;
660 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
661 sec
.flags
|= SEC_LEVEL
;
662 sec
.level
= SEC_LEVEL_2
;
663 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
664 sec
.flags
|= SEC_LEVEL
;
665 sec
.level
= SEC_LEVEL_3
;
667 /* Don't set sec level for group keys. */
669 sec
.flags
&= ~SEC_LEVEL
;
672 if (ieee
->set_security
)
673 ieee
->set_security(ieee
->dev
, &sec
);
675 if (ieee
->reset_on_keychange
&&
676 ieee
->iw_mode
!= IW_MODE_INFRA
&&
677 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
678 RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
683 EXPORT_SYMBOL(rtllib_wx_set_encode_ext
);
685 int rtllib_wx_get_encode_ext(struct rtllib_device
*ieee
,
686 struct iw_request_info
*info
,
687 union iwreq_data
*wrqu
, char *extra
)
689 struct iw_point
*encoding
= &wrqu
->encoding
;
690 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
691 struct lib80211_crypt_data
*crypt
;
692 int idx
, max_key_len
;
694 max_key_len
= encoding
->length
- sizeof(*ext
);
698 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
700 if (idx
< 1 || idx
> NUM_WEP_KEYS
)
704 idx
= ieee
->crypt_info
.tx_keyidx
;
706 if (!(ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) &&
707 (ext
->alg
!= IW_ENCODE_ALG_WEP
))
708 if (idx
!= 0 || (ieee
->iw_mode
!= IW_MODE_INFRA
))
711 crypt
= ieee
->crypt_info
.crypt
[idx
];
713 encoding
->flags
= idx
+ 1;
714 memset(ext
, 0, sizeof(*ext
));
716 if (crypt
== NULL
|| crypt
->ops
== NULL
) {
717 ext
->alg
= IW_ENCODE_ALG_NONE
;
719 encoding
->flags
|= IW_ENCODE_DISABLED
;
721 if (strcmp(crypt
->ops
->name
, "R-WEP") == 0)
722 ext
->alg
= IW_ENCODE_ALG_WEP
;
723 else if (strcmp(crypt
->ops
->name
, "R-TKIP"))
724 ext
->alg
= IW_ENCODE_ALG_TKIP
;
725 else if (strcmp(crypt
->ops
->name
, "R-CCMP"))
726 ext
->alg
= IW_ENCODE_ALG_CCMP
;
729 ext
->key_len
= crypt
->ops
->get_key(ext
->key
, SCM_KEY_LEN
,
731 encoding
->flags
|= IW_ENCODE_ENABLED
;
733 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
734 ext
->alg
== IW_ENCODE_ALG_CCMP
))
735 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
742 int rtllib_wx_set_mlme(struct rtllib_device
*ieee
,
743 struct iw_request_info
*info
,
744 union iwreq_data
*wrqu
, char *extra
)
748 struct iw_mlme
*mlme
= (struct iw_mlme
*) extra
;
750 if (ieee
->state
!= RTLLIB_LINKED
)
758 /* leave break out intentionly */
760 case IW_MLME_DISASSOC
:
762 printk(KERN_INFO
"disauth packet !\n");
764 printk(KERN_INFO
"dis associate packet!\n");
766 ieee
->cannot_notify
= true;
768 SendDisassociation(ieee
, deauth
, mlme
->reason_code
);
769 rtllib_disassociate(ieee
);
772 for (i
= 0; i
< 6; i
++)
773 ieee
->current_network
.bssid
[i
] = 0x55;
776 ieee
->current_network
.ssid
[0] = '\0';
777 ieee
->current_network
.ssid_len
= 0;
788 EXPORT_SYMBOL(rtllib_wx_set_mlme
);
790 int rtllib_wx_set_auth(struct rtllib_device
*ieee
,
791 struct iw_request_info
*info
,
792 struct iw_param
*data
, char *extra
)
794 switch (data
->flags
& IW_AUTH_INDEX
) {
795 case IW_AUTH_WPA_VERSION
:
797 case IW_AUTH_CIPHER_PAIRWISE
:
798 case IW_AUTH_CIPHER_GROUP
:
799 case IW_AUTH_KEY_MGMT
:
801 * Host AP driver does not use these parameters and allows
802 * wpa_supplicant to control them internally.
805 case IW_AUTH_TKIP_COUNTERMEASURES
:
806 ieee
->tkip_countermeasures
= data
->value
;
808 case IW_AUTH_DROP_UNENCRYPTED
:
809 ieee
->drop_unencrypted
= data
->value
;
812 case IW_AUTH_80211_AUTH_ALG
:
813 if (data
->value
& IW_AUTH_ALG_SHARED_KEY
) {
816 } else if (data
->value
& IW_AUTH_ALG_OPEN_SYSTEM
) {
819 } else if (data
->value
& IW_AUTH_ALG_LEAP
) {
826 case IW_AUTH_WPA_ENABLED
:
827 ieee
->wpa_enabled
= (data
->value
) ? 1 : 0;
830 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
831 ieee
->ieee802_1x
= data
->value
;
833 case IW_AUTH_PRIVACY_INVOKED
:
834 ieee
->privacy_invoked
= data
->value
;
841 EXPORT_SYMBOL(rtllib_wx_set_auth
);
843 int rtllib_wx_set_gen_ie(struct rtllib_device
*ieee
, u8
*ie
, size_t len
)
846 u8 eid
, wps_oui
[4] = {0x0, 0x50, 0xf2, 0x04};
848 if (len
> MAX_WPA_IE_LEN
|| (len
&& ie
== NULL
))
853 if ((eid
== MFIE_TYPE_GENERIC
) && (!memcmp(&ie
[2],
856 ieee
->wps_ie_len
= (len
< MAX_WZC_IE_LEN
) ? (len
) :
858 buf
= kmemdup(ie
, ieee
->wps_ie_len
, GFP_KERNEL
);
865 ieee
->wps_ie_len
= 0;
871 buf
= kmemdup(ie
, len
, GFP_KERNEL
);
876 ieee
->wpa_ie_len
= len
;
880 ieee
->wpa_ie_len
= 0;
884 EXPORT_SYMBOL(rtllib_wx_set_gen_ie
);