/kern_oII/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c

http://omnia2droid.googlecode.com/ · C · 1032 lines · 842 code · 93 blank · 97 comment · 185 complexity · 1802e1158142b046db1f09214037acad MD5 · raw file

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