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