These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / rtl8192e / rtllib_wx.c
1 /******************************************************************************
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   The full GNU General Public License is included in this distribution in the
21   file called LICENSE.
22
23   Contact Information:
24   James P. Ketrenos <ipw2100-admin@linux.intel.com>
25   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26
27 ******************************************************************************/
28 #include <linux/wireless.h>
29 #include <linux/kmod.h>
30 #include <linux/module.h>
31 #include <linux/etherdevice.h>
32 #include "rtllib.h"
33 struct modes_unit {
34         char *mode_string;
35         int mode_size;
36 };
37 static struct modes_unit rtllib_modes[] = {
38         {"a", 1},
39         {"b", 1},
40         {"g", 1},
41         {"?", 1},
42         {"N-24G", 5},
43         {"N-5G", 4},
44 };
45
46 #define MAX_CUSTOM_LEN 64
47 static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
48                                            char *start, char *stop,
49                                            struct rtllib_network *network,
50                                            struct iw_request_info *info)
51 {
52         char custom[MAX_CUSTOM_LEN];
53         char proto_name[IFNAMSIZ];
54         char *pname = proto_name;
55         char *p;
56         struct iw_event iwe;
57         int i, j;
58         u16 max_rate, rate;
59         static u8       EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
60
61         /* First entry *MUST* be the AP MAC address */
62         iwe.cmd = SIOCGIWAP;
63         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
64         ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid);
65         start = iwe_stream_add_event_rsl(info, start, stop,
66                                          &iwe, IW_EV_ADDR_LEN);
67         /* Remaining entries will be displayed in the order we provide them */
68
69         /* Add the ESSID */
70         iwe.cmd = SIOCGIWESSID;
71         iwe.u.data.flags = 1;
72         if (network->ssid_len > 0) {
73                 iwe.u.data.length = min_t(u8, network->ssid_len, 32);
74                 start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
75                                                  network->ssid);
76         } else if (network->hidden_ssid_len == 0) {
77                 iwe.u.data.length = sizeof("<hidden>");
78                 start = iwe_stream_add_point_rsl(info, start, stop,
79                                                  &iwe, "<hidden>");
80         } else {
81                 iwe.u.data.length = min_t(u8, network->hidden_ssid_len, 32);
82                 start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
83                                                  network->hidden_ssid);
84         }
85         /* Add the protocol name */
86         iwe.cmd = SIOCGIWNAME;
87         for (i = 0; i < ARRAY_SIZE(rtllib_modes); i++) {
88                 if (network->mode&(1<<i)) {
89                         sprintf(pname, rtllib_modes[i].mode_string,
90                                 rtllib_modes[i].mode_size);
91                         pname += rtllib_modes[i].mode_size;
92                 }
93         }
94         *pname = '\0';
95         snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
96         start = iwe_stream_add_event_rsl(info, start, stop,
97                                          &iwe, IW_EV_CHAR_LEN);
98         /* Add mode */
99         iwe.cmd = SIOCGIWMODE;
100         if (network->capability &
101             (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
102                 if (network->capability & WLAN_CAPABILITY_ESS)
103                         iwe.u.mode = IW_MODE_MASTER;
104                 else
105                         iwe.u.mode = IW_MODE_ADHOC;
106                 start = iwe_stream_add_event_rsl(info, start, stop,
107                                                  &iwe, IW_EV_UINT_LEN);
108         }
109
110         /* Add frequency/channel */
111         iwe.cmd = SIOCGIWFREQ;
112         iwe.u.freq.m = network->channel;
113         iwe.u.freq.e = 0;
114         iwe.u.freq.i = 0;
115         start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
116                                          IW_EV_FREQ_LEN);
117
118         /* Add encryption capability */
119         iwe.cmd = SIOCGIWENCODE;
120         if (network->capability & WLAN_CAPABILITY_PRIVACY)
121                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
122         else
123                 iwe.u.data.flags = IW_ENCODE_DISABLED;
124         iwe.u.data.length = 0;
125         start = iwe_stream_add_point_rsl(info, start, stop,
126                                          &iwe, network->ssid);
127         /* Add basic and extended rates */
128         max_rate = 0;
129         p = custom;
130         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
131         for (i = 0, j = 0; i < network->rates_len;) {
132                 if (j < network->rates_ex_len &&
133                     ((network->rates_ex[j] & 0x7F) <
134                      (network->rates[i] & 0x7F)))
135                         rate = network->rates_ex[j++] & 0x7F;
136                 else
137                         rate = network->rates[i++] & 0x7F;
138                 if (rate > max_rate)
139                         max_rate = rate;
140                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
141                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
142         }
143         for (; j < network->rates_ex_len; j++) {
144                 rate = network->rates_ex[j] & 0x7F;
145                 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
146                               "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
147                 if (rate > max_rate)
148                         max_rate = rate;
149         }
150
151         if (network->mode >= IEEE_N_24G) {
152                 struct ht_capab_ele *ht_cap = NULL;
153                 bool is40M = false, isShortGI = false;
154                 u8 max_mcs = 0;
155
156                 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
157                         ht_cap = (struct ht_capab_ele *)
158                                  &network->bssht.bdHTCapBuf[4];
159                 else
160                         ht_cap = (struct ht_capab_ele *)
161                                  &network->bssht.bdHTCapBuf[0];
162                 is40M = (ht_cap->ChlWidth) ? 1 : 0;
163                 isShortGI = (ht_cap->ChlWidth) ?
164                                 ((ht_cap->ShortGI40Mhz) ? 1 : 0) :
165                                 ((ht_cap->ShortGI20Mhz) ? 1 : 0);
166
167                 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS,
168                                               MCS_FILTER_ALL);
169                 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f];
170                 if (rate > max_rate)
171                         max_rate = rate;
172         }
173         iwe.cmd = SIOCGIWRATE;
174         iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
175         iwe.u.bitrate.value = max_rate * 500000;
176         start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
177                                      IW_EV_PARAM_LEN);
178         iwe.cmd = IWEVCUSTOM;
179         iwe.u.data.length = p - custom;
180         if (iwe.u.data.length)
181                 start = iwe_stream_add_point_rsl(info, start, stop,
182                                                  &iwe, custom);
183         /* Add quality statistics */
184         /* TODO: Fix these values... */
185         iwe.cmd = IWEVQUAL;
186         iwe.u.qual.qual = network->stats.signal;
187         iwe.u.qual.level = network->stats.rssi;
188         iwe.u.qual.noise = network->stats.noise;
189         iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK;
190         if (!(network->stats.mask & RTLLIB_STATMASK_RSSI))
191                 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
192         if (!(network->stats.mask & RTLLIB_STATMASK_NOISE))
193                 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
194         if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL))
195                 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
196         iwe.u.qual.updated = 7;
197         start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
198                                          IW_EV_QUAL_LEN);
199
200         iwe.cmd = IWEVCUSTOM;
201         p = custom;
202         iwe.u.data.length = p - custom;
203         if (iwe.u.data.length)
204                 start = iwe_stream_add_point_rsl(info, start, stop,
205                                                  &iwe, custom);
206
207         memset(&iwe, 0, sizeof(iwe));
208         if (network->wpa_ie_len) {
209                 char buf[MAX_WPA_IE_LEN];
210
211                 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
212                 iwe.cmd = IWEVGENIE;
213                 iwe.u.data.length = network->wpa_ie_len;
214                 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
215         }
216         memset(&iwe, 0, sizeof(iwe));
217         if (network->rsn_ie_len) {
218                 char buf[MAX_WPA_IE_LEN];
219
220                 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
221                 iwe.cmd = IWEVGENIE;
222                 iwe.u.data.length = network->rsn_ie_len;
223                 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
224         }
225
226         /* add info for WZC */
227         memset(&iwe, 0, sizeof(iwe));
228         if (network->wzc_ie_len) {
229                 char buf[MAX_WZC_IE_LEN];
230
231                 memcpy(buf, network->wzc_ie, network->wzc_ie_len);
232                 iwe.cmd = IWEVGENIE;
233                 iwe.u.data.length = network->wzc_ie_len;
234                 start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
235         }
236
237         /* Add EXTRA: Age to display seconds since last beacon/probe response
238          * for given network.
239          */
240         iwe.cmd = IWEVCUSTOM;
241         p = custom;
242         p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
243                       " Last beacon: %lums ago",
244                       (jiffies - network->last_scanned) / (HZ / 100));
245         iwe.u.data.length = p - custom;
246         if (iwe.u.data.length)
247                 start = iwe_stream_add_point_rsl(info, start, stop,
248                                                  &iwe, custom);
249
250         return start;
251 }
252
253 int rtllib_wx_get_scan(struct rtllib_device *ieee,
254                           struct iw_request_info *info,
255                           union iwreq_data *wrqu, char *extra)
256 {
257         struct rtllib_network *network;
258         unsigned long flags;
259
260         char *ev = extra;
261         char *stop = ev + wrqu->data.length;
262         int i = 0;
263         int err = 0;
264
265         netdev_dbg(ieee->dev, "Getting scan\n");
266         down(&ieee->wx_sem);
267         spin_lock_irqsave(&ieee->lock, flags);
268
269         list_for_each_entry(network, &ieee->network_list, list) {
270                 i++;
271                 if ((stop - ev) < 200) {
272                         err = -E2BIG;
273                         break;
274                 }
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,
278                                                     info);
279                 else
280                         netdev_dbg(ieee->dev,
281                                    "Network '%s ( %pM)' hidden due to age (%lums).\n",
282                                    escape_essid(network->ssid,
283                                                 network->ssid_len),
284                                    network->bssid,
285                                    (jiffies - network->last_scanned) /
286                                    (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
294         netdev_dbg(ieee->dev, "%s(): %d networks returned.\n", __func__, i);
295
296         return err;
297 }
298 EXPORT_SYMBOL(rtllib_wx_get_scan);
299
300 int rtllib_wx_set_encode(struct rtllib_device *ieee,
301                             struct iw_request_info *info,
302                             union iwreq_data *wrqu, char *keybuf)
303 {
304         struct iw_point *erq = &(wrqu->encoding);
305         struct net_device *dev = ieee->dev;
306         struct rtllib_security sec = {
307                 .flags = 0
308         };
309         int i, key, key_provided, len;
310         struct lib80211_crypt_data **crypt;
311
312         netdev_dbg(ieee->dev, "%s()\n", __func__);
313
314         key = erq->flags & IW_ENCODE_INDEX;
315         if (key) {
316                 if (key > NUM_WEP_KEYS)
317                         return -EINVAL;
318                 key--;
319                 key_provided = 1;
320         } else {
321                 key_provided = 0;
322                 key = ieee->crypt_info.tx_keyidx;
323         }
324
325         netdev_dbg(ieee->dev, "Key: %d [%s]\n", key, key_provided ?
326                            "provided" : "default");
327         crypt = &ieee->crypt_info.crypt[key];
328         if (erq->flags & IW_ENCODE_DISABLED) {
329                 if (key_provided && *crypt) {
330                         netdev_dbg(ieee->dev,
331                                    "Disabling encryption on key %d.\n", key);
332                         lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
333                 } else
334                         netdev_dbg(ieee->dev, "Disabling encryption.\n");
335
336                 /* Check all the keys to see if any are still configured,
337                  * and if no key index was provided, de-init them all
338                  */
339                 for (i = 0; i < NUM_WEP_KEYS; i++) {
340                         if (ieee->crypt_info.crypt[i] != NULL) {
341                                 if (key_provided)
342                                         break;
343                                 lib80211_crypt_delayed_deinit(&ieee->crypt_info,
344                                                     &ieee->crypt_info.crypt[i]);
345                         }
346                 }
347
348                 if (i == NUM_WEP_KEYS) {
349                         sec.enabled = 0;
350                         sec.level = SEC_LEVEL_0;
351                         sec.flags |= SEC_ENABLED | SEC_LEVEL;
352                 }
353
354                 goto done;
355         }
356
357
358
359         sec.enabled = 1;
360         sec.flags |= SEC_ENABLED;
361
362         if (*crypt != NULL && (*crypt)->ops != NULL &&
363             strcmp((*crypt)->ops->name, "R-WEP") != 0) {
364                 /* changing to use WEP; deinit previously used algorithm
365                  * on this key
366                  */
367                 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
368         }
369
370         if (*crypt == NULL) {
371                 struct lib80211_crypt_data *new_crypt;
372
373                 /* take WEP into use */
374                 new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
375                                     GFP_KERNEL);
376                 if (new_crypt == NULL)
377                         return -ENOMEM;
378                 new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
379                 if (!new_crypt->ops) {
380                         request_module("rtllib_crypt_wep");
381                         new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
382                 }
383
384                 if (new_crypt->ops)
385                         new_crypt->priv = new_crypt->ops->init(key);
386
387                 if (!new_crypt->ops || !new_crypt->priv) {
388                         kfree(new_crypt);
389                         new_crypt = NULL;
390
391                         netdev_warn(dev,
392                                     "%s: could not initialize WEP: load module rtllib_crypt_wep\n",
393                                     dev->name);
394                         return -EOPNOTSUPP;
395                 }
396                 *crypt = new_crypt;
397         }
398
399         /* If a new key was provided, set it up */
400         if (erq->length > 0) {
401                 len = erq->length <= 5 ? 5 : 13;
402                 memcpy(sec.keys[key], keybuf, erq->length);
403                 if (len > erq->length)
404                         memset(sec.keys[key] + erq->length, 0,
405                                len - erq->length);
406                 netdev_dbg(ieee->dev, "Setting key %d to '%s' (%d:%d bytes)\n",
407                            key, escape_essid(sec.keys[key], len), erq->length,
408                            len);
409                 sec.key_sizes[key] = len;
410                 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
411                                        (*crypt)->priv);
412                 sec.flags |= (1 << key);
413                 /* This ensures a key will be activated if no key is
414                  * explicitly set
415                  */
416                 if (key == sec.active_key)
417                         sec.flags |= SEC_ACTIVE_KEY;
418                 ieee->crypt_info.tx_keyidx = key;
419
420         } else {
421                 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
422                                              NULL, (*crypt)->priv);
423                 if (len == 0) {
424                         /* Set a default key of all 0 */
425                         netdev_info(ieee->dev, "Setting key %d to all zero.\n",
426                                            key);
427
428                         memset(sec.keys[key], 0, 13);
429                         (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
430                                                (*crypt)->priv);
431                         sec.key_sizes[key] = 13;
432                         sec.flags |= (1 << key);
433                 }
434
435                 /* No key data - just set the default TX key index */
436                 if (key_provided) {
437                         netdev_dbg(ieee->dev,
438                                    "Setting key %d as default Tx key.\n", key);
439                         ieee->crypt_info.tx_keyidx = key;
440                         sec.active_key = key;
441                         sec.flags |= SEC_ACTIVE_KEY;
442                 }
443         }
444  done:
445         ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
446         ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
447                           WLAN_AUTH_SHARED_KEY;
448         sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
449         sec.flags |= SEC_AUTH_MODE;
450         netdev_dbg(ieee->dev, "Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
451                            "OPEN" : "SHARED KEY");
452
453         /* For now we just support WEP, so only set that security level...
454          * TODO: When WPA is added this is one place that needs to change
455          */
456         sec.flags |= SEC_LEVEL;
457         sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
458
459         if (ieee->set_security)
460                 ieee->set_security(dev, &sec);
461
462         /* Do not reset port if card is in Managed mode since resetting will
463          * generate new IEEE 802.11 authentication which may end up in looping
464          * with IEEE 802.1X.  If your hardware requires a reset after WEP
465          * configuration (for example... Prism2), implement the reset_port in
466          * the callbacks structures used to initialize the 802.11 stack.
467          */
468         if (ieee->reset_on_keychange &&
469             ieee->iw_mode != IW_MODE_INFRA &&
470             ieee->reset_port && ieee->reset_port(dev)) {
471                 netdev_dbg(dev, "%s: reset_port failed\n", dev->name);
472                 return -EINVAL;
473         }
474         return 0;
475 }
476 EXPORT_SYMBOL(rtllib_wx_set_encode);
477
478 int rtllib_wx_get_encode(struct rtllib_device *ieee,
479                             struct iw_request_info *info,
480                             union iwreq_data *wrqu, char *keybuf)
481 {
482         struct iw_point *erq = &(wrqu->encoding);
483         int len, key;
484         struct lib80211_crypt_data *crypt;
485
486         netdev_dbg(ieee->dev, "%s()\n", __func__);
487
488         if (ieee->iw_mode == IW_MODE_MONITOR)
489                 return -1;
490
491         key = erq->flags & IW_ENCODE_INDEX;
492         if (key) {
493                 if (key > NUM_WEP_KEYS)
494                         return -EINVAL;
495                 key--;
496         } else {
497                 key = ieee->crypt_info.tx_keyidx;
498         }
499         crypt = ieee->crypt_info.crypt[key];
500
501         erq->flags = key + 1;
502
503         if (crypt == NULL || crypt->ops == NULL) {
504                 erq->length = 0;
505                 erq->flags |= IW_ENCODE_DISABLED;
506                 return 0;
507         }
508         len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
509
510         erq->length = max(len, 0);
511
512         erq->flags |= IW_ENCODE_ENABLED;
513
514         if (ieee->open_wep)
515                 erq->flags |= IW_ENCODE_OPEN;
516         else
517                 erq->flags |= IW_ENCODE_RESTRICTED;
518
519         return 0;
520 }
521 EXPORT_SYMBOL(rtllib_wx_get_encode);
522
523 int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
524                                struct iw_request_info *info,
525                                union iwreq_data *wrqu, char *extra)
526 {
527         int ret = 0;
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;
531         int i, idx;
532         int group_key = 0;
533         const char *alg, *module;
534         struct lib80211_crypto_ops *ops;
535         struct lib80211_crypt_data **crypt;
536
537         struct rtllib_security sec = {
538                 .flags = 0,
539         };
540         idx = encoding->flags & IW_ENCODE_INDEX;
541         if (idx) {
542                 if (idx < 1 || idx > NUM_WEP_KEYS)
543                         return -EINVAL;
544                 idx--;
545         } else{
546                         idx = ieee->crypt_info.tx_keyidx;
547         }
548         if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
549                 crypt = &ieee->crypt_info.crypt[idx];
550                 group_key = 1;
551         } else {
552                 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
553                 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
554                         return -EINVAL;
555                 if (ieee->iw_mode == IW_MODE_INFRA)
556                         crypt = &ieee->crypt_info.crypt[idx];
557                 else
558                         return -EINVAL;
559         }
560
561         sec.flags |= SEC_ENABLED;
562         if ((encoding->flags & IW_ENCODE_DISABLED) ||
563             ext->alg == IW_ENCODE_ALG_NONE) {
564                 if (*crypt)
565                         lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
566
567                 for (i = 0; i < NUM_WEP_KEYS; i++) {
568                         if (ieee->crypt_info.crypt[i] != NULL)
569                                 break;
570                 }
571                 if (i == NUM_WEP_KEYS) {
572                         sec.enabled = 0;
573                         sec.level = SEC_LEVEL_0;
574                         sec.flags |= SEC_LEVEL;
575                 }
576                 goto done;
577         }
578
579         sec.enabled = 1;
580         switch (ext->alg) {
581         case IW_ENCODE_ALG_WEP:
582                 alg = "R-WEP";
583                 module = "rtllib_crypt_wep";
584                 break;
585         case IW_ENCODE_ALG_TKIP:
586                 alg = "R-TKIP";
587                 module = "rtllib_crypt_tkip";
588                 break;
589         case IW_ENCODE_ALG_CCMP:
590                 alg = "R-CCMP";
591                 module = "rtllib_crypt_ccmp";
592                 break;
593         default:
594                 netdev_dbg(ieee->dev, "Unknown crypto alg %d\n", ext->alg);
595                 ret = -EINVAL;
596                 goto done;
597         }
598         netdev_info(dev, "alg name:%s\n", alg);
599
600         ops = lib80211_get_crypto_ops(alg);
601         if (ops == NULL) {
602                 char tempbuf[100];
603
604                 memset(tempbuf, 0x00, 100);
605                 sprintf(tempbuf, "%s", module);
606                 request_module("%s", tempbuf);
607                 ops = lib80211_get_crypto_ops(alg);
608         }
609         if (ops == NULL) {
610                 netdev_info(dev, "========>unknown crypto alg %d\n", ext->alg);
611                 ret = -EINVAL;
612                 goto done;
613         }
614
615         if (*crypt == NULL || (*crypt)->ops != ops) {
616                 struct lib80211_crypt_data *new_crypt;
617
618                 lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
619
620                 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
621                 if (new_crypt == NULL) {
622                         ret = -ENOMEM;
623                         goto done;
624                 }
625                 new_crypt->ops = ops;
626                 if (new_crypt->ops)
627                         new_crypt->priv = new_crypt->ops->init(idx);
628
629                 if (new_crypt->priv == NULL) {
630                         kfree(new_crypt);
631                         ret = -EINVAL;
632                         goto done;
633                 }
634                 *crypt = new_crypt;
635
636         }
637
638         if (ext->key_len > 0 && (*crypt)->ops->set_key &&
639             (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
640                                    (*crypt)->priv) < 0) {
641                 netdev_info(dev, "key setting failed\n");
642                 ret = -EINVAL;
643                 goto done;
644         }
645         if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
646                 ieee->crypt_info.tx_keyidx = idx;
647                 sec.active_key = idx;
648                 sec.flags |= SEC_ACTIVE_KEY;
649         }
650         if (ext->alg != IW_ENCODE_ALG_NONE) {
651                 sec.key_sizes[idx] = ext->key_len;
652                 sec.flags |= (1 << idx);
653                 if (ext->alg == IW_ENCODE_ALG_WEP) {
654                         sec.flags |= SEC_LEVEL;
655                         sec.level = SEC_LEVEL_1;
656                 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
657                         sec.flags |= SEC_LEVEL;
658                         sec.level = SEC_LEVEL_2;
659                 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
660                         sec.flags |= SEC_LEVEL;
661                         sec.level = SEC_LEVEL_3;
662                 }
663                 /* Don't set sec level for group keys. */
664                 if (group_key)
665                         sec.flags &= ~SEC_LEVEL;
666         }
667 done:
668         if (ieee->set_security)
669                 ieee->set_security(ieee->dev, &sec);
670
671          if (ieee->reset_on_keychange &&
672             ieee->iw_mode != IW_MODE_INFRA &&
673             ieee->reset_port && ieee->reset_port(dev)) {
674                 netdev_dbg(ieee->dev, "Port reset failed\n");
675                 return -EINVAL;
676         }
677         return ret;
678 }
679 EXPORT_SYMBOL(rtllib_wx_set_encode_ext);
680
681 int rtllib_wx_set_mlme(struct rtllib_device *ieee,
682                                struct iw_request_info *info,
683                                union iwreq_data *wrqu, char *extra)
684 {
685         u8 i = 0;
686         bool deauth = false;
687         struct iw_mlme *mlme = (struct iw_mlme *) extra;
688
689         if (ieee->state != RTLLIB_LINKED)
690                 return -ENOLINK;
691
692         down(&ieee->wx_sem);
693
694         switch (mlme->cmd) {
695         case IW_MLME_DEAUTH:
696                 deauth = true;
697                 /* leave break out intentionly */
698
699         case IW_MLME_DISASSOC:
700                 if (deauth)
701                         netdev_info(ieee->dev, "disauth packet !\n");
702                 else
703                         netdev_info(ieee->dev, "dis associate packet!\n");
704
705                 ieee->cannot_notify = true;
706
707                 SendDisassociation(ieee, deauth, mlme->reason_code);
708                 rtllib_disassociate(ieee);
709
710                 ieee->wap_set = 0;
711                 for (i = 0; i < 6; i++)
712                         ieee->current_network.bssid[i] = 0x55;
713
714                 ieee->ssid_set = 0;
715                 ieee->current_network.ssid[0] = '\0';
716                 ieee->current_network.ssid_len = 0;
717                 break;
718         default:
719                 up(&ieee->wx_sem);
720                 return -EOPNOTSUPP;
721         }
722
723         up(&ieee->wx_sem);
724
725         return 0;
726 }
727 EXPORT_SYMBOL(rtllib_wx_set_mlme);
728
729 int rtllib_wx_set_auth(struct rtllib_device *ieee,
730                                struct iw_request_info *info,
731                                struct iw_param *data, char *extra)
732 {
733         switch (data->flags & IW_AUTH_INDEX) {
734         case IW_AUTH_WPA_VERSION:
735                 break;
736         case IW_AUTH_CIPHER_PAIRWISE:
737         case IW_AUTH_CIPHER_GROUP:
738         case IW_AUTH_KEY_MGMT:
739                 /* Host AP driver does not use these parameters and allows
740                  * wpa_supplicant to control them internally.
741                  */
742                 break;
743         case IW_AUTH_TKIP_COUNTERMEASURES:
744                 ieee->tkip_countermeasures = data->value;
745                 break;
746         case IW_AUTH_DROP_UNENCRYPTED:
747                 ieee->drop_unencrypted = data->value;
748                 break;
749
750         case IW_AUTH_80211_AUTH_ALG:
751                 if (data->value & IW_AUTH_ALG_SHARED_KEY) {
752                         ieee->open_wep = 0;
753                         ieee->auth_mode = 1;
754                 } else if (data->value & IW_AUTH_ALG_OPEN_SYSTEM) {
755                         ieee->open_wep = 1;
756                         ieee->auth_mode = 0;
757                 } else if (data->value & IW_AUTH_ALG_LEAP) {
758                         ieee->open_wep = 1;
759                         ieee->auth_mode = 2;
760                 } else
761                         return -EINVAL;
762                 break;
763
764         case IW_AUTH_WPA_ENABLED:
765                 ieee->wpa_enabled = (data->value) ? 1 : 0;
766                 break;
767
768         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
769                 ieee->ieee802_1x = data->value;
770                 break;
771         case IW_AUTH_PRIVACY_INVOKED:
772                 ieee->privacy_invoked = data->value;
773                 break;
774         default:
775                 return -EOPNOTSUPP;
776         }
777         return 0;
778 }
779 EXPORT_SYMBOL(rtllib_wx_set_auth);
780
781 int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
782 {
783         u8 *buf;
784         u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
785
786         if (len > MAX_WPA_IE_LEN || (len && ie == NULL))
787                 return -EINVAL;
788
789         if (len) {
790                 eid = ie[0];
791                 if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2],
792                      wps_oui, 4))) {
793
794                         ieee->wps_ie_len = min_t(size_t, len, MAX_WZC_IE_LEN);
795                         buf = kmemdup(ie, ieee->wps_ie_len, GFP_KERNEL);
796                         if (buf == NULL)
797                                 return -ENOMEM;
798                         ieee->wps_ie = buf;
799                         return 0;
800                 }
801         }
802         ieee->wps_ie_len = 0;
803         kfree(ieee->wps_ie);
804         ieee->wps_ie = NULL;
805         if (len) {
806                 if (len != ie[1]+2)
807                         return -EINVAL;
808                 buf = kmemdup(ie, len, GFP_KERNEL);
809                 if (buf == NULL)
810                         return -ENOMEM;
811                 kfree(ieee->wpa_ie);
812                 ieee->wpa_ie = buf;
813                 ieee->wpa_ie_len = len;
814         } else {
815                 kfree(ieee->wpa_ie);
816                 ieee->wpa_ie = NULL;
817                 ieee->wpa_ie_len = 0;
818         }
819         return 0;
820 }
821 EXPORT_SYMBOL(rtllib_wx_set_gen_ie);