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