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
< (sizeof(rtllib_modes
)/sizeof(rtllib_modes
[0])); 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;
161 if (!memcmp(network
->bssht
.bdHTCapBuf
, EWC11NHTCap
, 4))
162 ht_cap
= (struct ht_capab_ele
*)
163 &network
->bssht
.bdHTCapBuf
[4];
165 ht_cap
= (struct ht_capab_ele
*)
166 &network
->bssht
.bdHTCapBuf
[0];
167 is40M
= (ht_cap
->ChlWidth
) ? 1 : 0;
168 isShortGI
= (ht_cap
->ChlWidth
) ?
169 ((ht_cap
->ShortGI40Mhz
) ? 1 : 0) :
170 ((ht_cap
->ShortGI20Mhz
) ? 1 : 0);
172 max_mcs
= HTGetHighestMCSRate(ieee
, ht_cap
->MCS
,
174 rate
= MCS_DATA_RATE
[is40M
][isShortGI
][max_mcs
& 0x7f];
178 iwe
.cmd
= SIOCGIWRATE
;
179 iwe
.u
.bitrate
.fixed
= iwe
.u
.bitrate
.disabled
= 0;
180 iwe
.u
.bitrate
.value
= max_rate
* 500000;
181 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
,
183 iwe
.cmd
= IWEVCUSTOM
;
184 iwe
.u
.data
.length
= p
- custom
;
185 if (iwe
.u
.data
.length
)
186 start
= iwe_stream_add_point_rsl(info
, start
, stop
,
188 /* Add quality statistics */
189 /* TODO: Fix these values... */
191 iwe
.u
.qual
.qual
= network
->stats
.signal
;
192 iwe
.u
.qual
.level
= network
->stats
.rssi
;
193 iwe
.u
.qual
.noise
= network
->stats
.noise
;
194 iwe
.u
.qual
.updated
= network
->stats
.mask
& RTLLIB_STATMASK_WEMASK
;
195 if (!(network
->stats
.mask
& RTLLIB_STATMASK_RSSI
))
196 iwe
.u
.qual
.updated
|= IW_QUAL_LEVEL_INVALID
;
197 if (!(network
->stats
.mask
& RTLLIB_STATMASK_NOISE
))
198 iwe
.u
.qual
.updated
|= IW_QUAL_NOISE_INVALID
;
199 if (!(network
->stats
.mask
& RTLLIB_STATMASK_SIGNAL
))
200 iwe
.u
.qual
.updated
|= IW_QUAL_QUAL_INVALID
;
201 iwe
.u
.qual
.updated
= 7;
202 start
= iwe_stream_add_event_rsl(info
, start
, stop
, &iwe
,
205 iwe
.cmd
= IWEVCUSTOM
;
207 iwe
.u
.data
.length
= p
- custom
;
208 if (iwe
.u
.data
.length
)
209 start
= iwe_stream_add_point_rsl(info
, start
, stop
,
212 memset(&iwe
, 0, sizeof(iwe
));
213 if (network
->wpa_ie_len
) {
214 char buf
[MAX_WPA_IE_LEN
];
215 memcpy(buf
, network
->wpa_ie
, network
->wpa_ie_len
);
217 iwe
.u
.data
.length
= network
->wpa_ie_len
;
218 start
= iwe_stream_add_point_rsl(info
, start
, stop
, &iwe
, buf
);
220 memset(&iwe
, 0, sizeof(iwe
));
221 if (network
->rsn_ie_len
) {
222 char buf
[MAX_WPA_IE_LEN
];
223 memcpy(buf
, network
->rsn_ie
, network
->rsn_ie_len
);
225 iwe
.u
.data
.length
= network
->rsn_ie_len
;
226 start
= iwe_stream_add_point_rsl(info
, start
, stop
, &iwe
, buf
);
229 /* add info for WZC */
230 memset(&iwe
, 0, sizeof(iwe
));
231 if (network
->wzc_ie_len
) {
232 char buf
[MAX_WZC_IE_LEN
];
233 memcpy(buf
, network
->wzc_ie
, network
->wzc_ie_len
);
235 iwe
.u
.data
.length
= network
->wzc_ie_len
;
236 start
= iwe_stream_add_point_rsl(info
, start
, stop
, &iwe
, buf
);
239 /* Add EXTRA: Age to display seconds since last beacon/probe response
240 * for given network. */
241 iwe
.cmd
= IWEVCUSTOM
;
243 p
+= snprintf(p
, MAX_CUSTOM_LEN
- (p
- custom
),
244 " Last beacon: %lums ago",
245 (jiffies
- network
->last_scanned
) / (HZ
/ 100));
246 iwe
.u
.data
.length
= p
- custom
;
247 if (iwe
.u
.data
.length
)
248 start
= iwe_stream_add_point_rsl(info
, start
, stop
,
254 int rtllib_wx_get_scan(struct rtllib_device
*ieee
,
255 struct iw_request_info
*info
,
256 union iwreq_data
*wrqu
, char *extra
)
258 struct rtllib_network
*network
;
262 char *stop
= ev
+ wrqu
->data
.length
;
265 RTLLIB_DEBUG_WX("Getting scan\n");
267 spin_lock_irqsave(&ieee
->lock
, flags
);
269 list_for_each_entry(network
, &ieee
->network_list
, list
) {
271 if ((stop
- ev
) < 200) {
275 if (ieee
->scan_age
== 0 ||
276 time_after(network
->last_scanned
+ ieee
->scan_age
, jiffies
))
277 ev
= rtl819x_translate_scan(ieee
, ev
, stop
, network
,
280 RTLLIB_DEBUG_SCAN("Not showing network '%s ("
281 " %pM)' due to age (%lums).\n",
282 escape_essid(network
->ssid
,
285 (jiffies
- network
->last_scanned
) / (HZ
/ 100));
288 spin_unlock_irqrestore(&ieee
->lock
, flags
);
290 wrqu
->data
.length
= ev
- extra
;
291 wrqu
->data
.flags
= 0;
293 RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i
);
297 EXPORT_SYMBOL(rtllib_wx_get_scan
);
299 int rtllib_wx_set_encode(struct rtllib_device
*ieee
,
300 struct iw_request_info
*info
,
301 union iwreq_data
*wrqu
, char *keybuf
)
303 struct iw_point
*erq
= &(wrqu
->encoding
);
304 struct net_device
*dev
= ieee
->dev
;
305 struct rtllib_security sec
= {
308 int i
, key
, key_provided
, len
;
309 struct lib80211_crypt_data
**crypt
;
311 RTLLIB_DEBUG_WX("SET_ENCODE\n");
313 key
= erq
->flags
& IW_ENCODE_INDEX
;
315 if (key
> NUM_WEP_KEYS
)
321 key
= ieee
->crypt_info
.tx_keyidx
;
324 RTLLIB_DEBUG_WX("Key: %d [%s]\n", key
, key_provided
?
325 "provided" : "default");
326 crypt
= &ieee
->crypt_info
.crypt
[key
];
327 if (erq
->flags
& IW_ENCODE_DISABLED
) {
328 if (key_provided
&& *crypt
) {
329 RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
331 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
333 RTLLIB_DEBUG_WX("Disabling encryption.\n");
335 /* Check all the keys to see if any are still configured,
336 * and if no key index was provided, de-init them all */
337 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
338 if (ieee
->crypt_info
.crypt
[i
] != NULL
) {
341 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
,
342 &ieee
->crypt_info
.crypt
[i
]);
346 if (i
== NUM_WEP_KEYS
) {
348 sec
.level
= SEC_LEVEL_0
;
349 sec
.flags
|= SEC_ENABLED
| SEC_LEVEL
;
358 sec
.flags
|= SEC_ENABLED
;
360 if (*crypt
!= NULL
&& (*crypt
)->ops
!= NULL
&&
361 strcmp((*crypt
)->ops
->name
, "R-WEP") != 0) {
362 /* changing to use WEP; deinit previously used algorithm
364 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
367 if (*crypt
== NULL
) {
368 struct lib80211_crypt_data
*new_crypt
;
370 /* take WEP into use */
371 new_crypt
= kzalloc(sizeof(struct lib80211_crypt_data
),
373 if (new_crypt
== NULL
)
375 new_crypt
->ops
= lib80211_get_crypto_ops("R-WEP");
376 if (!new_crypt
->ops
) {
377 request_module("rtllib_crypt_wep");
378 new_crypt
->ops
= lib80211_get_crypto_ops("R-WEP");
382 new_crypt
->priv
= new_crypt
->ops
->init(key
);
384 if (!new_crypt
->ops
|| !new_crypt
->priv
) {
388 printk(KERN_WARNING
"%s: could not initialize WEP: "
389 "load module rtllib_crypt_wep\n",
396 /* If a new key was provided, set it up */
397 if (erq
->length
> 0) {
398 len
= erq
->length
<= 5 ? 5 : 13;
399 memcpy(sec
.keys
[key
], keybuf
, erq
->length
);
400 if (len
> erq
->length
)
401 memset(sec
.keys
[key
] + erq
->length
, 0,
403 RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
404 key
, escape_essid(sec
.keys
[key
], len
),
406 sec
.key_sizes
[key
] = len
;
407 (*crypt
)->ops
->set_key(sec
.keys
[key
], len
, NULL
,
409 sec
.flags
|= (1 << key
);
410 /* This ensures a key will be activated if no key is
412 if (key
== sec
.active_key
)
413 sec
.flags
|= SEC_ACTIVE_KEY
;
414 ieee
->crypt_info
.tx_keyidx
= key
;
417 len
= (*crypt
)->ops
->get_key(sec
.keys
[key
], WEP_KEY_LEN
,
418 NULL
, (*crypt
)->priv
);
420 /* Set a default key of all 0 */
421 printk(KERN_INFO
"Setting key %d to all zero.\n",
424 RTLLIB_DEBUG_WX("Setting key %d to all zero.\n",
426 memset(sec
.keys
[key
], 0, 13);
427 (*crypt
)->ops
->set_key(sec
.keys
[key
], 13, NULL
,
429 sec
.key_sizes
[key
] = 13;
430 sec
.flags
|= (1 << key
);
433 /* No key data - just set the default TX key index */
436 "Setting key %d to default Tx key.\n", key
);
437 ieee
->crypt_info
.tx_keyidx
= key
;
438 sec
.active_key
= key
;
439 sec
.flags
|= SEC_ACTIVE_KEY
;
443 ieee
->open_wep
= !(erq
->flags
& IW_ENCODE_RESTRICTED
);
444 ieee
->auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
:
445 WLAN_AUTH_SHARED_KEY
;
446 sec
.auth_mode
= ieee
->open_wep
? WLAN_AUTH_OPEN
: WLAN_AUTH_SHARED_KEY
;
447 sec
.flags
|= SEC_AUTH_MODE
;
448 RTLLIB_DEBUG_WX("Auth: %s\n", sec
.auth_mode
== WLAN_AUTH_OPEN
?
449 "OPEN" : "SHARED KEY");
451 /* For now we just support WEP, so only set that security level...
452 * TODO: When WPA is added this is one place that needs to change */
453 sec
.flags
|= SEC_LEVEL
;
454 sec
.level
= SEC_LEVEL_1
; /* 40 and 104 bit WEP */
456 if (ieee
->set_security
)
457 ieee
->set_security(dev
, &sec
);
459 /* Do not reset port if card is in Managed mode since resetting will
460 * generate new IEEE 802.11 authentication which may end up in looping
461 * with IEEE 802.1X. If your hardware requires a reset after WEP
462 * configuration (for example... Prism2), implement the reset_port in
463 * the callbacks structures used to initialize the 802.11 stack. */
464 if (ieee
->reset_on_keychange
&&
465 ieee
->iw_mode
!= IW_MODE_INFRA
&&
466 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
467 printk(KERN_DEBUG
"%s: reset_port failed\n", dev
->name
);
472 EXPORT_SYMBOL(rtllib_wx_set_encode
);
474 int rtllib_wx_get_encode(struct rtllib_device
*ieee
,
475 struct iw_request_info
*info
,
476 union iwreq_data
*wrqu
, char *keybuf
)
478 struct iw_point
*erq
= &(wrqu
->encoding
);
480 struct lib80211_crypt_data
*crypt
;
482 RTLLIB_DEBUG_WX("GET_ENCODE\n");
484 if (ieee
->iw_mode
== IW_MODE_MONITOR
)
487 key
= erq
->flags
& IW_ENCODE_INDEX
;
489 if (key
> NUM_WEP_KEYS
)
493 key
= ieee
->crypt_info
.tx_keyidx
;
495 crypt
= ieee
->crypt_info
.crypt
[key
];
497 erq
->flags
= key
+ 1;
499 if (crypt
== NULL
|| crypt
->ops
== NULL
) {
501 erq
->flags
|= IW_ENCODE_DISABLED
;
504 len
= crypt
->ops
->get_key(keybuf
, SCM_KEY_LEN
, NULL
, crypt
->priv
);
505 erq
->length
= (len
>= 0 ? len
: 0);
507 erq
->flags
|= IW_ENCODE_ENABLED
;
510 erq
->flags
|= IW_ENCODE_OPEN
;
512 erq
->flags
|= IW_ENCODE_RESTRICTED
;
516 EXPORT_SYMBOL(rtllib_wx_get_encode
);
518 int rtllib_wx_set_encode_ext(struct rtllib_device
*ieee
,
519 struct iw_request_info
*info
,
520 union iwreq_data
*wrqu
, char *extra
)
523 struct net_device
*dev
= ieee
->dev
;
524 struct iw_point
*encoding
= &wrqu
->encoding
;
525 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
528 const char *alg
, *module
;
529 struct lib80211_crypto_ops
*ops
;
530 struct lib80211_crypt_data
**crypt
;
532 struct rtllib_security sec
= {
535 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
537 if (idx
< 1 || idx
> NUM_WEP_KEYS
)
541 idx
= ieee
->crypt_info
.tx_keyidx
;
543 if (ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) {
544 crypt
= &ieee
->crypt_info
.crypt
[idx
];
547 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
548 if (idx
!= 0 && ext
->alg
!= IW_ENCODE_ALG_WEP
)
550 if (ieee
->iw_mode
== IW_MODE_INFRA
)
551 crypt
= &ieee
->crypt_info
.crypt
[idx
];
556 sec
.flags
|= SEC_ENABLED
;
557 if ((encoding
->flags
& IW_ENCODE_DISABLED
) ||
558 ext
->alg
== IW_ENCODE_ALG_NONE
) {
560 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
562 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
563 if (ieee
->crypt_info
.crypt
[i
] != NULL
)
566 if (i
== NUM_WEP_KEYS
) {
568 sec
.level
= SEC_LEVEL_0
;
569 sec
.flags
|= SEC_LEVEL
;
576 case IW_ENCODE_ALG_WEP
:
578 module
= "rtllib_crypt_wep";
580 case IW_ENCODE_ALG_TKIP
:
582 module
= "rtllib_crypt_tkip";
584 case IW_ENCODE_ALG_CCMP
:
586 module
= "rtllib_crypt_ccmp";
589 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
590 dev
->name
, ext
->alg
);
594 printk(KERN_INFO
"alg name:%s\n", alg
);
596 ops
= lib80211_get_crypto_ops(alg
);
600 memset(tempbuf
, 0x00, 100);
601 sprintf(tempbuf
, "%s", module
);
602 request_module("%s", tempbuf
);
603 ops
= lib80211_get_crypto_ops(alg
);
606 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
607 dev
->name
, ext
->alg
);
608 printk(KERN_INFO
"========>unknown crypto alg %d\n", ext
->alg
);
613 if (*crypt
== NULL
|| (*crypt
)->ops
!= ops
) {
614 struct lib80211_crypt_data
*new_crypt
;
616 lib80211_crypt_delayed_deinit(&ieee
->crypt_info
, crypt
);
618 new_crypt
= kzalloc(sizeof(*new_crypt
), GFP_KERNEL
);
619 if (new_crypt
== NULL
) {
623 new_crypt
->ops
= ops
;
625 new_crypt
->priv
= new_crypt
->ops
->init(idx
);
627 if (new_crypt
->priv
== NULL
) {
636 if (ext
->key_len
> 0 && (*crypt
)->ops
->set_key
&&
637 (*crypt
)->ops
->set_key(ext
->key
, ext
->key_len
, ext
->rx_seq
,
638 (*crypt
)->priv
) < 0) {
639 RTLLIB_DEBUG_WX("%s: key setting failed\n", dev
->name
);
640 printk(KERN_INFO
"key setting failed\n");
644 if (ext
->ext_flags
& IW_ENCODE_EXT_SET_TX_KEY
) {
645 ieee
->crypt_info
.tx_keyidx
= idx
;
646 sec
.active_key
= idx
;
647 sec
.flags
|= SEC_ACTIVE_KEY
;
649 if (ext
->alg
!= IW_ENCODE_ALG_NONE
) {
650 sec
.key_sizes
[idx
] = ext
->key_len
;
651 sec
.flags
|= (1 << idx
);
652 if (ext
->alg
== IW_ENCODE_ALG_WEP
) {
653 sec
.flags
|= SEC_LEVEL
;
654 sec
.level
= SEC_LEVEL_1
;
655 } else if (ext
->alg
== IW_ENCODE_ALG_TKIP
) {
656 sec
.flags
|= SEC_LEVEL
;
657 sec
.level
= SEC_LEVEL_2
;
658 } else if (ext
->alg
== IW_ENCODE_ALG_CCMP
) {
659 sec
.flags
|= SEC_LEVEL
;
660 sec
.level
= SEC_LEVEL_3
;
662 /* Don't set sec level for group keys. */
664 sec
.flags
&= ~SEC_LEVEL
;
667 if (ieee
->set_security
)
668 ieee
->set_security(ieee
->dev
, &sec
);
670 if (ieee
->reset_on_keychange
&&
671 ieee
->iw_mode
!= IW_MODE_INFRA
&&
672 ieee
->reset_port
&& ieee
->reset_port(dev
)) {
673 RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev
->name
);
678 EXPORT_SYMBOL(rtllib_wx_set_encode_ext
);
680 int rtllib_wx_get_encode_ext(struct rtllib_device
*ieee
,
681 struct iw_request_info
*info
,
682 union iwreq_data
*wrqu
, char *extra
)
684 struct iw_point
*encoding
= &wrqu
->encoding
;
685 struct iw_encode_ext
*ext
= (struct iw_encode_ext
*)extra
;
686 struct lib80211_crypt_data
*crypt
;
687 int idx
, max_key_len
;
689 max_key_len
= encoding
->length
- sizeof(*ext
);
693 idx
= encoding
->flags
& IW_ENCODE_INDEX
;
695 if (idx
< 1 || idx
> NUM_WEP_KEYS
)
699 idx
= ieee
->crypt_info
.tx_keyidx
;
701 if (!(ext
->ext_flags
& IW_ENCODE_EXT_GROUP_KEY
) &&
702 (ext
->alg
!= IW_ENCODE_ALG_WEP
))
703 if (idx
!= 0 || (ieee
->iw_mode
!= IW_MODE_INFRA
))
706 crypt
= ieee
->crypt_info
.crypt
[idx
];
708 encoding
->flags
= idx
+ 1;
709 memset(ext
, 0, sizeof(*ext
));
711 if (crypt
== NULL
|| crypt
->ops
== NULL
) {
712 ext
->alg
= IW_ENCODE_ALG_NONE
;
714 encoding
->flags
|= IW_ENCODE_DISABLED
;
716 if (strcmp(crypt
->ops
->name
, "R-WEP") == 0)
717 ext
->alg
= IW_ENCODE_ALG_WEP
;
718 else if (strcmp(crypt
->ops
->name
, "R-TKIP"))
719 ext
->alg
= IW_ENCODE_ALG_TKIP
;
720 else if (strcmp(crypt
->ops
->name
, "R-CCMP"))
721 ext
->alg
= IW_ENCODE_ALG_CCMP
;
724 ext
->key_len
= crypt
->ops
->get_key(ext
->key
, SCM_KEY_LEN
,
726 encoding
->flags
|= IW_ENCODE_ENABLED
;
728 (ext
->alg
== IW_ENCODE_ALG_TKIP
||
729 ext
->alg
== IW_ENCODE_ALG_CCMP
))
730 ext
->ext_flags
|= IW_ENCODE_EXT_TX_SEQ_VALID
;
737 int rtllib_wx_set_mlme(struct rtllib_device
*ieee
,
738 struct iw_request_info
*info
,
739 union iwreq_data
*wrqu
, char *extra
)
743 struct iw_mlme
*mlme
= (struct iw_mlme
*) extra
;
745 if (ieee
->state
!= RTLLIB_LINKED
)
753 /* leave break out intentionly */
755 case IW_MLME_DISASSOC
:
757 printk(KERN_INFO
"disauth packet !\n");
759 printk(KERN_INFO
"dis associate packet!\n");
761 ieee
->cannot_notify
= true;
763 SendDisassociation(ieee
, deauth
, mlme
->reason_code
);
764 rtllib_disassociate(ieee
);
767 for (i
= 0; i
< 6; i
++)
768 ieee
->current_network
.bssid
[i
] = 0x55;
771 ieee
->current_network
.ssid
[0] = '\0';
772 ieee
->current_network
.ssid_len
= 0;
783 EXPORT_SYMBOL(rtllib_wx_set_mlme
);
785 int rtllib_wx_set_auth(struct rtllib_device
*ieee
,
786 struct iw_request_info
*info
,
787 struct iw_param
*data
, char *extra
)
789 switch (data
->flags
& IW_AUTH_INDEX
) {
790 case IW_AUTH_WPA_VERSION
:
792 case IW_AUTH_CIPHER_PAIRWISE
:
793 case IW_AUTH_CIPHER_GROUP
:
794 case IW_AUTH_KEY_MGMT
:
796 * Host AP driver does not use these parameters and allows
797 * wpa_supplicant to control them internally.
800 case IW_AUTH_TKIP_COUNTERMEASURES
:
801 ieee
->tkip_countermeasures
= data
->value
;
803 case IW_AUTH_DROP_UNENCRYPTED
:
804 ieee
->drop_unencrypted
= data
->value
;
807 case IW_AUTH_80211_AUTH_ALG
:
808 if (data
->value
& IW_AUTH_ALG_SHARED_KEY
) {
811 } else if (data
->value
& IW_AUTH_ALG_OPEN_SYSTEM
) {
814 } else if (data
->value
& IW_AUTH_ALG_LEAP
) {
821 case IW_AUTH_WPA_ENABLED
:
822 ieee
->wpa_enabled
= (data
->value
) ? 1 : 0;
825 case IW_AUTH_RX_UNENCRYPTED_EAPOL
:
826 ieee
->ieee802_1x
= data
->value
;
828 case IW_AUTH_PRIVACY_INVOKED
:
829 ieee
->privacy_invoked
= data
->value
;
836 EXPORT_SYMBOL(rtllib_wx_set_auth
);
838 int rtllib_wx_set_gen_ie(struct rtllib_device
*ieee
, u8
*ie
, size_t len
)
841 u8 eid
, wps_oui
[4] = {0x0, 0x50, 0xf2, 0x04};
843 if (len
> MAX_WPA_IE_LEN
|| (len
&& ie
== NULL
))
848 if ((eid
== MFIE_TYPE_GENERIC
) && (!memcmp(&ie
[2],
851 ieee
->wps_ie_len
= (len
< MAX_WZC_IE_LEN
) ? (len
) :
853 buf
= kmemdup(ie
, ieee
->wps_ie_len
, GFP_KERNEL
);
860 ieee
->wps_ie_len
= 0;
866 buf
= kmemdup(ie
, len
, GFP_KERNEL
);
871 ieee
->wpa_ie_len
= len
;
875 ieee
->wpa_ie_len
= 0;
879 EXPORT_SYMBOL(rtllib_wx_set_gen_ie
);