Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtllib_wx.c
Go to the documentation of this file.
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
9  Copyright (c) 2002-2003, Jouni Malinen <[email protected]>
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 <[email protected]>
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 
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  memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
69  start = iwe_stream_add_event_rsl(info, start, stop,
70  &iwe, IW_EV_ADDR_LEN);
71  /* Remaining entries will be displayed in the order we provide them */
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(network->ssid_len, (u8)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(network->hidden_ssid_len, (u8)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 &
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 = rtllib_frequency(network->channel, network->mode);
117  iwe.u.freq.e = 3; */
118  iwe.u.freq.m = network->channel;
119  iwe.u.freq.e = 0;
120  iwe.u.freq.i = 0;
121  start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
123 
124  /* Add encryption capability */
125  iwe.cmd = SIOCGIWENCODE;
126  if (network->capability & WLAN_CAPABILITY_PRIVACY)
127  iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
128  else
129  iwe.u.data.flags = IW_ENCODE_DISABLED;
130  iwe.u.data.length = 0;
131  start = iwe_stream_add_point_rsl(info, start, stop,
132  &iwe, network->ssid);
133  /* Add basic and extended rates */
134  max_rate = 0;
135  p = custom;
136  p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
137  for (i = 0, j = 0; i < network->rates_len;) {
138  if (j < network->rates_ex_len &&
139  ((network->rates_ex[j] & 0x7F) <
140  (network->rates[i] & 0x7F)))
141  rate = network->rates_ex[j++] & 0x7F;
142  else
143  rate = network->rates[i++] & 0x7F;
144  if (rate > max_rate)
145  max_rate = rate;
146  p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
147  "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
148  }
149  for (; j < network->rates_ex_len; j++) {
150  rate = network->rates_ex[j] & 0x7F;
151  p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
152  "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
153  if (rate > max_rate)
154  max_rate = rate;
155  }
156 
157  if (network->mode >= IEEE_N_24G) {
158  struct ht_capab_ele *ht_cap = NULL;
159  bool is40M = false, isShortGI = false;
160  u8 max_mcs = 0;
161  if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
162  ht_cap = (struct ht_capab_ele *)
163  &network->bssht.bdHTCapBuf[4];
164  else
165  ht_cap = (struct ht_capab_ele *)
166  &network->bssht.bdHTCapBuf[0];
167  is40M = (ht_cap->ChlWidth) ? 1 : 0;
168  isShortGI = (ht_cap->ChlWidth) ?
169  ((ht_cap->ShortGI40Mhz) ? 1 : 0) :
170  ((ht_cap->ShortGI20Mhz) ? 1 : 0);
171 
172  max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS,
174  rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f];
175  if (rate > max_rate)
176  max_rate = rate;
177  }
178  iwe.cmd = SIOCGIWRATE;
179  iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
180  iwe.u.bitrate.value = max_rate * 500000;
181  start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
183  iwe.cmd = IWEVCUSTOM;
184  iwe.u.data.length = p - custom;
185  if (iwe.u.data.length)
186  start = iwe_stream_add_point_rsl(info, start, stop,
187  &iwe, custom);
188  /* Add quality statistics */
189  /* TODO: Fix these values... */
190  iwe.cmd = IWEVQUAL;
191  iwe.u.qual.qual = network->stats.signal;
192  iwe.u.qual.level = network->stats.rssi;
193  iwe.u.qual.noise = network->stats.noise;
194  iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK;
195  if (!(network->stats.mask & RTLLIB_STATMASK_RSSI))
196  iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
197  if (!(network->stats.mask & RTLLIB_STATMASK_NOISE))
198  iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
199  if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL))
200  iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
201  iwe.u.qual.updated = 7;
202  start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
204 
205  iwe.cmd = IWEVCUSTOM;
206  p = custom;
207  iwe.u.data.length = p - custom;
208  if (iwe.u.data.length)
209  start = iwe_stream_add_point_rsl(info, start, stop,
210  &iwe, custom);
211 
212  memset(&iwe, 0, sizeof(iwe));
213  if (network->wpa_ie_len) {
214  char buf[MAX_WPA_IE_LEN];
215  memcpy(buf, network->wpa_ie, network->wpa_ie_len);
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  memcpy(buf, network->rsn_ie, network->rsn_ie_len);
224  iwe.cmd = IWEVGENIE;
225  iwe.u.data.length = network->rsn_ie_len;
226  start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
227  }
228 
229  /* add info for WZC */
230  memset(&iwe, 0, sizeof(iwe));
231  if (network->wzc_ie_len) {
232  char buf[MAX_WZC_IE_LEN];
233  memcpy(buf, network->wzc_ie, network->wzc_ie_len);
234  iwe.cmd = IWEVGENIE;
235  iwe.u.data.length = network->wzc_ie_len;
236  start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
237  }
238 
239  /* Add EXTRA: Age to display seconds since last beacon/probe response
240  * for given network. */
241  iwe.cmd = IWEVCUSTOM;
242  p = custom;
243  p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
244  " Last beacon: %lums ago",
245  (jiffies - network->last_scanned) / (HZ / 100));
246  iwe.u.data.length = p - custom;
247  if (iwe.u.data.length)
248  start = iwe_stream_add_point_rsl(info, start, stop,
249  &iwe, custom);
250 
251  return start;
252 }
253 
255  struct iw_request_info *info,
256  union iwreq_data *wrqu, char *extra)
257 {
258  struct rtllib_network *network;
259  unsigned long flags;
260 
261  char *ev = extra;
262  char *stop = ev + wrqu->data.length;
263  int i = 0;
264  int err = 0;
265  RTLLIB_DEBUG_WX("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  RTLLIB_DEBUG_SCAN("Not showing network '%s ("
281  " %pM)' due to age (%lums).\n",
282  escape_essid(network->ssid,
283  network->ssid_len),
284  network->bssid,
285  (jiffies - network->last_scanned) / (HZ / 100));
286  }
287 
288  spin_unlock_irqrestore(&ieee->lock, flags);
289  up(&ieee->wx_sem);
290  wrqu->data.length = ev - extra;
291  wrqu->data.flags = 0;
292 
293  RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i);
294 
295  return err;
296 }
298 
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 lib80211_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 > NUM_WEP_KEYS)
316  return -EINVAL;
317  key--;
318  key_provided = 1;
319  } else {
320  key_provided = 0;
321  key = ieee->crypt_info.tx_keyidx;
322  }
323 
324  RTLLIB_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
325  "provided" : "default");
326  crypt = &ieee->crypt_info.crypt[key];
327  if (erq->flags & IW_ENCODE_DISABLED) {
328  if (key_provided && *crypt) {
329  RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
330  key);
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 < NUM_WEP_KEYS; i++) {
338  if (ieee->crypt_info.crypt[i] != NULL) {
339  if (key_provided)
340  break;
342  &ieee->crypt_info.crypt[i]);
343  }
344  }
345 
346  if (i == NUM_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, "R-WEP") != 0) {
362  /* changing to use WEP; deinit previously used algorithm
363  * on this key */
365  }
366 
367  if (*crypt == NULL) {
368  struct lib80211_crypt_data *new_crypt;
369 
370  /* take WEP into use */
371  new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
372  GFP_KERNEL);
373  if (new_crypt == NULL)
374  return -ENOMEM;
375  new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
376  if (!new_crypt->ops) {
377  request_module("rtllib_crypt_wep");
378  new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
379  }
380 
381  if (new_crypt->ops)
382  new_crypt->priv = new_crypt->ops->init(key);
383 
384  if (!new_crypt->ops || !new_crypt->priv) {
385  kfree(new_crypt);
386  new_crypt = NULL;
387 
388  printk(KERN_WARNING "%s: could not initialize WEP: "
389  "load module rtllib_crypt_wep\n",
390  dev->name);
391  return -EOPNOTSUPP;
392  }
393  *crypt = new_crypt;
394  }
395 
396  /* If a new key was provided, set it up */
397  if (erq->length > 0) {
398  len = erq->length <= 5 ? 5 : 13;
399  memcpy(sec.keys[key], keybuf, erq->length);
400  if (len > erq->length)
401  memset(sec.keys[key] + erq->length, 0,
402  len - erq->length);
403  RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
404  key, escape_essid(sec.keys[key], len),
405  erq->length, len);
406  sec.key_sizes[key] = len;
407  (*crypt)->ops->set_key(sec.keys[key], len, NULL,
408  (*crypt)->priv);
409  sec.flags |= (1 << key);
410  /* This ensures a key will be activated if no key is
411  * explicitly set */
412  if (key == sec.active_key)
413  sec.flags |= SEC_ACTIVE_KEY;
414  ieee->crypt_info.tx_keyidx = key;
415 
416  } else {
417  len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
418  NULL, (*crypt)->priv);
419  if (len == 0) {
420  /* Set a default key of all 0 */
421  printk(KERN_INFO "Setting key %d to all zero.\n",
422  key);
423 
424  RTLLIB_DEBUG_WX("Setting key %d to all zero.\n",
425  key);
426  memset(sec.keys[key], 0, 13);
427  (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
428  (*crypt)->priv);
429  sec.key_sizes[key] = 13;
430  sec.flags |= (1 << key);
431  }
432 
433  /* No key data - just set the default TX key index */
434  if (key_provided) {
436  "Setting key %d to default Tx key.\n", key);
437  ieee->crypt_info.tx_keyidx = key;
438  sec.active_key = key;
439  sec.flags |= SEC_ACTIVE_KEY;
440  }
441  }
442  done:
443  ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
444  ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
447  sec.flags |= SEC_AUTH_MODE;
448  RTLLIB_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
449  "OPEN" : "SHARED KEY");
450 
451  /* For now we just support WEP, so only set that security level...
452  * TODO: When WPA is added this is one place that needs to change */
453  sec.flags |= SEC_LEVEL;
454  sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
455 
456  if (ieee->set_security)
457  ieee->set_security(dev, &sec);
458 
459  /* Do not reset port if card is in Managed mode since resetting will
460  * generate new IEEE 802.11 authentication which may end up in looping
461  * with IEEE 802.1X. If your hardware requires a reset after WEP
462  * configuration (for example... Prism2), implement the reset_port in
463  * the callbacks structures used to initialize the 802.11 stack. */
464  if (ieee->reset_on_keychange &&
465  ieee->iw_mode != IW_MODE_INFRA &&
466  ieee->reset_port && ieee->reset_port(dev)) {
467  printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
468  return -EINVAL;
469  }
470  return 0;
471 }
473 
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 lib80211_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 > NUM_WEP_KEYS)
490  return -EINVAL;
491  key--;
492  } else {
493  key = ieee->crypt_info.tx_keyidx;
494  }
495  crypt = ieee->crypt_info.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 }
517 
519  struct iw_request_info *info,
520  union iwreq_data *wrqu, char *extra)
521 {
522  int ret = 0;
523  struct net_device *dev = ieee->dev;
524  struct iw_point *encoding = &wrqu->encoding;
525  struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
526  int i, idx;
527  int group_key = 0;
528  const char *alg, *module;
529  struct lib80211_crypto_ops *ops;
530  struct lib80211_crypt_data **crypt;
531 
532  struct rtllib_security sec = {
533  .flags = 0,
534  };
535  idx = encoding->flags & IW_ENCODE_INDEX;
536  if (idx) {
537  if (idx < 1 || idx > NUM_WEP_KEYS)
538  return -EINVAL;
539  idx--;
540  } else{
541  idx = ieee->crypt_info.tx_keyidx;
542  }
543  if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
544  crypt = &ieee->crypt_info.crypt[idx];
545  group_key = 1;
546  } else {
547  /* some Cisco APs use idx>0 for unicast in dynamic WEP */
548  if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
549  return -EINVAL;
550  if (ieee->iw_mode == IW_MODE_INFRA)
551  crypt = &ieee->crypt_info.crypt[idx];
552  else
553  return -EINVAL;
554  }
555 
556  sec.flags |= SEC_ENABLED;
557  if ((encoding->flags & IW_ENCODE_DISABLED) ||
558  ext->alg == IW_ENCODE_ALG_NONE) {
559  if (*crypt)
561 
562  for (i = 0; i < NUM_WEP_KEYS; i++) {
563  if (ieee->crypt_info.crypt[i] != NULL)
564  break;
565  }
566  if (i == NUM_WEP_KEYS) {
567  sec.enabled = 0;
568  sec.level = SEC_LEVEL_0;
569  sec.flags |= SEC_LEVEL;
570  }
571  goto done;
572  }
573 
574  sec.enabled = 1;
575  switch (ext->alg) {
576  case IW_ENCODE_ALG_WEP:
577  alg = "R-WEP";
578  module = "rtllib_crypt_wep";
579  break;
580  case IW_ENCODE_ALG_TKIP:
581  alg = "R-TKIP";
582  module = "rtllib_crypt_tkip";
583  break;
584  case IW_ENCODE_ALG_CCMP:
585  alg = "R-CCMP";
586  module = "rtllib_crypt_ccmp";
587  break;
588  default:
589  RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
590  dev->name, ext->alg);
591  ret = -EINVAL;
592  goto done;
593  }
594  printk(KERN_INFO "alg name:%s\n", alg);
595 
596  ops = lib80211_get_crypto_ops(alg);
597  if (ops == NULL) {
598  char tempbuf[100];
599 
600  memset(tempbuf, 0x00, 100);
601  sprintf(tempbuf, "%s", module);
602  request_module("%s", tempbuf);
603  ops = lib80211_get_crypto_ops(alg);
604  }
605  if (ops == NULL) {
606  RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
607  dev->name, ext->alg);
608  printk(KERN_INFO "========>unknown crypto alg %d\n", ext->alg);
609  ret = -EINVAL;
610  goto done;
611  }
612 
613  if (*crypt == NULL || (*crypt)->ops != ops) {
614  struct lib80211_crypt_data *new_crypt;
615 
617 
618  new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
619  if (new_crypt == NULL) {
620  ret = -ENOMEM;
621  goto done;
622  }
623  new_crypt->ops = ops;
624  if (new_crypt->ops)
625  new_crypt->priv = new_crypt->ops->init(idx);
626 
627  if (new_crypt->priv == NULL) {
628  kfree(new_crypt);
629  ret = -EINVAL;
630  goto done;
631  }
632  *crypt = new_crypt;
633 
634  }
635 
636  if (ext->key_len > 0 && (*crypt)->ops->set_key &&
637  (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
638  (*crypt)->priv) < 0) {
639  RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name);
640  printk(KERN_INFO "key setting failed\n");
641  ret = -EINVAL;
642  goto done;
643  }
644  if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
645  ieee->crypt_info.tx_keyidx = idx;
646  sec.active_key = idx;
647  sec.flags |= SEC_ACTIVE_KEY;
648  }
649  if (ext->alg != IW_ENCODE_ALG_NONE) {
650  sec.key_sizes[idx] = ext->key_len;
651  sec.flags |= (1 << idx);
652  if (ext->alg == IW_ENCODE_ALG_WEP) {
653  sec.flags |= SEC_LEVEL;
654  sec.level = SEC_LEVEL_1;
655  } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
656  sec.flags |= SEC_LEVEL;
657  sec.level = SEC_LEVEL_2;
658  } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
659  sec.flags |= SEC_LEVEL;
660  sec.level = SEC_LEVEL_3;
661  }
662  /* Don't set sec level for group keys. */
663  if (group_key)
664  sec.flags &= ~SEC_LEVEL;
665  }
666 done:
667  if (ieee->set_security)
668  ieee->set_security(ieee->dev, &sec);
669 
670  if (ieee->reset_on_keychange &&
671  ieee->iw_mode != IW_MODE_INFRA &&
672  ieee->reset_port && ieee->reset_port(dev)) {
673  RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name);
674  return -EINVAL;
675  }
676  return ret;
677 }
679 
681  struct iw_request_info *info,
682  union iwreq_data *wrqu, char *extra)
683 {
684  struct iw_point *encoding = &wrqu->encoding;
685  struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
686  struct lib80211_crypt_data *crypt;
687  int idx, max_key_len;
688 
689  max_key_len = encoding->length - sizeof(*ext);
690  if (max_key_len < 0)
691  return -EINVAL;
692 
693  idx = encoding->flags & IW_ENCODE_INDEX;
694  if (idx) {
695  if (idx < 1 || idx > NUM_WEP_KEYS)
696  return -EINVAL;
697  idx--;
698  } else {
699  idx = ieee->crypt_info.tx_keyidx;
700  }
701  if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
702  (ext->alg != IW_ENCODE_ALG_WEP))
703  if (idx != 0 || (ieee->iw_mode != IW_MODE_INFRA))
704  return -EINVAL;
705 
706  crypt = ieee->crypt_info.crypt[idx];
707 
708  encoding->flags = idx + 1;
709  memset(ext, 0, sizeof(*ext));
710 
711  if (crypt == NULL || crypt->ops == NULL) {
712  ext->alg = IW_ENCODE_ALG_NONE;
713  ext->key_len = 0;
714  encoding->flags |= IW_ENCODE_DISABLED;
715  } else {
716  if (strcmp(crypt->ops->name, "R-WEP") == 0)
717  ext->alg = IW_ENCODE_ALG_WEP;
718  else if (strcmp(crypt->ops->name, "R-TKIP"))
719  ext->alg = IW_ENCODE_ALG_TKIP;
720  else if (strcmp(crypt->ops->name, "R-CCMP"))
721  ext->alg = IW_ENCODE_ALG_CCMP;
722  else
723  return -EINVAL;
724  ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN,
725  NULL, crypt->priv);
726  encoding->flags |= IW_ENCODE_ENABLED;
727  if (ext->key_len &&
728  (ext->alg == IW_ENCODE_ALG_TKIP ||
729  ext->alg == IW_ENCODE_ALG_CCMP))
731 
732  }
733 
734  return 0;
735 }
736 
738  struct iw_request_info *info,
739  union iwreq_data *wrqu, char *extra)
740 {
741  u8 i = 0;
742  bool deauth = false;
743  struct iw_mlme *mlme = (struct iw_mlme *) extra;
744 
745  if (ieee->state != RTLLIB_LINKED)
746  return -ENOLINK;
747 
748  down(&ieee->wx_sem);
749 
750  switch (mlme->cmd) {
751  case IW_MLME_DEAUTH:
752  deauth = true;
753  /* leave break out intentionly */
754 
755  case IW_MLME_DISASSOC:
756  if (deauth == true)
757  printk(KERN_INFO "disauth packet !\n");
758  else
759  printk(KERN_INFO "dis associate packet!\n");
760 
761  ieee->cannot_notify = true;
762 
763  SendDisassociation(ieee, deauth, mlme->reason_code);
764  rtllib_disassociate(ieee);
765 
766  ieee->wap_set = 0;
767  for (i = 0; i < 6; i++)
768  ieee->current_network.bssid[i] = 0x55;
769 
770  ieee->ssid_set = 0;
771  ieee->current_network.ssid[0] = '\0';
772  ieee->current_network.ssid_len = 0;
773  break;
774  default:
775  up(&ieee->wx_sem);
776  return -EOPNOTSUPP;
777  }
778 
779  up(&ieee->wx_sem);
780 
781  return 0;
782 }
784 
786  struct iw_request_info *info,
787  struct iw_param *data, char *extra)
788 {
789  switch (data->flags & IW_AUTH_INDEX) {
790  case IW_AUTH_WPA_VERSION:
791  break;
794  case IW_AUTH_KEY_MGMT:
795  /*
796  * Host AP driver does not use these parameters and allows
797  * wpa_supplicant to control them internally.
798  */
799  break;
801  ieee->tkip_countermeasures = data->value;
802  break;
804  ieee->drop_unencrypted = data->value;
805  break;
806 
808  if (data->value & IW_AUTH_ALG_SHARED_KEY) {
809  ieee->open_wep = 0;
810  ieee->auth_mode = 1;
811  } else if (data->value & IW_AUTH_ALG_OPEN_SYSTEM) {
812  ieee->open_wep = 1;
813  ieee->auth_mode = 0;
814  } else if (data->value & IW_AUTH_ALG_LEAP) {
815  ieee->open_wep = 1;
816  ieee->auth_mode = 2;
817  } else
818  return -EINVAL;
819  break;
820 
821  case IW_AUTH_WPA_ENABLED:
822  ieee->wpa_enabled = (data->value) ? 1 : 0;
823  break;
824 
826  ieee->ieee802_1x = data->value;
827  break;
829  ieee->privacy_invoked = data->value;
830  break;
831  default:
832  return -EOPNOTSUPP;
833  }
834  return 0;
835 }
837 
838 int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
839 {
840  u8 *buf;
841  u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
842 
843  if (len > MAX_WPA_IE_LEN || (len && ie == NULL))
844  return -EINVAL;
845 
846  if (len) {
847  eid = ie[0];
848  if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2],
849  wps_oui, 4))) {
850 
851  ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len) :
852  (MAX_WZC_IE_LEN);
853  buf = kmemdup(ie, ieee->wps_ie_len, GFP_KERNEL);
854  if (buf == NULL)
855  return -ENOMEM;
856  ieee->wps_ie = buf;
857  return 0;
858  }
859  }
860  ieee->wps_ie_len = 0;
861  kfree(ieee->wps_ie);
862  ieee->wps_ie = NULL;
863  if (len) {
864  if (len != ie[1]+2)
865  return -EINVAL;
866  buf = kmemdup(ie, len, GFP_KERNEL);
867  if (buf == NULL)
868  return -ENOMEM;
869  kfree(ieee->wpa_ie);
870  ieee->wpa_ie = buf;
871  ieee->wpa_ie_len = len;
872  } else {
873  kfree(ieee->wpa_ie);
874  ieee->wpa_ie = NULL;
875  ieee->wpa_ie_len = 0;
876  }
877  return 0;
878 }