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