blob: a8fd2e1f4ada28860e82e375c168b19fc7c75be7 [file] [log] [blame]
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -07001/******************************************************************************
2
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
4
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
8 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
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.
14
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
18 more details.
19
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.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31******************************************************************************/
32#include <linux/wireless.h>
33#include <linux/version.h>
34#include <linux/kmod.h>
35#include <linux/module.h>
36
Larry Finger94a79942011-08-23 19:00:42 -050037#include "rtllib.h"
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070038struct modes_unit {
39 char *mode_string;
40 int mode_size;
41};
Larry Finger94a79942011-08-23 19:00:42 -050042static struct modes_unit rtllib_modes[] = {
Larry Finger62f27cc2011-08-25 11:48:29 -050043 {"a", 1},
44 {"b", 1},
45 {"g", 1},
46 {"?", 1},
47 {"N-24G", 5},
48 {"N-5G", 4},
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070049};
50
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070051#define MAX_CUSTOM_LEN 64
Larry Finger94a79942011-08-23 19:00:42 -050052static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
53 char *start, char *stop,
54 struct rtllib_network *network,
Larry Finger62f27cc2011-08-25 11:48:29 -050055 struct iw_request_info *info)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070056{
57 char custom[MAX_CUSTOM_LEN];
58 char proto_name[IFNAMSIZ];
59 char *pname = proto_name;
60 char *p;
61 struct iw_event iwe;
62 int i, j;
63 u16 max_rate, rate;
64 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
65
66 /* First entry *MUST* be the AP MAC address */
67 iwe.cmd = SIOCGIWAP;
68 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
69 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
Larry Finger62f27cc2011-08-25 11:48:29 -050070 start = iwe_stream_add_event_rsl(info, start, stop,
71 &iwe, IW_EV_ADDR_LEN);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070072 /* Remaining entries will be displayed in the order we provide them */
73
74 /* Add the ESSID */
75 iwe.cmd = SIOCGIWESSID;
76 iwe.u.data.flags = 1;
Larry Finger62f27cc2011-08-25 11:48:29 -050077 if (network->ssid_len > 0) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070078 iwe.u.data.length = min(network->ssid_len, (u8)32);
Larry Finger62f27cc2011-08-25 11:48:29 -050079 start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
80 network->ssid);
81 } else if (network->hidden_ssid_len == 0) {
Larry Finger94a79942011-08-23 19:00:42 -050082 iwe.u.data.length = sizeof("<hidden>");
Larry Finger62f27cc2011-08-25 11:48:29 -050083 start = iwe_stream_add_point_rsl(info, start, stop,
84 &iwe, "<hidden>");
85 } else {
Larry Finger94a79942011-08-23 19:00:42 -050086 iwe.u.data.length = min(network->hidden_ssid_len, (u8)32);
Larry Finger62f27cc2011-08-25 11:48:29 -050087 start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
88 network->hidden_ssid);
Larry Finger94a79942011-08-23 19:00:42 -050089 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070090 /* Add the protocol name */
91 iwe.cmd = SIOCGIWNAME;
Larry Finger62f27cc2011-08-25 11:48:29 -050092 for (i = 0; i < (sizeof(rtllib_modes)/sizeof(rtllib_modes[0])); i++) {
Larry Finger94a79942011-08-23 19:00:42 -050093 if (network->mode&(1<<i)) {
Larry Finger62f27cc2011-08-25 11:48:29 -050094 sprintf(pname, rtllib_modes[i].mode_string,
95 rtllib_modes[i].mode_size);
96 pname += rtllib_modes[i].mode_size;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -070097 }
98 }
99 *pname = '\0';
100 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
Larry Finger62f27cc2011-08-25 11:48:29 -0500101 start = iwe_stream_add_event_rsl(info, start, stop,
102 &iwe, IW_EV_CHAR_LEN);
103 /* Add mode */
104 iwe.cmd = SIOCGIWMODE;
105 if (network->capability &
Larry Finger94a79942011-08-23 19:00:42 -0500106 (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
107 if (network->capability & WLAN_CAPABILITY_ESS)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700108 iwe.u.mode = IW_MODE_MASTER;
109 else
110 iwe.u.mode = IW_MODE_ADHOC;
Larry Finger62f27cc2011-08-25 11:48:29 -0500111 start = iwe_stream_add_event_rsl(info, start, stop,
112 &iwe, IW_EV_UINT_LEN);
113 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700114
Larry Finger62f27cc2011-08-25 11:48:29 -0500115 /* Add frequency/channel */
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700116 iwe.cmd = SIOCGIWFREQ;
Larry Finger94a79942011-08-23 19:00:42 -0500117/* iwe.u.freq.m = rtllib_frequency(network->channel, network->mode);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700118 iwe.u.freq.e = 3; */
119 iwe.u.freq.m = network->channel;
120 iwe.u.freq.e = 0;
121 iwe.u.freq.i = 0;
Larry Finger62f27cc2011-08-25 11:48:29 -0500122 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
123 IW_EV_FREQ_LEN);
Larry Finger94a79942011-08-23 19:00:42 -0500124
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700125 /* Add encryption capability */
126 iwe.cmd = SIOCGIWENCODE;
127 if (network->capability & WLAN_CAPABILITY_PRIVACY)
128 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
129 else
130 iwe.u.data.flags = IW_ENCODE_DISABLED;
131 iwe.u.data.length = 0;
Larry Finger62f27cc2011-08-25 11:48:29 -0500132 start = iwe_stream_add_point_rsl(info, start, stop,
133 &iwe, network->ssid);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700134 /* Add basic and extended rates */
135 max_rate = 0;
136 p = custom;
137 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
Larry Finger62f27cc2011-08-25 11:48:29 -0500138 for (i = 0, j = 0; i < network->rates_len;) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700139 if (j < network->rates_ex_len &&
140 ((network->rates_ex[j] & 0x7F) <
141 (network->rates[i] & 0x7F)))
142 rate = network->rates_ex[j++] & 0x7F;
143 else
144 rate = network->rates[i++] & 0x7F;
145 if (rate > max_rate)
146 max_rate = rate;
147 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
148 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
149 }
150 for (; j < network->rates_ex_len; j++) {
151 rate = network->rates_ex[j] & 0x7F;
152 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
153 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
154 if (rate > max_rate)
155 max_rate = rate;
156 }
157
Larry Finger62f27cc2011-08-25 11:48:29 -0500158 if (network->mode >= IEEE_N_24G) {
Larry Fingere92b71d2011-07-18 20:34:19 -0500159 struct ht_capab_ele *ht_cap = NULL;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700160 bool is40M = false, isShortGI = false;
161 u8 max_mcs = 0;
162 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
Larry Finger62f27cc2011-08-25 11:48:29 -0500163 ht_cap = (struct ht_capab_ele *)
164 &network->bssht.bdHTCapBuf[4];
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700165 else
Larry Finger62f27cc2011-08-25 11:48:29 -0500166 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);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700172
Larry Finger62f27cc2011-08-25 11:48:29 -0500173 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS,
174 MCS_FILTER_ALL);
175 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f];
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700176 if (rate > max_rate)
177 max_rate = rate;
178 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700179 iwe.cmd = SIOCGIWRATE;
180 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
181 iwe.u.bitrate.value = max_rate * 500000;
Larry Finger94a79942011-08-23 19:00:42 -0500182 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700183 IW_EV_PARAM_LEN);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700184 iwe.cmd = IWEVCUSTOM;
185 iwe.u.data.length = p - custom;
186 if (iwe.u.data.length)
Larry Finger62f27cc2011-08-25 11:48:29 -0500187 start = iwe_stream_add_point_rsl(info, start, stop,
188 &iwe, custom);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700189 /* Add quality statistics */
190 /* TODO: Fix these values... */
191 iwe.cmd = IWEVQUAL;
192 iwe.u.qual.qual = network->stats.signal;
193 iwe.u.qual.level = network->stats.rssi;
194 iwe.u.qual.noise = network->stats.noise;
Larry Finger94a79942011-08-23 19:00:42 -0500195 iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK;
196 if (!(network->stats.mask & RTLLIB_STATMASK_RSSI))
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700197 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
Larry Finger94a79942011-08-23 19:00:42 -0500198 if (!(network->stats.mask & RTLLIB_STATMASK_NOISE))
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700199 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
Larry Finger94a79942011-08-23 19:00:42 -0500200 if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL))
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700201 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
202 iwe.u.qual.updated = 7;
Larry Finger62f27cc2011-08-25 11:48:29 -0500203 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
204 IW_EV_QUAL_LEN);
Larry Finger94a79942011-08-23 19:00:42 -0500205
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700206 iwe.cmd = IWEVCUSTOM;
207 p = custom;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700208 iwe.u.data.length = p - custom;
209 if (iwe.u.data.length)
Larry Finger62f27cc2011-08-25 11:48:29 -0500210 start = iwe_stream_add_point_rsl(info, start, stop,
211 &iwe, custom);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700212
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700213 memset(&iwe, 0, sizeof(iwe));
Larry Finger62f27cc2011-08-25 11:48:29 -0500214 if (network->wpa_ie_len) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700215 char buf[MAX_WPA_IE_LEN];
216 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
217 iwe.cmd = IWEVGENIE;
218 iwe.u.data.length = network->wpa_ie_len;
Larry Finger94a79942011-08-23 19:00:42 -0500219 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
Larry Finger62f27cc2011-08-25 11:48:29 -0500220 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700221 memset(&iwe, 0, sizeof(iwe));
Larry Finger62f27cc2011-08-25 11:48:29 -0500222 if (network->rsn_ie_len) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700223 char buf[MAX_WPA_IE_LEN];
224 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
225 iwe.cmd = IWEVGENIE;
226 iwe.u.data.length = network->rsn_ie_len;
Larry Finger94a79942011-08-23 19:00:42 -0500227 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
Larry Finger62f27cc2011-08-25 11:48:29 -0500228 }
Larry Finger94a79942011-08-23 19:00:42 -0500229
Larry Finger94a79942011-08-23 19:00:42 -0500230 /* add info for WZC */
231 memset(&iwe, 0, sizeof(iwe));
Larry Finger62f27cc2011-08-25 11:48:29 -0500232 if (network->wzc_ie_len) {
Larry Finger94a79942011-08-23 19:00:42 -0500233 char buf[MAX_WZC_IE_LEN];
234 memcpy(buf, network->wzc_ie, network->wzc_ie_len);
235 iwe.cmd = IWEVGENIE;
236 iwe.u.data.length = network->wzc_ie_len;
237 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
Larry Finger62f27cc2011-08-25 11:48:29 -0500238 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700239
240 /* Add EXTRA: Age to display seconds since last beacon/probe response
241 * for given network. */
242 iwe.cmd = IWEVCUSTOM;
243 p = custom;
244 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
Larry Finger62f27cc2011-08-25 11:48:29 -0500245 " Last beacon: %lums ago",
246 (jiffies - network->last_scanned) / (HZ / 100));
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700247 iwe.u.data.length = p - custom;
248 if (iwe.u.data.length)
Larry Finger62f27cc2011-08-25 11:48:29 -0500249 start = iwe_stream_add_point_rsl(info, start, stop,
250 &iwe, custom);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700251
252 return start;
253}
254
Larry Finger94a79942011-08-23 19:00:42 -0500255int rtllib_wx_get_scan(struct rtllib_device *ieee,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700256 struct iw_request_info *info,
257 union iwreq_data *wrqu, char *extra)
258{
Larry Finger94a79942011-08-23 19:00:42 -0500259 struct rtllib_network *network;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700260 unsigned long flags;
261
262 char *ev = extra;
Larry Finger94a79942011-08-23 19:00:42 -0500263 char *stop = ev + wrqu->data.length;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700264 int i = 0;
265 int err = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500266 RTLLIB_DEBUG_WX("Getting scan\n");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700267 down(&ieee->wx_sem);
268 spin_lock_irqsave(&ieee->lock, flags);
269
270 list_for_each_entry(network, &ieee->network_list, list) {
271 i++;
Larry Finger62f27cc2011-08-25 11:48:29 -0500272 if ((stop - ev) < 200) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700273 err = -E2BIG;
274 break;
Larry Finger62f27cc2011-08-25 11:48:29 -0500275 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700276 if (ieee->scan_age == 0 ||
277 time_after(network->last_scanned + ieee->scan_age, jiffies))
Larry Finger62f27cc2011-08-25 11:48:29 -0500278 ev = rtl819x_translate_scan(ieee, ev, stop, network,
279 info);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700280 else
Larry Finger62f27cc2011-08-25 11:48:29 -0500281 RTLLIB_DEBUG_SCAN("Not showing network '%s ("
Larry Fingerac50dda2011-08-25 14:07:03 -0500282 " %pM)' due to age (%lums).\n",
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700283 escape_essid(network->ssid,
284 network->ssid_len),
Larry Fingerac50dda2011-08-25 14:07:03 -0500285 network->bssid,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700286 (jiffies - network->last_scanned) / (HZ / 100));
287 }
288
289 spin_unlock_irqrestore(&ieee->lock, flags);
290 up(&ieee->wx_sem);
291 wrqu->data.length = ev - extra;
292 wrqu->data.flags = 0;
293
Larry Finger94a79942011-08-23 19:00:42 -0500294 RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700295
296 return err;
297}
298
Larry Finger94a79942011-08-23 19:00:42 -0500299int rtllib_wx_set_encode(struct rtllib_device *ieee,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700300 struct iw_request_info *info,
301 union iwreq_data *wrqu, char *keybuf)
302{
303 struct iw_point *erq = &(wrqu->encoding);
304 struct net_device *dev = ieee->dev;
Larry Finger94a79942011-08-23 19:00:42 -0500305 struct rtllib_security sec = {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700306 .flags = 0
307 };
308 int i, key, key_provided, len;
Larry Finger94a79942011-08-23 19:00:42 -0500309 struct rtllib_crypt_data **crypt;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700310
Larry Finger94a79942011-08-23 19:00:42 -0500311 RTLLIB_DEBUG_WX("SET_ENCODE\n");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700312
313 key = erq->flags & IW_ENCODE_INDEX;
314 if (key) {
315 if (key > WEP_KEYS)
316 return -EINVAL;
317 key--;
318 key_provided = 1;
319 } else {
320 key_provided = 0;
321 key = ieee->tx_keyidx;
322 }
323
Larry Finger94a79942011-08-23 19:00:42 -0500324 RTLLIB_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700325 "provided" : "default");
326 crypt = &ieee->crypt[key];
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700327 if (erq->flags & IW_ENCODE_DISABLED) {
328 if (key_provided && *crypt) {
Larry Finger94a79942011-08-23 19:00:42 -0500329 RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700330 key);
Larry Finger94a79942011-08-23 19:00:42 -0500331 rtllib_crypt_delayed_deinit(ieee, crypt);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700332 } else
Larry Finger94a79942011-08-23 19:00:42 -0500333 RTLLIB_DEBUG_WX("Disabling encryption.\n");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700334
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 < WEP_KEYS; i++) {
338 if (ieee->crypt[i] != NULL) {
339 if (key_provided)
340 break;
Larry Finger62f27cc2011-08-25 11:48:29 -0500341 rtllib_crypt_delayed_deinit(ieee,
342 &ieee->crypt[i]);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700343 }
344 }
345
346 if (i == WEP_KEYS) {
347 sec.enabled = 0;
348 sec.level = SEC_LEVEL_0;
349 sec.flags |= SEC_ENABLED | SEC_LEVEL;
350 }
351
352 goto done;
353 }
354
355
356
357 sec.enabled = 1;
358 sec.flags |= SEC_ENABLED;
359
360 if (*crypt != NULL && (*crypt)->ops != NULL &&
361 strcmp((*crypt)->ops->name, "WEP") != 0) {
362 /* changing to use WEP; deinit previously used algorithm
363 * on this key */
Larry Finger94a79942011-08-23 19:00:42 -0500364 rtllib_crypt_delayed_deinit(ieee, crypt);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700365 }
366
367 if (*crypt == NULL) {
Larry Finger94a79942011-08-23 19:00:42 -0500368 struct rtllib_crypt_data *new_crypt;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700369
370 /* take WEP into use */
Thomas Meyer929fa2a2011-11-10 19:04:19 +0100371 new_crypt = kzalloc(sizeof(struct rtllib_crypt_data),
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700372 GFP_KERNEL);
373 if (new_crypt == NULL)
374 return -ENOMEM;
Larry Finger94a79942011-08-23 19:00:42 -0500375 new_crypt->ops = rtllib_get_crypto_ops("WEP");
376 if (!new_crypt->ops) {
377 request_module("rtllib_crypt_wep");
378 new_crypt->ops = rtllib_get_crypto_ops("WEP");
379 }
380
Herton Ronaldo Krzesinskia010a332009-10-02 11:03:38 -0300381 if (new_crypt->ops)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700382 new_crypt->priv = new_crypt->ops->init(key);
383
384 if (!new_crypt->ops || !new_crypt->priv) {
385 kfree(new_crypt);
386 new_crypt = NULL;
387
388 printk(KERN_WARNING "%s: could not initialize WEP: "
Larry Finger94a79942011-08-23 19:00:42 -0500389 "load module rtllib_crypt_wep\n",
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700390 dev->name);
391 return -EOPNOTSUPP;
392 }
393 *crypt = new_crypt;
394 }
395
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,
402 len - erq->length);
Larry Finger94a79942011-08-23 19:00:42 -0500403 RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700404 key, escape_essid(sec.keys[key], len),
405 erq->length, len);
406 sec.key_sizes[key] = len;
Larry Finger94a79942011-08-23 19:00:42 -0500407 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700408 (*crypt)->priv);
409 sec.flags |= (1 << key);
410 /* This ensures a key will be activated if no key is
411 * explicitely set */
412 if (key == sec.active_key)
413 sec.flags |= SEC_ACTIVE_KEY;
414 ieee->tx_keyidx = key;
415
416 } else {
417 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
418 NULL, (*crypt)->priv);
419 if (len == 0) {
420 /* Set a default key of all 0 */
Larry Finger62f27cc2011-08-25 11:48:29 -0500421 printk(KERN_INFO "Setting key %d to all zero.\n",
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700422 key);
423
Larry Finger94a79942011-08-23 19:00:42 -0500424 RTLLIB_DEBUG_WX("Setting key %d to all zero.\n",
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700425 key);
426 memset(sec.keys[key], 0, 13);
427 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
428 (*crypt)->priv);
429 sec.key_sizes[key] = 13;
430 sec.flags |= (1 << key);
431 }
432
433 /* No key data - just set the default TX key index */
434 if (key_provided) {
Larry Finger94a79942011-08-23 19:00:42 -0500435 RTLLIB_DEBUG_WX(
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700436 "Setting key %d to default Tx key.\n", key);
437 ieee->tx_keyidx = key;
438 sec.active_key = key;
439 sec.flags |= SEC_ACTIVE_KEY;
440 }
441 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700442 done:
443 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
Larry Finger62f27cc2011-08-25 11:48:29 -0500444 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
445 WLAN_AUTH_SHARED_KEY;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700446 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
447 sec.flags |= SEC_AUTH_MODE;
Larry Finger94a79942011-08-23 19:00:42 -0500448 RTLLIB_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700449 "OPEN" : "SHARED KEY");
450
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 */
455
456 if (ieee->set_security)
Larry Finger94a79942011-08-23 19:00:42 -0500457 ieee->set_security(dev, &sec);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700458
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 &&
Larry Finger94a79942011-08-23 19:00:42 -0500466 ieee->reset_port && ieee->reset_port(dev)) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700467 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
468 return -EINVAL;
469 }
470 return 0;
471}
472
Larry Finger94a79942011-08-23 19:00:42 -0500473int rtllib_wx_get_encode(struct rtllib_device *ieee,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700474 struct iw_request_info *info,
475 union iwreq_data *wrqu, char *keybuf)
476{
477 struct iw_point *erq = &(wrqu->encoding);
478 int len, key;
Larry Finger94a79942011-08-23 19:00:42 -0500479 struct rtllib_crypt_data *crypt;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700480
Larry Finger94a79942011-08-23 19:00:42 -0500481 RTLLIB_DEBUG_WX("GET_ENCODE\n");
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700482
Larry Finger94a79942011-08-23 19:00:42 -0500483 if (ieee->iw_mode == IW_MODE_MONITOR)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700484 return -1;
485
486 key = erq->flags & IW_ENCODE_INDEX;
487 if (key) {
488 if (key > WEP_KEYS)
489 return -EINVAL;
490 key--;
Larry Finger94a79942011-08-23 19:00:42 -0500491 } else {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700492 key = ieee->tx_keyidx;
Larry Finger94a79942011-08-23 19:00:42 -0500493 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700494 crypt = ieee->crypt[key];
Larry Finger94a79942011-08-23 19:00:42 -0500495
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700496 erq->flags = key + 1;
497
498 if (crypt == NULL || crypt->ops == NULL) {
499 erq->length = 0;
500 erq->flags |= IW_ENCODE_DISABLED;
501 return 0;
502 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700503 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
504 erq->length = (len >= 0 ? len : 0);
505
506 erq->flags |= IW_ENCODE_ENABLED;
507
508 if (ieee->open_wep)
509 erq->flags |= IW_ENCODE_OPEN;
510 else
511 erq->flags |= IW_ENCODE_RESTRICTED;
512
513 return 0;
514}
Mike McCormack35917332011-07-11 08:56:03 +0900515
Larry Finger94a79942011-08-23 19:00:42 -0500516int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
Larry Finger62f27cc2011-08-25 11:48:29 -0500517 struct iw_request_info *info,
518 union iwreq_data *wrqu, char *extra)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700519{
520 int ret = 0;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700521 struct net_device *dev = ieee->dev;
Larry Finger62f27cc2011-08-25 11:48:29 -0500522 struct iw_point *encoding = &wrqu->encoding;
523 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
524 int i, idx;
525 int group_key = 0;
526 const char *alg, *module;
527 struct rtllib_crypto_ops *ops;
528 struct rtllib_crypt_data **crypt;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700529
Larry Finger62f27cc2011-08-25 11:48:29 -0500530 struct rtllib_security sec = {
531 .flags = 0,
532 };
533 idx = encoding->flags & IW_ENCODE_INDEX;
534 if (idx) {
535 if (idx < 1 || idx > WEP_KEYS)
536 return -EINVAL;
537 idx--;
Larry Finger94a79942011-08-23 19:00:42 -0500538 } else{
539 idx = ieee->tx_keyidx;
540 }
541 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
542 crypt = &ieee->crypt[idx];
543 group_key = 1;
544 } else {
545 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
546 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
Larry Finger62f27cc2011-08-25 11:48:29 -0500547 return -EINVAL;
Larry Finger94a79942011-08-23 19:00:42 -0500548 if (ieee->iw_mode == IW_MODE_INFRA)
549 crypt = &ieee->crypt[idx];
550 else
551 return -EINVAL;
552 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700553
Larry Finger94a79942011-08-23 19:00:42 -0500554 sec.flags |= SEC_ENABLED;
555 if ((encoding->flags & IW_ENCODE_DISABLED) ||
Larry Finger62f27cc2011-08-25 11:48:29 -0500556 ext->alg == IW_ENCODE_ALG_NONE) {
Larry Finger94a79942011-08-23 19:00:42 -0500557 if (*crypt)
558 rtllib_crypt_delayed_deinit(ieee, crypt);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700559
Larry Finger94a79942011-08-23 19:00:42 -0500560 for (i = 0; i < WEP_KEYS; i++) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700561 if (ieee->crypt[i] != NULL)
Larry Finger94a79942011-08-23 19:00:42 -0500562 break;
563 }
564 if (i == WEP_KEYS) {
565 sec.enabled = 0;
566 sec.level = SEC_LEVEL_0;
567 sec.flags |= SEC_LEVEL;
568 }
569 goto done;
570 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700571
572 sec.enabled = 1;
Larry Finger62f27cc2011-08-25 11:48:29 -0500573 switch (ext->alg) {
574 case IW_ENCODE_ALG_WEP:
575 alg = "WEP";
576 module = "rtllib_crypt_wep";
577 break;
578 case IW_ENCODE_ALG_TKIP:
579 alg = "TKIP";
580 module = "rtllib_crypt_tkip";
581 break;
582 case IW_ENCODE_ALG_CCMP:
583 alg = "CCMP";
584 module = "rtllib_crypt_ccmp";
585 break;
586 default:
587 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
588 dev->name, ext->alg);
589 ret = -EINVAL;
590 goto done;
591 }
592 printk(KERN_INFO "alg name:%s\n", alg);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700593
Larry Finger94a79942011-08-23 19:00:42 -0500594 ops = rtllib_get_crypto_ops(alg);
Larry Finger62f27cc2011-08-25 11:48:29 -0500595 if (ops == NULL) {
596 char tempbuf[100];
Larry Finger94a79942011-08-23 19:00:42 -0500597
Larry Finger62f27cc2011-08-25 11:48:29 -0500598 memset(tempbuf, 0x00, 100);
599 sprintf(tempbuf, "%s", module);
600 request_module("%s", tempbuf);
601 ops = rtllib_get_crypto_ops(alg);
602 }
603 if (ops == NULL) {
604 RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
605 dev->name, ext->alg);
606 printk(KERN_INFO "========>unknown crypto alg %d\n", ext->alg);
607 ret = -EINVAL;
608 goto done;
609 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700610
Larry Finger62f27cc2011-08-25 11:48:29 -0500611 if (*crypt == NULL || (*crypt)->ops != ops) {
612 struct rtllib_crypt_data *new_crypt;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700613
Larry Finger62f27cc2011-08-25 11:48:29 -0500614 rtllib_crypt_delayed_deinit(ieee, crypt);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700615
Larry Finger62f27cc2011-08-25 11:48:29 -0500616 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
617 if (new_crypt == NULL) {
618 ret = -ENOMEM;
619 goto done;
620 }
621 new_crypt->ops = ops;
Larry Finger94a79942011-08-23 19:00:42 -0500622 if (new_crypt->ops)
Larry Finger62f27cc2011-08-25 11:48:29 -0500623 new_crypt->priv = new_crypt->ops->init(idx);
Larry Finger94a79942011-08-23 19:00:42 -0500624
Larry Finger62f27cc2011-08-25 11:48:29 -0500625 if (new_crypt->priv == NULL) {
626 kfree(new_crypt);
627 ret = -EINVAL;
628 goto done;
629 }
630 *crypt = new_crypt;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700631
Larry Finger94a79942011-08-23 19:00:42 -0500632 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700633
Larry Finger62f27cc2011-08-25 11:48:29 -0500634 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
635 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
636 (*crypt)->priv) < 0) {
637 RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name);
638 printk(KERN_INFO "key setting failed\n");
639 ret = -EINVAL;
640 goto done;
641 }
642 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
643 ieee->tx_keyidx = idx;
644 sec.active_key = idx;
645 sec.flags |= SEC_ACTIVE_KEY;
646 }
647 if (ext->alg != IW_ENCODE_ALG_NONE) {
648 sec.key_sizes[idx] = ext->key_len;
649 sec.flags |= (1 << idx);
650 if (ext->alg == IW_ENCODE_ALG_WEP) {
651 sec.flags |= SEC_LEVEL;
652 sec.level = SEC_LEVEL_1;
653 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
654 sec.flags |= SEC_LEVEL;
655 sec.level = SEC_LEVEL_2;
656 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
657 sec.flags |= SEC_LEVEL;
658 sec.level = SEC_LEVEL_3;
659 }
660 /* Don't set sec level for group keys. */
661 if (group_key)
662 sec.flags &= ~SEC_LEVEL;
663 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700664done:
Larry Finger62f27cc2011-08-25 11:48:29 -0500665 if (ieee->set_security)
666 ieee->set_security(ieee->dev, &sec);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700667
668 if (ieee->reset_on_keychange &&
Larry Finger62f27cc2011-08-25 11:48:29 -0500669 ieee->iw_mode != IW_MODE_INFRA &&
670 ieee->reset_port && ieee->reset_port(dev)) {
671 RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name);
672 return -EINVAL;
673 }
674 return ret;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700675}
676
Larry Finger94a79942011-08-23 19:00:42 -0500677int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700678 struct iw_request_info *info,
679 union iwreq_data *wrqu, char *extra)
680{
681 struct iw_point *encoding = &wrqu->encoding;
682 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
Larry Finger94a79942011-08-23 19:00:42 -0500683 struct rtllib_crypt_data *crypt;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700684 int idx, max_key_len;
685
686 max_key_len = encoding->length - sizeof(*ext);
687 if (max_key_len < 0)
688 return -EINVAL;
689
690 idx = encoding->flags & IW_ENCODE_INDEX;
691 if (idx) {
692 if (idx < 1 || idx > WEP_KEYS)
693 return -EINVAL;
694 idx--;
Larry Finger94a79942011-08-23 19:00:42 -0500695 } else {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700696 idx = ieee->tx_keyidx;
Larry Finger94a79942011-08-23 19:00:42 -0500697 }
Greg Kroah-Hartman3ef5a262009-08-20 06:14:22 -0700698 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
Larry Finger94a79942011-08-23 19:00:42 -0500699 (ext->alg != IW_ENCODE_ALG_WEP))
700 if (idx != 0 || (ieee->iw_mode != IW_MODE_INFRA))
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700701 return -EINVAL;
702
703 crypt = ieee->crypt[idx];
Larry Finger94a79942011-08-23 19:00:42 -0500704
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700705 encoding->flags = idx + 1;
706 memset(ext, 0, sizeof(*ext));
707
Larry Finger62f27cc2011-08-25 11:48:29 -0500708 if (crypt == NULL || crypt->ops == NULL) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700709 ext->alg = IW_ENCODE_ALG_NONE;
710 ext->key_len = 0;
711 encoding->flags |= IW_ENCODE_DISABLED;
712 } else {
Larry Finger62f27cc2011-08-25 11:48:29 -0500713 if (strcmp(crypt->ops->name, "WEP") == 0)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700714 ext->alg = IW_ENCODE_ALG_WEP;
715 else if (strcmp(crypt->ops->name, "TKIP"))
716 ext->alg = IW_ENCODE_ALG_TKIP;
717 else if (strcmp(crypt->ops->name, "CCMP"))
718 ext->alg = IW_ENCODE_ALG_CCMP;
719 else
720 return -EINVAL;
Larry Finger62f27cc2011-08-25 11:48:29 -0500721 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN,
722 NULL, crypt->priv);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700723 encoding->flags |= IW_ENCODE_ENABLED;
724 if (ext->key_len &&
725 (ext->alg == IW_ENCODE_ALG_TKIP ||
726 ext->alg == IW_ENCODE_ALG_CCMP))
727 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
728
729 }
730
731 return 0;
732}
733
Larry Finger94a79942011-08-23 19:00:42 -0500734int rtllib_wx_set_mlme(struct rtllib_device *ieee,
Larry Finger62f27cc2011-08-25 11:48:29 -0500735 struct iw_request_info *info,
736 union iwreq_data *wrqu, char *extra)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700737{
Larry Finger94a79942011-08-23 19:00:42 -0500738 u8 i = 0;
739 bool deauth = false;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700740 struct iw_mlme *mlme = (struct iw_mlme *) extra;
Larry Finger94a79942011-08-23 19:00:42 -0500741
742 if (ieee->state != RTLLIB_LINKED)
743 return -ENOLINK;
744
745 down(&ieee->wx_sem);
746
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700747 switch (mlme->cmd) {
Larry Finger62f27cc2011-08-25 11:48:29 -0500748 case IW_MLME_DEAUTH:
749 deauth = true;
750 /* leave break out intentionly */
Larry Finger94a79942011-08-23 19:00:42 -0500751
Larry Finger62f27cc2011-08-25 11:48:29 -0500752 case IW_MLME_DISASSOC:
753 if (deauth == true)
754 printk(KERN_INFO "disauth packet !\n");
755 else
756 printk(KERN_INFO "dis associate packet!\n");
Larry Finger94a79942011-08-23 19:00:42 -0500757
Larry Finger62f27cc2011-08-25 11:48:29 -0500758 ieee->cannot_notify = true;
Larry Finger94a79942011-08-23 19:00:42 -0500759
Larry Finger62f27cc2011-08-25 11:48:29 -0500760 SendDisassociation(ieee, deauth, mlme->reason_code);
761 rtllib_disassociate(ieee);
Larry Finger94a79942011-08-23 19:00:42 -0500762
Larry Finger62f27cc2011-08-25 11:48:29 -0500763 ieee->wap_set = 0;
764 for (i = 0; i < 6; i++)
765 ieee->current_network.bssid[i] = 0x55;
Larry Finger94a79942011-08-23 19:00:42 -0500766
Larry Finger62f27cc2011-08-25 11:48:29 -0500767 ieee->ssid_set = 0;
768 ieee->current_network.ssid[0] = '\0';
769 ieee->current_network.ssid_len = 0;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700770 break;
Larry Finger94a79942011-08-23 19:00:42 -0500771 default:
772 up(&ieee->wx_sem);
773 return -EOPNOTSUPP;
774 }
775
776 up(&ieee->wx_sem);
777
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700778 return 0;
779}
780
Larry Finger94a79942011-08-23 19:00:42 -0500781int rtllib_wx_set_auth(struct rtllib_device *ieee,
Larry Finger62f27cc2011-08-25 11:48:29 -0500782 struct iw_request_info *info,
783 struct iw_param *data, char *extra)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700784{
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700785 switch (data->flags & IW_AUTH_INDEX) {
Larry Finger62f27cc2011-08-25 11:48:29 -0500786 case IW_AUTH_WPA_VERSION:
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700787 break;
Larry Finger62f27cc2011-08-25 11:48:29 -0500788 case IW_AUTH_CIPHER_PAIRWISE:
789 case IW_AUTH_CIPHER_GROUP:
790 case IW_AUTH_KEY_MGMT:
Larry Finger94a79942011-08-23 19:00:42 -0500791 /*
792 * Host AP driver does not use these parameters and allows
793 * wpa_supplicant to control them internally.
794 */
Larry Finger62f27cc2011-08-25 11:48:29 -0500795 break;
796 case IW_AUTH_TKIP_COUNTERMEASURES:
797 ieee->tkip_countermeasures = data->value;
798 break;
799 case IW_AUTH_DROP_UNENCRYPTED:
800 ieee->drop_unencrypted = data->value;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700801 break;
802
803 case IW_AUTH_80211_AUTH_ALG:
Larry Finger62f27cc2011-08-25 11:48:29 -0500804 if (data->value & IW_AUTH_ALG_SHARED_KEY) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700805 ieee->open_wep = 0;
806 ieee->auth_mode = 1;
Larry Finger62f27cc2011-08-25 11:48:29 -0500807 } else if (data->value & IW_AUTH_ALG_OPEN_SYSTEM) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700808 ieee->open_wep = 1;
809 ieee->auth_mode = 0;
Larry Finger62f27cc2011-08-25 11:48:29 -0500810 } else if (data->value & IW_AUTH_ALG_LEAP) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700811 ieee->open_wep = 1;
812 ieee->auth_mode = 2;
Larry Finger62f27cc2011-08-25 11:48:29 -0500813 } else
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700814 return -EINVAL;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700815 break;
816
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700817 case IW_AUTH_WPA_ENABLED:
Larry Finger62f27cc2011-08-25 11:48:29 -0500818 ieee->wpa_enabled = (data->value) ? 1 : 0;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700819 break;
820
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700821 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
Larry Finger62f27cc2011-08-25 11:48:29 -0500822 ieee->ieee802_1x = data->value;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700823 break;
824 case IW_AUTH_PRIVACY_INVOKED:
825 ieee->privacy_invoked = data->value;
826 break;
827 default:
Larry Finger62f27cc2011-08-25 11:48:29 -0500828 return -EOPNOTSUPP;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700829 }
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700830 return 0;
831}
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700832
Larry Finger94a79942011-08-23 19:00:42 -0500833int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
834{
Larry Finger94a79942011-08-23 19:00:42 -0500835 u8 *buf;
Larry Finger62f27cc2011-08-25 11:48:29 -0500836 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
Larry Finger94a79942011-08-23 19:00:42 -0500837
Larry Finger62f27cc2011-08-25 11:48:29 -0500838 if (len > MAX_WPA_IE_LEN || (len && ie == NULL))
Larry Finger94a79942011-08-23 19:00:42 -0500839 return -EINVAL;
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700840
Larry Finger94a79942011-08-23 19:00:42 -0500841 if (len) {
842 eid = ie[0];
Larry Finger62f27cc2011-08-25 11:48:29 -0500843 if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2],
844 wps_oui, 4))) {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700845
Larry Finger62f27cc2011-08-25 11:48:29 -0500846 ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len) :
847 (MAX_WZC_IE_LEN);
Larry Finger94a79942011-08-23 19:00:42 -0500848 buf = kmalloc(ieee->wps_ie_len, GFP_KERNEL);
849 if (buf == NULL)
850 return -ENOMEM;
851 memcpy(buf, ie, ieee->wps_ie_len);
852 ieee->wps_ie = buf;
853 return 0;
854 }
855 }
856 ieee->wps_ie_len = 0;
Larry Finger62f27cc2011-08-25 11:48:29 -0500857 kfree(ieee->wps_ie);
Larry Finger94a79942011-08-23 19:00:42 -0500858 ieee->wps_ie = NULL;
859 if (len) {
Larry Finger62f27cc2011-08-25 11:48:29 -0500860 if (len != ie[1]+2)
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700861 return -EINVAL;
Larry Finger94a79942011-08-23 19:00:42 -0500862 buf = kmalloc(len, GFP_KERNEL);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700863 if (buf == NULL)
864 return -ENOMEM;
Larry Finger94a79942011-08-23 19:00:42 -0500865 memcpy(buf, ie, len);
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700866 kfree(ieee->wpa_ie);
867 ieee->wpa_ie = buf;
868 ieee->wpa_ie_len = len;
Larry Finger94a79942011-08-23 19:00:42 -0500869 } else {
Greg Kroah-Hartmanecdfa442009-08-04 15:57:55 -0700870 kfree(ieee->wpa_ie);
871 ieee->wpa_ie = NULL;
872 ieee->wpa_ie_len = 0;
873 }
Larry Finger94a79942011-08-23 19:00:42 -0500874 return 0;
875}