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