PageRenderTime 32ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/wl/sys/wl_iw.c

https://bitbucket.org/agalog/broadcom
C | 2722 lines | 2246 code | 463 blank | 13 comment | 337 complexity | fad4fc2b1ea39f4f18a48e5a3e755ce2 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Linux Wireless Extensions support
  3. *
  4. * Copyright (C) 2010, Broadcom Corporation
  5. * All Rights Reserved.
  6. *
  7. * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
  8. * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
  9. * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
  10. * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
  11. *
  12. * $Id: wl_iw.c,v 1.133.2.1.28.9 2011-01-26 22:23:18 Exp $
  13. */
  14. #if defined(USE_IW)
  15. #define LINUX_PORT
  16. #include <typedefs.h>
  17. #include <linuxver.h>
  18. #include <osl.h>
  19. #include <bcmutils.h>
  20. #include <bcmendian.h>
  21. #include <proto/ethernet.h>
  22. #include <linux/if_arp.h>
  23. #include <asm/uaccess.h>
  24. typedef const struct si_pub si_t;
  25. #include <wlioctl.h>
  26. #include <wl_dbg.h>
  27. #include <wl_iw.h>
  28. extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
  29. uint32 reason, char* stringBuf, uint buflen);
  30. #define MAX_WLIW_IOCTL_LEN 1024
  31. #define htod32(i) i
  32. #define htod16(i) i
  33. #define dtoh32(i) i
  34. #define dtoh16(i) i
  35. #define htodchanspec(i) i
  36. #define dtohchanspec(i) i
  37. extern struct iw_statistics *wl_get_wireless_stats(struct net_device *dev);
  38. #if WIRELESS_EXT < 19
  39. #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
  40. #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
  41. #endif
  42. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
  43. #define IW_DEV_IF(dev) ((wl_iw_t *)netdev_priv(dev))
  44. #else
  45. #define IW_DEV_IF(dev) ((wl_iw_t *)dev->priv)
  46. #endif
  47. static void swap_key_from_BE(
  48. wl_wsec_key_t *key
  49. )
  50. {
  51. key->index = htod32(key->index);
  52. key->len = htod32(key->len);
  53. key->algo = htod32(key->algo);
  54. key->flags = htod32(key->flags);
  55. key->rxiv.hi = htod32(key->rxiv.hi);
  56. key->rxiv.lo = htod16(key->rxiv.lo);
  57. key->iv_initialized = htod32(key->iv_initialized);
  58. }
  59. static void swap_key_to_BE(
  60. wl_wsec_key_t *key
  61. )
  62. {
  63. key->index = dtoh32(key->index);
  64. key->len = dtoh32(key->len);
  65. key->algo = dtoh32(key->algo);
  66. key->flags = dtoh32(key->flags);
  67. key->rxiv.hi = dtoh32(key->rxiv.hi);
  68. key->rxiv.lo = dtoh16(key->rxiv.lo);
  69. key->iv_initialized = dtoh32(key->iv_initialized);
  70. }
  71. static int
  72. dev_wlc_ioctl(
  73. struct net_device *dev,
  74. int cmd,
  75. void *arg,
  76. int len
  77. )
  78. {
  79. struct ifreq ifr;
  80. wl_ioctl_t ioc;
  81. mm_segment_t fs;
  82. int ret;
  83. memset(&ioc, 0, sizeof(ioc));
  84. ioc.cmd = cmd;
  85. ioc.buf = arg;
  86. ioc.len = len;
  87. strcpy(ifr.ifr_name, dev->name);
  88. ifr.ifr_data = (caddr_t) &ioc;
  89. fs = get_fs();
  90. set_fs(get_ds());
  91. #if defined(WL_USE_NETDEV_OPS)
  92. ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
  93. #else
  94. ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
  95. #endif
  96. set_fs(fs);
  97. return ret;
  98. }
  99. static int
  100. dev_wlc_intvar_set(
  101. struct net_device *dev,
  102. char *name,
  103. int val)
  104. {
  105. char buf[WLC_IOCTL_SMLEN];
  106. uint len;
  107. val = htod32(val);
  108. len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
  109. ASSERT(len);
  110. return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
  111. }
  112. #if WIRELESS_EXT > 17
  113. static int
  114. dev_wlc_bufvar_set(
  115. struct net_device *dev,
  116. char *name,
  117. char *buf, int len)
  118. {
  119. char *ioctlbuf;
  120. uint buflen;
  121. int error;
  122. ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
  123. if (!ioctlbuf)
  124. return -ENOMEM;
  125. buflen = bcm_mkiovar(name, buf, len, ioctlbuf, MAX_WLIW_IOCTL_LEN);
  126. ASSERT(buflen);
  127. error = dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen);
  128. kfree(ioctlbuf);
  129. return error;
  130. }
  131. #endif
  132. static int
  133. dev_wlc_bufvar_get(
  134. struct net_device *dev,
  135. char *name,
  136. char *buf, int buflen)
  137. {
  138. char *ioctlbuf;
  139. int error;
  140. uint len;
  141. ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL);
  142. if (!ioctlbuf)
  143. return -ENOMEM;
  144. len = bcm_mkiovar(name, NULL, 0, ioctlbuf, MAX_WLIW_IOCTL_LEN);
  145. ASSERT(len);
  146. error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN);
  147. if (!error)
  148. bcopy(ioctlbuf, buf, buflen);
  149. kfree(ioctlbuf);
  150. return (error);
  151. }
  152. static int
  153. dev_wlc_intvar_get(
  154. struct net_device *dev,
  155. char *name,
  156. int *retval)
  157. {
  158. union {
  159. char buf[WLC_IOCTL_SMLEN];
  160. int val;
  161. } var;
  162. int error;
  163. uint len;
  164. uint data_null;
  165. len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf));
  166. ASSERT(len);
  167. error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
  168. *retval = dtoh32(var.val);
  169. return (error);
  170. }
  171. #if WIRELESS_EXT < 13
  172. struct iw_request_info
  173. {
  174. __u16 cmd;
  175. __u16 flags;
  176. };
  177. typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
  178. void *wrqu, char *extra);
  179. #endif
  180. #if WIRELESS_EXT > 12
  181. static int
  182. wl_iw_set_leddc(
  183. struct net_device *dev,
  184. struct iw_request_info *info,
  185. union iwreq_data *wrqu,
  186. char *extra
  187. )
  188. {
  189. int dc = *(int *)extra;
  190. int error;
  191. error = dev_wlc_intvar_set(dev, "leddc", dc);
  192. return error;
  193. }
  194. static int
  195. wl_iw_set_vlanmode(
  196. struct net_device *dev,
  197. struct iw_request_info *info,
  198. union iwreq_data *wrqu,
  199. char *extra
  200. )
  201. {
  202. int mode = *(int *)extra;
  203. int error;
  204. mode = htod32(mode);
  205. error = dev_wlc_intvar_set(dev, "vlan_mode", mode);
  206. return error;
  207. }
  208. static int
  209. wl_iw_set_pm(
  210. struct net_device *dev,
  211. struct iw_request_info *info,
  212. union iwreq_data *wrqu,
  213. char *extra
  214. )
  215. {
  216. int pm = *(int *)extra;
  217. int error;
  218. pm = htod32(pm);
  219. error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
  220. return error;
  221. }
  222. #endif
  223. static int
  224. wl_iw_config_commit(
  225. struct net_device *dev,
  226. struct iw_request_info *info,
  227. void *zwrq,
  228. char *extra
  229. )
  230. {
  231. wlc_ssid_t ssid;
  232. int error;
  233. struct sockaddr bssid;
  234. WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name));
  235. if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid))))
  236. return error;
  237. ssid.SSID_len = dtoh32(ssid.SSID_len);
  238. if (!ssid.SSID_len)
  239. return 0;
  240. bzero(&bssid, sizeof(struct sockaddr));
  241. if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) {
  242. WL_ERROR(("%s: WLC_REASSOC failed (%d)\n", __FUNCTION__, error));
  243. return error;
  244. }
  245. return 0;
  246. }
  247. static int
  248. wl_iw_get_name(
  249. struct net_device *dev,
  250. struct iw_request_info *info,
  251. union iwreq_data *cwrq,
  252. char *extra
  253. )
  254. {
  255. int phytype, err;
  256. uint band[3];
  257. char cap[5];
  258. WL_TRACE(("%s: SIOCGIWNAME\n", dev->name));
  259. cap[0] = 0;
  260. if ((err = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))) < 0)
  261. goto done;
  262. if ((err = dev_wlc_ioctl(dev, WLC_GET_BANDLIST, band, sizeof(band))) < 0)
  263. goto done;
  264. band[0] = dtoh32(band[0]);
  265. switch (phytype) {
  266. case WLC_PHY_TYPE_A:
  267. strcpy(cap, "a");
  268. break;
  269. case WLC_PHY_TYPE_B:
  270. strcpy(cap, "b");
  271. break;
  272. case WLC_PHY_TYPE_LP:
  273. case WLC_PHY_TYPE_G:
  274. if (band[0] >= 2)
  275. strcpy(cap, "abg");
  276. else
  277. strcpy(cap, "bg");
  278. break;
  279. case WLC_PHY_TYPE_N:
  280. if (band[0] >= 2)
  281. strcpy(cap, "abgn");
  282. else
  283. strcpy(cap, "bgn");
  284. break;
  285. }
  286. done:
  287. snprintf(cwrq->name, IFNAMSIZ, "IEEE 802.11%s", cap);
  288. return 0;
  289. }
  290. static int
  291. wl_iw_set_freq(
  292. struct net_device *dev,
  293. struct iw_request_info *info,
  294. struct iw_freq *fwrq,
  295. char *extra
  296. )
  297. {
  298. int error, chan;
  299. uint sf = 0;
  300. WL_TRACE(("%s: SIOCSIWFREQ\n", dev->name));
  301. if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
  302. chan = fwrq->m;
  303. }
  304. else {
  305. if (fwrq->e >= 6) {
  306. fwrq->e -= 6;
  307. while (fwrq->e--)
  308. fwrq->m *= 10;
  309. } else if (fwrq->e < 6) {
  310. while (fwrq->e++ < 6)
  311. fwrq->m /= 10;
  312. }
  313. if (fwrq->m > 4000 && fwrq->m < 5000)
  314. sf = WF_CHAN_FACTOR_4_G;
  315. chan = wf_mhz2channel(fwrq->m, sf);
  316. }
  317. chan = htod32(chan);
  318. if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
  319. return error;
  320. return -EINPROGRESS;
  321. }
  322. static int
  323. wl_iw_get_freq(
  324. struct net_device *dev,
  325. struct iw_request_info *info,
  326. struct iw_freq *fwrq,
  327. char *extra
  328. )
  329. {
  330. channel_info_t ci;
  331. int error;
  332. WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
  333. if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
  334. return error;
  335. fwrq->m = dtoh32(ci.hw_channel);
  336. fwrq->e = dtoh32(0);
  337. return 0;
  338. }
  339. static int
  340. wl_iw_set_mode(
  341. struct net_device *dev,
  342. struct iw_request_info *info,
  343. __u32 *uwrq,
  344. char *extra
  345. )
  346. {
  347. int infra = 0, ap = 0, error = 0;
  348. WL_TRACE(("%s: SIOCSIWMODE\n", dev->name));
  349. switch (*uwrq) {
  350. case IW_MODE_MASTER:
  351. infra = ap = 1;
  352. break;
  353. case IW_MODE_ADHOC:
  354. case IW_MODE_AUTO:
  355. break;
  356. case IW_MODE_INFRA:
  357. infra = 1;
  358. break;
  359. default:
  360. return -EINVAL;
  361. }
  362. infra = htod32(infra);
  363. ap = htod32(ap);
  364. if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) ||
  365. (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap))))
  366. return error;
  367. return -EINPROGRESS;
  368. }
  369. static int
  370. wl_iw_get_mode(
  371. struct net_device *dev,
  372. struct iw_request_info *info,
  373. __u32 *uwrq,
  374. char *extra
  375. )
  376. {
  377. int error, infra = 0, ap = 0;
  378. WL_TRACE(("%s: SIOCGIWMODE\n", dev->name));
  379. if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) ||
  380. (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap))))
  381. return error;
  382. infra = dtoh32(infra);
  383. ap = dtoh32(ap);
  384. *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
  385. return 0;
  386. }
  387. static int
  388. wl_iw_get_range(
  389. struct net_device *dev,
  390. struct iw_request_info *info,
  391. struct iw_point *dwrq,
  392. char *extra
  393. )
  394. {
  395. struct iw_range *range = (struct iw_range *) extra;
  396. static int channels[MAXCHANNEL+1];
  397. wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
  398. wl_rateset_t rateset;
  399. int error, i, k;
  400. uint sf, ch;
  401. int phytype;
  402. int bw_cap = 0, sgi_tx = 0, nmode = 0;
  403. channel_info_t ci;
  404. uint8 nrate_list2copy = 0;
  405. uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
  406. {14, 29, 43, 58, 87, 116, 130, 144},
  407. {27, 54, 81, 108, 162, 216, 243, 270},
  408. {30, 60, 90, 120, 180, 240, 270, 300}};
  409. WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
  410. if (!extra)
  411. return -EINVAL;
  412. dwrq->length = sizeof(struct iw_range);
  413. memset(range, 0, sizeof(range));
  414. range->min_nwid = range->max_nwid = 0;
  415. list->count = htod32(MAXCHANNEL);
  416. if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels))))
  417. return error;
  418. for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
  419. range->freq[i].i = dtoh32(list->element[i]);
  420. ch = dtoh32(list->element[i]);
  421. if (ch <= CH_MAX_2G_CHANNEL)
  422. sf = WF_CHAN_FACTOR_2_4_G;
  423. else
  424. sf = WF_CHAN_FACTOR_5_G;
  425. range->freq[i].m = wf_channel2mhz(ch, sf);
  426. range->freq[i].e = 6;
  427. }
  428. range->num_frequency = range->num_channels = i;
  429. range->max_qual.qual = 5;
  430. range->max_qual.level = 0x100 - 200;
  431. range->max_qual.noise = 0x100 - 200;
  432. range->sensitivity = 65535;
  433. #if WIRELESS_EXT > 11
  434. range->avg_qual.qual = 3;
  435. range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD;
  436. range->avg_qual.noise = 0x100 - 75;
  437. #endif
  438. if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
  439. return error;
  440. rateset.count = dtoh32(rateset.count);
  441. range->num_bitrates = rateset.count;
  442. for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
  443. range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000;
  444. dev_wlc_intvar_get(dev, "nmode", &nmode);
  445. dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype));
  446. if (nmode == 1 && ((phytype == WLC_PHY_TYPE_SSN) || (phytype == WLC_PHY_TYPE_LCN))) {
  447. dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap);
  448. dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
  449. dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t));
  450. ci.hw_channel = dtoh32(ci.hw_channel);
  451. if (bw_cap == 0 ||
  452. (bw_cap == 2 && ci.hw_channel <= 14)) {
  453. if (sgi_tx == 0)
  454. nrate_list2copy = 0;
  455. else
  456. nrate_list2copy = 1;
  457. }
  458. if (bw_cap == 1 ||
  459. (bw_cap == 2 && ci.hw_channel >= 36)) {
  460. if (sgi_tx == 0)
  461. nrate_list2copy = 2;
  462. else
  463. nrate_list2copy = 3;
  464. }
  465. range->num_bitrates += 8;
  466. for (k = 0; i < range->num_bitrates; k++, i++) {
  467. range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
  468. }
  469. }
  470. if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i))))
  471. return error;
  472. i = dtoh32(i);
  473. if (i == WLC_PHY_TYPE_A)
  474. range->throughput = 24000000;
  475. else
  476. range->throughput = 1500000;
  477. range->min_rts = 0;
  478. range->max_rts = 2347;
  479. range->min_frag = 256;
  480. range->max_frag = 2346;
  481. range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
  482. range->num_encoding_sizes = 4;
  483. range->encoding_size[0] = WEP1_KEY_SIZE;
  484. range->encoding_size[1] = WEP128_KEY_SIZE;
  485. #if WIRELESS_EXT > 17
  486. range->encoding_size[2] = TKIP_KEY_SIZE;
  487. #else
  488. range->encoding_size[2] = 0;
  489. #endif
  490. range->encoding_size[3] = AES_KEY_SIZE;
  491. range->min_pmp = 0;
  492. range->max_pmp = 0;
  493. range->min_pmt = 0;
  494. range->max_pmt = 0;
  495. range->pmp_flags = 0;
  496. range->pm_capa = 0;
  497. range->num_txpower = 2;
  498. range->txpower[0] = 1;
  499. range->txpower[1] = 255;
  500. range->txpower_capa = IW_TXPOW_MWATT;
  501. #if WIRELESS_EXT > 10
  502. range->we_version_compiled = WIRELESS_EXT;
  503. range->we_version_source = 19;
  504. range->retry_capa = IW_RETRY_LIMIT;
  505. range->retry_flags = IW_RETRY_LIMIT;
  506. range->r_time_flags = 0;
  507. range->min_retry = 1;
  508. range->max_retry = 255;
  509. range->min_r_time = 0;
  510. range->max_r_time = 0;
  511. #endif
  512. #if WIRELESS_EXT > 17
  513. range->enc_capa = IW_ENC_CAPA_WPA;
  514. range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
  515. range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
  516. range->enc_capa |= IW_ENC_CAPA_WPA2;
  517. IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
  518. IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
  519. IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
  520. IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
  521. IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
  522. IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
  523. #if WIRELESS_EXT >= 22 && defined(IW_SCAN_CAPA_ESSID)
  524. range->scan_capa = IW_SCAN_CAPA_ESSID;
  525. #endif
  526. #endif
  527. return 0;
  528. }
  529. static int
  530. rssi_to_qual(int rssi)
  531. {
  532. if (rssi <= WL_IW_RSSI_NO_SIGNAL)
  533. return 0;
  534. else if (rssi <= WL_IW_RSSI_VERY_LOW)
  535. return 1;
  536. else if (rssi <= WL_IW_RSSI_LOW)
  537. return 2;
  538. else if (rssi <= WL_IW_RSSI_GOOD)
  539. return 3;
  540. else if (rssi <= WL_IW_RSSI_VERY_GOOD)
  541. return 4;
  542. else
  543. return 5;
  544. }
  545. static int
  546. wl_iw_set_spy(
  547. struct net_device *dev,
  548. struct iw_request_info *info,
  549. struct iw_point *dwrq,
  550. char *extra
  551. )
  552. {
  553. wl_iw_t *iw = IW_DEV_IF(dev);
  554. struct sockaddr *addr = (struct sockaddr *) extra;
  555. int i;
  556. WL_TRACE(("%s: SIOCSIWSPY\n", dev->name));
  557. if (!extra)
  558. return -EINVAL;
  559. iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length);
  560. for (i = 0; i < iw->spy_num; i++)
  561. memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN);
  562. memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
  563. return 0;
  564. }
  565. static int
  566. wl_iw_get_spy(
  567. struct net_device *dev,
  568. struct iw_request_info *info,
  569. struct iw_point *dwrq,
  570. char *extra
  571. )
  572. {
  573. wl_iw_t *iw = IW_DEV_IF(dev);
  574. struct sockaddr *addr = (struct sockaddr *) extra;
  575. struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num];
  576. int i;
  577. WL_TRACE(("%s: SIOCGIWSPY\n", dev->name));
  578. if (!extra)
  579. return -EINVAL;
  580. dwrq->length = iw->spy_num;
  581. for (i = 0; i < iw->spy_num; i++) {
  582. memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN);
  583. addr[i].sa_family = AF_UNIX;
  584. memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
  585. iw->spy_qual[i].updated = 0;
  586. }
  587. return 0;
  588. }
  589. static int
  590. wl_iw_set_wap(
  591. struct net_device *dev,
  592. struct iw_request_info *info,
  593. struct sockaddr *awrq,
  594. char *extra
  595. )
  596. {
  597. int error = -EINVAL;
  598. #ifdef BCMDBG
  599. #endif
  600. WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
  601. if (awrq->sa_family != ARPHRD_ETHER) {
  602. WL_ERROR(("%s: Invalid Header...sa_family\n", __FUNCTION__));
  603. return -EINVAL;
  604. }
  605. if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
  606. scb_val_t scbval;
  607. bzero(&scbval, sizeof(scb_val_t));
  608. if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) {
  609. WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error));
  610. }
  611. return 0;
  612. }
  613. if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) {
  614. WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error));
  615. return error;
  616. }
  617. return 0;
  618. }
  619. static int
  620. wl_iw_get_wap(
  621. struct net_device *dev,
  622. struct iw_request_info *info,
  623. struct sockaddr *awrq,
  624. char *extra
  625. )
  626. {
  627. WL_TRACE(("%s: SIOCGIWAP\n", dev->name));
  628. awrq->sa_family = ARPHRD_ETHER;
  629. memset(awrq->sa_data, 0, ETHER_ADDR_LEN);
  630. (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN);
  631. return 0;
  632. }
  633. #if WIRELESS_EXT > 17
  634. static int
  635. wl_iw_mlme(
  636. struct net_device *dev,
  637. struct iw_request_info *info,
  638. struct sockaddr *awrq,
  639. char *extra
  640. )
  641. {
  642. struct iw_mlme *mlme;
  643. scb_val_t scbval;
  644. int error = -EINVAL;
  645. WL_TRACE(("%s: SIOCSIWMLME\n", dev->name));
  646. mlme = (struct iw_mlme *)extra;
  647. if (mlme == NULL) {
  648. WL_ERROR(("Invalid ioctl data.\n"));
  649. return error;
  650. }
  651. scbval.val = mlme->reason_code;
  652. bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN);
  653. if (mlme->cmd == IW_MLME_DISASSOC) {
  654. scbval.val = htod32(scbval.val);
  655. error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
  656. }
  657. else if (mlme->cmd == IW_MLME_DEAUTH) {
  658. scbval.val = htod32(scbval.val);
  659. error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
  660. sizeof(scb_val_t));
  661. }
  662. else {
  663. WL_ERROR(("%s: Invalid ioctl data.\n", __FUNCTION__));
  664. return error;
  665. }
  666. return error;
  667. }
  668. #endif
  669. static int
  670. wl_iw_get_aplist(
  671. struct net_device *dev,
  672. struct iw_request_info *info,
  673. struct iw_point *dwrq,
  674. char *extra
  675. )
  676. {
  677. wl_scan_results_t *list;
  678. struct sockaddr *addr = (struct sockaddr *) extra;
  679. struct iw_quality qual[IW_MAX_AP];
  680. wl_bss_info_t *bi = NULL;
  681. int error, i;
  682. uint buflen = dwrq->length;
  683. WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
  684. if (!extra)
  685. return -EINVAL;
  686. list = kmalloc(buflen, GFP_KERNEL);
  687. if (!list)
  688. return -ENOMEM;
  689. memset(list, 0, buflen);
  690. list->buflen = htod32(buflen);
  691. if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
  692. WL_ERROR(("%d: Scan results error %d\n", __LINE__, error));
  693. kfree(list);
  694. return error;
  695. }
  696. list->buflen = dtoh32(list->buflen);
  697. list->version = dtoh32(list->version);
  698. list->count = dtoh32(list->count);
  699. ASSERT(list->version == WL_BSS_INFO_VERSION);
  700. for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
  701. bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
  702. ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
  703. buflen));
  704. if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
  705. continue;
  706. memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
  707. addr[dwrq->length].sa_family = ARPHRD_ETHER;
  708. qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
  709. qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
  710. qual[dwrq->length].noise = 0x100 + bi->phy_noise;
  711. #if WIRELESS_EXT > 18
  712. qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
  713. #else
  714. qual[dwrq->length].updated = 7;
  715. #endif
  716. dwrq->length++;
  717. }
  718. kfree(list);
  719. if (dwrq->length) {
  720. memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
  721. dwrq->flags = 1;
  722. }
  723. return 0;
  724. }
  725. #if WIRELESS_EXT > 13
  726. static int
  727. wl_iw_set_scan(
  728. struct net_device *dev,
  729. struct iw_request_info *info,
  730. union iwreq_data *wrqu,
  731. char *extra
  732. )
  733. {
  734. wlc_ssid_t ssid;
  735. WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
  736. memset(&ssid, 0, sizeof(ssid));
  737. #if WIRELESS_EXT > 17
  738. if (wrqu->data.length == sizeof(struct iw_scan_req)) {
  739. if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
  740. struct iw_scan_req *req = (struct iw_scan_req *)extra;
  741. ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
  742. memcpy(ssid.SSID, req->essid, ssid.SSID_len);
  743. ssid.SSID_len = htod32(ssid.SSID_len);
  744. }
  745. }
  746. #endif
  747. (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid));
  748. return 0;
  749. }
  750. #if WIRELESS_EXT > 17
  751. static bool
  752. ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len)
  753. {
  754. uint8 *ie = *wpaie;
  755. if ((ie[1] >= 6) &&
  756. !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) {
  757. return TRUE;
  758. }
  759. ie += ie[1] + 2;
  760. *tlvs_len -= (int)(ie - *tlvs);
  761. *tlvs = ie;
  762. return FALSE;
  763. }
  764. static bool
  765. ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
  766. {
  767. uint8 *ie = *wpsie;
  768. if ((ie[1] >= 4) &&
  769. !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) {
  770. return TRUE;
  771. }
  772. ie += ie[1] + 2;
  773. *tlvs_len -= (int)(ie - *tlvs);
  774. *tlvs = ie;
  775. return FALSE;
  776. }
  777. #endif
  778. static int
  779. wl_iw_handle_scanresults_ies(char **event_p, char *end,
  780. struct iw_request_info *info, wl_bss_info_t *bi)
  781. {
  782. #if WIRELESS_EXT > 17
  783. struct iw_event iwe;
  784. char *event;
  785. event = *event_p;
  786. if (bi->ie_length) {
  787. bcm_tlv_t *ie;
  788. uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
  789. int ptr_len = bi->ie_length;
  790. if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
  791. iwe.cmd = IWEVGENIE;
  792. iwe.u.data.length = ie->len + 2;
  793. event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
  794. }
  795. ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
  796. while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
  797. if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
  798. iwe.cmd = IWEVGENIE;
  799. iwe.u.data.length = ie->len + 2;
  800. event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
  801. break;
  802. }
  803. }
  804. ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
  805. ptr_len = bi->ie_length;
  806. while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
  807. if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
  808. iwe.cmd = IWEVGENIE;
  809. iwe.u.data.length = ie->len + 2;
  810. event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
  811. break;
  812. }
  813. }
  814. *event_p = event;
  815. }
  816. #endif
  817. return 0;
  818. }
  819. static int
  820. wl_iw_get_scan(
  821. struct net_device *dev,
  822. struct iw_request_info *info,
  823. struct iw_point *dwrq,
  824. char *extra
  825. )
  826. {
  827. channel_info_t ci;
  828. wl_scan_results_t *list;
  829. struct iw_event iwe;
  830. wl_bss_info_t *bi = NULL;
  831. int error, i, j;
  832. char *event = extra, *end = extra + IW_SCAN_MAX_DATA, *value;
  833. uint buflen = dwrq->length;
  834. WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name));
  835. if (!extra)
  836. return -EINVAL;
  837. if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
  838. return error;
  839. ci.scan_channel = dtoh32(ci.scan_channel);
  840. if (ci.scan_channel)
  841. return -EAGAIN;
  842. list = kmalloc(buflen, GFP_KERNEL);
  843. if (!list)
  844. return -ENOMEM;
  845. memset(list, 0, buflen);
  846. list->buflen = htod32(buflen);
  847. if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
  848. kfree(list);
  849. return error;
  850. }
  851. list->buflen = dtoh32(list->buflen);
  852. list->version = dtoh32(list->version);
  853. list->count = dtoh32(list->count);
  854. ASSERT(list->version == WL_BSS_INFO_VERSION);
  855. for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
  856. bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
  857. ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
  858. buflen));
  859. iwe.cmd = SIOCGIWAP;
  860. iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
  861. memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
  862. event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
  863. iwe.u.data.length = dtoh32(bi->SSID_len);
  864. iwe.cmd = SIOCGIWESSID;
  865. iwe.u.data.flags = 1;
  866. event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
  867. if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
  868. iwe.cmd = SIOCGIWMODE;
  869. if (dtoh16(bi->capability) & DOT11_CAP_ESS)
  870. iwe.u.mode = IW_MODE_INFRA;
  871. else
  872. iwe.u.mode = IW_MODE_ADHOC;
  873. event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
  874. }
  875. iwe.cmd = SIOCGIWFREQ;
  876. iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
  877. CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
  878. WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
  879. iwe.u.freq.e = 6;
  880. event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
  881. iwe.cmd = IWEVQUAL;
  882. iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
  883. iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
  884. iwe.u.qual.noise = 0x100 + bi->phy_noise;
  885. event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
  886. wl_iw_handle_scanresults_ies(&event, end, info, bi);
  887. iwe.cmd = SIOCGIWENCODE;
  888. if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
  889. iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
  890. else
  891. iwe.u.data.flags = IW_ENCODE_DISABLED;
  892. iwe.u.data.length = 0;
  893. event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
  894. if (bi->rateset.count) {
  895. value = event + IW_EV_LCP_LEN;
  896. iwe.cmd = SIOCGIWRATE;
  897. iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
  898. for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
  899. iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
  900. value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
  901. IW_EV_PARAM_LEN);
  902. }
  903. event = value;
  904. }
  905. }
  906. kfree(list);
  907. dwrq->length = event - extra;
  908. dwrq->flags = 0;
  909. return 0;
  910. }
  911. #endif
  912. static int
  913. wl_iw_set_essid(
  914. struct net_device *dev,
  915. struct iw_request_info *info,
  916. struct iw_point *dwrq,
  917. char *extra
  918. )
  919. {
  920. wlc_ssid_t ssid;
  921. int error;
  922. WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
  923. memset(&ssid, 0, sizeof(ssid));
  924. if (dwrq->length && extra) {
  925. #if WIRELESS_EXT > 20
  926. ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length);
  927. #else
  928. ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1);
  929. #endif
  930. memcpy(ssid.SSID, extra, ssid.SSID_len);
  931. ssid.SSID_len = htod32(ssid.SSID_len);
  932. if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))
  933. return error;
  934. }
  935. else {
  936. scb_val_t scbval;
  937. bzero(&scbval, sizeof(scb_val_t));
  938. if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t))))
  939. return error;
  940. }
  941. return 0;
  942. }
  943. static int
  944. wl_iw_get_essid(
  945. struct net_device *dev,
  946. struct iw_request_info *info,
  947. struct iw_point *dwrq,
  948. char *extra
  949. )
  950. {
  951. wlc_ssid_t ssid;
  952. int error;
  953. WL_TRACE(("%s: SIOCGIWESSID\n", dev->name));
  954. if (!extra)
  955. return -EINVAL;
  956. if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) {
  957. WL_ERROR(("Error getting the SSID\n"));
  958. return error;
  959. }
  960. ssid.SSID_len = dtoh32(ssid.SSID_len);
  961. memcpy(extra, ssid.SSID, ssid.SSID_len);
  962. dwrq->length = ssid.SSID_len;
  963. dwrq->flags = 1;
  964. return 0;
  965. }
  966. static int
  967. wl_iw_set_nick(
  968. struct net_device *dev,
  969. struct iw_request_info *info,
  970. struct iw_point *dwrq,
  971. char *extra
  972. )
  973. {
  974. wl_iw_t *iw = IW_DEV_IF(dev);
  975. WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name));
  976. if (!extra)
  977. return -EINVAL;
  978. if (dwrq->length > sizeof(iw->nickname))
  979. return -E2BIG;
  980. memcpy(iw->nickname, extra, dwrq->length);
  981. iw->nickname[dwrq->length - 1] = '\0';
  982. return 0;
  983. }
  984. static int
  985. wl_iw_get_nick(
  986. struct net_device *dev,
  987. struct iw_request_info *info,
  988. struct iw_point *dwrq,
  989. char *extra
  990. )
  991. {
  992. wl_iw_t *iw = IW_DEV_IF(dev);
  993. WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name));
  994. if (!extra)
  995. return -EINVAL;
  996. strcpy(extra, iw->nickname);
  997. dwrq->length = strlen(extra) + 1;
  998. return 0;
  999. }
  1000. static int wl_iw_set_rate(
  1001. struct net_device *dev,
  1002. struct iw_request_info *info,
  1003. struct iw_param *vwrq,
  1004. char *extra
  1005. )
  1006. {
  1007. wl_rateset_t rateset;
  1008. int error, rate, i, error_bg, error_a;
  1009. WL_TRACE(("%s: SIOCSIWRATE\n", dev->name));
  1010. if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset))))
  1011. return error;
  1012. rateset.count = dtoh32(rateset.count);
  1013. if (vwrq->value < 0) {
  1014. rate = rateset.rates[rateset.count - 1] & 0x7f;
  1015. } else if (vwrq->value < rateset.count) {
  1016. rate = rateset.rates[vwrq->value] & 0x7f;
  1017. } else {
  1018. rate = vwrq->value / 500000;
  1019. }
  1020. if (vwrq->fixed) {
  1021. error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate);
  1022. error_a = dev_wlc_intvar_set(dev, "a_rate", rate);
  1023. if (error_bg && error_a)
  1024. return (error_bg | error_a);
  1025. } else {
  1026. error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0);
  1027. error_a = dev_wlc_intvar_set(dev, "a_rate", 0);
  1028. if (error_bg && error_a)
  1029. return (error_bg | error_a);
  1030. for (i = 0; i < rateset.count; i++)
  1031. if ((rateset.rates[i] & 0x7f) > rate)
  1032. break;
  1033. rateset.count = htod32(i);
  1034. if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset))))
  1035. return error;
  1036. }
  1037. return 0;
  1038. }
  1039. static int wl_iw_get_rate(
  1040. struct net_device *dev,
  1041. struct iw_request_info *info,
  1042. struct iw_param *vwrq,
  1043. char *extra
  1044. )
  1045. {
  1046. int error, rate;
  1047. WL_TRACE(("%s: SIOCGIWRATE\n", dev->name));
  1048. if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate))))
  1049. return error;
  1050. rate = dtoh32(rate);
  1051. vwrq->value = rate * 500000;
  1052. return 0;
  1053. }
  1054. static int
  1055. wl_iw_set_rts(
  1056. struct net_device *dev,
  1057. struct iw_request_info *info,
  1058. struct iw_param *vwrq,
  1059. char *extra
  1060. )
  1061. {
  1062. int error, rts;
  1063. WL_TRACE(("%s: SIOCSIWRTS\n", dev->name));
  1064. if (vwrq->disabled)
  1065. rts = DOT11_DEFAULT_RTS_LEN;
  1066. else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN)
  1067. return -EINVAL;
  1068. else
  1069. rts = vwrq->value;
  1070. if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts)))
  1071. return error;
  1072. return 0;
  1073. }
  1074. static int
  1075. wl_iw_get_rts(
  1076. struct net_device *dev,
  1077. struct iw_request_info *info,
  1078. struct iw_param *vwrq,
  1079. char *extra
  1080. )
  1081. {
  1082. int error, rts;
  1083. WL_TRACE(("%s: SIOCGIWRTS\n", dev->name));
  1084. if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts)))
  1085. return error;
  1086. vwrq->value = rts;
  1087. vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN);
  1088. vwrq->fixed = 1;
  1089. return 0;
  1090. }
  1091. static int
  1092. wl_iw_set_frag(
  1093. struct net_device *dev,
  1094. struct iw_request_info *info,
  1095. struct iw_param *vwrq,
  1096. char *extra
  1097. )
  1098. {
  1099. int error, frag;
  1100. WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name));
  1101. if (vwrq->disabled)
  1102. frag = DOT11_DEFAULT_FRAG_LEN;
  1103. else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN)
  1104. return -EINVAL;
  1105. else
  1106. frag = vwrq->value;
  1107. if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag)))
  1108. return error;
  1109. return 0;
  1110. }
  1111. static int
  1112. wl_iw_get_frag(
  1113. struct net_device *dev,
  1114. struct iw_request_info *info,
  1115. struct iw_param *vwrq,
  1116. char *extra
  1117. )
  1118. {
  1119. int error, fragthreshold;
  1120. WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name));
  1121. if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold)))
  1122. return error;
  1123. vwrq->value = fragthreshold;
  1124. vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN);
  1125. vwrq->fixed = 1;
  1126. return 0;
  1127. }
  1128. static int
  1129. wl_iw_set_txpow(
  1130. struct net_device *dev,
  1131. struct iw_request_info *info,
  1132. struct iw_param *vwrq,
  1133. char *extra
  1134. )
  1135. {
  1136. int error, disable;
  1137. uint16 txpwrmw;
  1138. WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name));
  1139. disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
  1140. disable += WL_RADIO_SW_DISABLE << 16;
  1141. disable = htod32(disable);
  1142. if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable))))
  1143. return error;
  1144. if (disable & WL_RADIO_SW_DISABLE)
  1145. return 0;
  1146. if (!(vwrq->flags & IW_TXPOW_MWATT))
  1147. return -EINVAL;
  1148. if (vwrq->value < 0)
  1149. return 0;
  1150. if (vwrq->value > 0xffff) txpwrmw = 0xffff;
  1151. else txpwrmw = (uint16)vwrq->value;
  1152. error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw)));
  1153. return error;
  1154. }
  1155. static int
  1156. wl_iw_get_txpow(
  1157. struct net_device *dev,
  1158. struct iw_request_info *info,
  1159. struct iw_param *vwrq,
  1160. char *extra
  1161. )
  1162. {
  1163. int error, disable, txpwrdbm;
  1164. uint8 result;
  1165. WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name));
  1166. if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) ||
  1167. (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm)))
  1168. return error;
  1169. disable = dtoh32(disable);
  1170. result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE);
  1171. vwrq->value = (int32)bcm_qdbm_to_mw(result);
  1172. vwrq->fixed = 0;
  1173. vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0;
  1174. vwrq->flags = IW_TXPOW_MWATT;
  1175. return 0;
  1176. }
  1177. #if WIRELESS_EXT > 10
  1178. static int
  1179. wl_iw_set_retry(
  1180. struct net_device *dev,
  1181. struct iw_request_info *info,
  1182. struct iw_param *vwrq,
  1183. char *extra
  1184. )
  1185. {
  1186. int error, lrl, srl;
  1187. WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name));
  1188. if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME))
  1189. return -EINVAL;
  1190. if (vwrq->flags & IW_RETRY_LIMIT) {
  1191. #if WIRELESS_EXT > 20
  1192. if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) ||
  1193. !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) {
  1194. #else
  1195. if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
  1196. #endif
  1197. lrl = htod32(vwrq->value);
  1198. if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl))))
  1199. return error;
  1200. }
  1201. #if WIRELESS_EXT > 20
  1202. if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) ||
  1203. !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) {
  1204. #else
  1205. if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) {
  1206. #endif
  1207. srl = htod32(vwrq->value);
  1208. if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl))))
  1209. return error;
  1210. }
  1211. }
  1212. return 0;
  1213. }
  1214. static int
  1215. wl_iw_get_retry(
  1216. struct net_device *dev,
  1217. struct iw_request_info *info,
  1218. struct iw_param *vwrq,
  1219. char *extra
  1220. )
  1221. {
  1222. int error, lrl, srl;
  1223. WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name));
  1224. vwrq->disabled = 0;
  1225. if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
  1226. return -EINVAL;
  1227. if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) ||
  1228. (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl))))
  1229. return error;
  1230. lrl = dtoh32(lrl);
  1231. srl = dtoh32(srl);
  1232. if (vwrq->flags & IW_RETRY_MAX) {
  1233. vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
  1234. vwrq->value = lrl;
  1235. } else {
  1236. vwrq->flags = IW_RETRY_LIMIT;
  1237. vwrq->value = srl;
  1238. if (srl != lrl)
  1239. vwrq->flags |= IW_RETRY_MIN;
  1240. }
  1241. return 0;
  1242. }
  1243. #endif
  1244. static int
  1245. wl_iw_set_encode(
  1246. struct net_device *dev,
  1247. struct iw_request_info *info,
  1248. struct iw_point *dwrq,
  1249. char *extra
  1250. )
  1251. {
  1252. wl_wsec_key_t key;
  1253. int error, val, wsec;
  1254. WL_TRACE(("%s: SIOCSIWENCODE\n", dev->name));
  1255. memset(&key, 0, sizeof(key));
  1256. if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
  1257. for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
  1258. val = htod32(key.index);
  1259. if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
  1260. return error;
  1261. val = dtoh32(val);
  1262. if (val)
  1263. break;
  1264. }
  1265. if (key.index == DOT11_MAX_DEFAULT_KEYS)
  1266. key.index = 0;
  1267. } else {
  1268. key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
  1269. if (key.index >= DOT11_MAX_DEFAULT_KEYS)
  1270. return -EINVAL;
  1271. }
  1272. wsec = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED;
  1273. if ((error = dev_wlc_intvar_set(dev, "wsec", wsec)))
  1274. return error;
  1275. if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
  1276. val = htod32(key.index);
  1277. if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val))))
  1278. return error;
  1279. } else {
  1280. key.len = dwrq->length;
  1281. if (dwrq->length > sizeof(key.data))
  1282. return -EINVAL;
  1283. memcpy(key.data, extra, dwrq->length);
  1284. key.flags = WL_PRIMARY_KEY;
  1285. switch (key.len) {
  1286. case WEP1_KEY_SIZE:
  1287. key.algo = CRYPTO_ALGO_WEP1;
  1288. break;
  1289. case WEP128_KEY_SIZE:
  1290. key.algo = CRYPTO_ALGO_WEP128;
  1291. break;
  1292. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
  1293. case TKIP_KEY_SIZE:
  1294. key.algo = CRYPTO_ALGO_TKIP;
  1295. break;
  1296. #endif
  1297. case AES_KEY_SIZE:
  1298. key.algo = CRYPTO_ALGO_AES_CCM;
  1299. break;
  1300. default:
  1301. return -EINVAL;
  1302. }
  1303. swap_key_from_BE(&key);
  1304. if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))
  1305. return error;
  1306. }
  1307. val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
  1308. val = htod32(val);
  1309. if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))
  1310. return error;
  1311. return 0;
  1312. }
  1313. static int
  1314. wl_iw_get_encode(
  1315. struct net_device *dev,
  1316. struct iw_request_info *info,
  1317. struct iw_point *dwrq,
  1318. char *extra
  1319. )
  1320. {
  1321. wl_wsec_key_t key;
  1322. int error, val, wsec, auth;
  1323. WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name));
  1324. bzero(&key, sizeof(wl_wsec_key_t));
  1325. if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
  1326. for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) {
  1327. val = key.index;
  1328. if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val))))
  1329. return error;
  1330. val = dtoh32(val);
  1331. if (val)
  1332. break;
  1333. }
  1334. } else
  1335. key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
  1336. if (key.index >= DOT11_MAX_DEFAULT_KEYS)
  1337. key.index = 0;
  1338. if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) ||
  1339. (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth))))
  1340. return error;
  1341. swap_key_to_BE(&key);
  1342. wsec = dtoh32(wsec);
  1343. auth = dtoh32(auth);
  1344. dwrq->length = MIN(IW_ENCODING_TOKEN_MAX, key.len);
  1345. dwrq->flags = key.index + 1;
  1346. if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) {
  1347. dwrq->flags |= IW_ENCODE_DISABLED;
  1348. }
  1349. if (auth) {
  1350. dwrq->flags |= IW_ENCODE_RESTRICTED;
  1351. }
  1352. if (dwrq->length && extra)
  1353. memcpy(extra, key.data, dwrq->length);
  1354. return 0;
  1355. }
  1356. static int
  1357. wl_iw_set_power(
  1358. struct net_device *dev,
  1359. struct iw_request_info *info,
  1360. struct iw_param *vwrq,
  1361. char *extra
  1362. )
  1363. {
  1364. int error, pm;
  1365. WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name));
  1366. pm = vwrq->disabled ? PM_OFF : PM_MAX;
  1367. pm = htod32(pm);
  1368. if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))
  1369. return error;
  1370. return 0;
  1371. }
  1372. static int
  1373. wl_iw_get_power(
  1374. struct net_device *dev,
  1375. struct iw_request_info *info,
  1376. struct iw_param *vwrq,
  1377. char *extra
  1378. )
  1379. {
  1380. int error, pm;
  1381. WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name));
  1382. if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))))
  1383. return error;
  1384. pm = dtoh32(pm);
  1385. vwrq->disabled = pm ? 0 : 1;
  1386. vwrq->flags = IW_POWER_ALL_R;
  1387. return 0;
  1388. }
  1389. #if WIRELESS_EXT > 17
  1390. static int
  1391. wl_iw_set_wpaie(
  1392. struct net_device *dev,
  1393. struct iw_request_info *info,
  1394. struct iw_point *iwp,
  1395. char *extra
  1396. )
  1397. {
  1398. dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
  1399. return 0;
  1400. }
  1401. static int
  1402. wl_iw_get_wpaie(
  1403. struct net_device *dev,
  1404. struct iw_request_info *info,
  1405. struct iw_point *iwp,
  1406. char *extra
  1407. )
  1408. {
  1409. WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name));
  1410. iwp->length = 64;
  1411. dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length);
  1412. return 0;
  1413. }
  1414. static int
  1415. wl_iw_set_encodeext(
  1416. struct net_device *dev,
  1417. struct iw_request_info *info,
  1418. struct iw_point *dwrq,
  1419. char *extra
  1420. )
  1421. {
  1422. wl_wsec_key_t key;
  1423. int error;
  1424. struct iw_encode_ext *iwe;
  1425. WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name));
  1426. memset(&key, 0, sizeof(key));
  1427. iwe = (struct iw_encode_ext *)extra;
  1428. if (dwrq->flags & IW_ENCODE_DISABLED) {
  1429. }
  1430. key.index = 0;
  1431. if (dwrq->flags & IW_ENCODE_INDEX)
  1432. key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
  1433. key.len = iwe->key_len;
  1434. if (!ETHER_ISMULTI(iwe->addr.sa_data))
  1435. bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN);
  1436. if (key.len == 0) {
  1437. if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
  1438. WL_WSEC(("Changing the the primary Key to %d\n", key.index));
  1439. key.index = htod32(key.index);
  1440. error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
  1441. &key.index, sizeof(key.index));
  1442. if (error)
  1443. return error;
  1444. }
  1445. else {
  1446. swap_key_from_BE(&key);
  1447. dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
  1448. }
  1449. }
  1450. else {
  1451. if (iwe->key_len > sizeof(key.data))
  1452. return -EINVAL;
  1453. WL_WSEC(("Setting the key index %d\n", key.index));
  1454. if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
  1455. WL_WSEC(("key is a Primary Key\n"));
  1456. key.flags = WL_PRIMARY_KEY;
  1457. }
  1458. bcopy((void *)iwe->key, key.data, iwe->key_len);
  1459. if (iwe->alg == IW_ENCODE_ALG_TKIP) {
  1460. uint8 keybuf[8];
  1461. bcopy(&key.data[24], keybuf, sizeof(keybuf));
  1462. bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
  1463. bcopy(keybuf, &key.data[16], sizeof(keybuf));
  1464. }
  1465. if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
  1466. uchar *ivptr;
  1467. ivptr = (uchar *)iwe->rx_seq;
  1468. key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
  1469. (ivptr[3] << 8) | ivptr[2];
  1470. key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
  1471. key.iv_initialized = TRUE;
  1472. }
  1473. switch (iwe->alg) {
  1474. case IW_ENCODE_ALG_NONE:
  1475. key.algo = CRYPTO_ALGO_OFF;
  1476. break;
  1477. case IW_ENCODE_ALG_WEP:
  1478. if (iwe->key_len == WEP1_KEY_SIZE)
  1479. key.algo = CRYPTO_ALGO_WEP1;
  1480. else
  1481. key.algo = CRYPTO_ALGO_WEP128;
  1482. break;
  1483. case IW_ENCODE_ALG_TKIP:
  1484. key.algo = CRYPTO_ALGO_TKIP;
  1485. break;
  1486. case IW_ENCODE_ALG_CCMP:
  1487. key.algo = CRYPTO_ALGO_AES_CCM;
  1488. break;
  1489. default:
  1490. break;
  1491. }
  1492. swap_key_from_BE(&key);
  1493. error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
  1494. if (error)
  1495. return error;
  1496. }
  1497. return 0;
  1498. }
  1499. #if WIRELESS_EXT > 17
  1500. struct {
  1501. pmkid_list_t pmkids;
  1502. pmkid_t foo[MAXPMKID-1];
  1503. } pmkid_list;
  1504. static int
  1505. wl_iw_set_pmksa(
  1506. struct net_device *dev,
  1507. struct iw_request_info *info,
  1508. struct iw_param *vwrq,
  1509. char *extra
  1510. )
  1511. {
  1512. struct iw_pmksa *iwpmksa;
  1513. uint i;
  1514. char eabuf[ETHER_ADDR_STR_LEN];
  1515. WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name));
  1516. iwpmksa = (struct iw_pmksa *)extra;
  1517. bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
  1518. if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
  1519. WL_TRACE(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
  1520. bzero((char *)&pmkid_list, sizeof(pmkid_list));
  1521. }
  1522. if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
  1523. pmkid_list_t pmkid, *pmkidptr;
  1524. pmkidptr = &pmkid;
  1525. bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
  1526. bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
  1527. {
  1528. uint j;
  1529. WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
  1530. bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID,
  1531. eabuf)));
  1532. for (j = 0; j < WPA2_PMKID_LEN; j++)
  1533. WL_TRACE(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
  1534. WL_TRACE(("\n"));
  1535. }
  1536. for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
  1537. if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID,
  1538. ETHER_ADDR_LEN))
  1539. break;
  1540. for (; i < pmkid_list.pmkids.npmkid; i++) {
  1541. bcopy(&pmkid_list.pmkids.pmkid[i+1].BSSID,
  1542. &pmkid_list.pmkids.pmkid[i].BSSID,
  1543. ETHER_ADDR_LEN);
  1544. bcopy(&pmkid_list.pmkids.pmkid[i+1].PMKID,
  1545. &pmkid_list.pmkids.pmkid[i].PMKID,
  1546. WPA2_PMKID_LEN);
  1547. }
  1548. pmkid_list.pmkids.npmkid--;
  1549. }
  1550. if (iwpmksa->cmd == IW_PMKSA_ADD) {
  1551. bcopy(&iwpmksa->bssid.sa_data[0],
  1552. &pmkid_list.pmkids.pmkid[pmkid_list.pmkids.npmkid].BSSID,
  1553. ETHER_ADDR_LEN);
  1554. bcopy(&iwpmksa->pmkid[0], &pmkid_list.pmkids.pmkid[pmkid_list.pmkids.npmkid].PMKID,
  1555. WPA2_PMKID_LEN);
  1556. {
  1557. uint j;
  1558. uint k;
  1559. k = pmkid_list.pmkids.npmkid;
  1560. WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
  1561. bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[k].BSSID,
  1562. eabuf)));
  1563. for (j = 0; j < WPA2_PMKID_LEN; j++)
  1564. WL_TRACE(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j]));
  1565. WL_TRACE(("\n"));
  1566. }
  1567. pmkid_list.pmkids.npmkid++;
  1568. }
  1569. WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid));
  1570. for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
  1571. uint j;
  1572. WL_TRACE(("PMKID[%d]: %s = ", i,
  1573. bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[i].BSSID,
  1574. eabuf)));
  1575. for (j = 0; j < WPA2_PMKID_LEN; j++)
  1576. WL_TRACE(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]));
  1577. printf("\n");
  1578. }
  1579. WL_TRACE(("\n"));
  1580. dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list));
  1581. return 0;
  1582. }
  1583. #endif
  1584. static int
  1585. wl_iw_get_encodeext(
  1586. struct net_device *dev,
  1587. struct iw_request_info *info,
  1588. struct iw_param *vwrq,
  1589. char *extra
  1590. )
  1591. {
  1592. WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name));
  1593. return 0;
  1594. }
  1595. static int
  1596. wl_iw_set_wpaauth(
  1597. struct net_device *dev,
  1598. struct iw_request_info *info,
  1599. struct iw_param *vwrq,
  1600. char *extra
  1601. )
  1602. {
  1603. int error = 0;
  1604. int paramid;
  1605. int paramval;
  1606. uint32 cipher_combined;
  1607. int val = 0;
  1608. wl_iw_t *iw = IW_DEV_IF(dev);
  1609. WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name));
  1610. paramid = vwrq->flags & IW_AUTH_INDEX;
  1611. paramval = vwrq->value;
  1612. WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
  1613. dev->name, paramid, paramval));
  1614. switch (paramid) {
  1615. case IW_AUTH_WPA_VERSION:
  1616. if (paramval & IW_AUTH_WPA_VERSION_DISABLED)
  1617. val = WPA_AUTH_DISABLED;
  1618. else if (paramval & (IW_AUTH_WPA_VERSION_WPA))
  1619. val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
  1620. else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
  1621. val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
  1622. WL_TRACE(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
  1623. if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
  1624. return error;
  1625. break;
  1626. case IW_AUTH_CIPHER_PAIRWISE:
  1627. case IW_AUTH_CIPHER_GROUP:
  1628. if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
  1629. iw->pwsec = paramval;
  1630. }
  1631. else {
  1632. iw->gwsec = paramval;
  1633. }
  1634. if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
  1635. return error;
  1636. cipher_combined = iw->gwsec | iw->pwsec;
  1637. val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED);
  1638. if (cipher_combined & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
  1639. val |= WEP_ENABLED;
  1640. if (cipher_combined & IW_AUTH_CIPHER_TKIP)
  1641. val |= TKIP_ENABLED;
  1642. if (cipher_combined & IW_AUTH_CIPHER_CCMP)
  1643. val |= AES_ENABLED;
  1644. if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
  1645. return error;
  1646. break;
  1647. case IW_AUTH_KEY_MGMT:
  1648. if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
  1649. return error;
  1650. if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
  1651. if (paramval & IW_AUTH_KEY_MGMT_PSK)
  1652. val = WPA_AUTH_PSK;
  1653. else
  1654. val = WPA_AUTH_UNSPECIFIED;
  1655. }
  1656. else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
  1657. if (paramval & IW_AUTH_KEY_MGMT_PSK)
  1658. val = WPA2_AUTH_PSK;
  1659. else
  1660. val = WPA2_AUTH_UNSPECIFIED;
  1661. }
  1662. WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
  1663. if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
  1664. return error;
  1665. break;
  1666. case IW_AUTH_TKIP_COUNTERMEASURES:
  1667. dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)&paramval, 1);
  1668. break;
  1669. case IW_AUTH_80211_AUTH_ALG:
  1670. WL_ERROR(("Setting the D11auth %d\n", paramval));
  1671. if (paramval & IW_AUTH_ALG_OPEN_SYSTEM)
  1672. val = 0;
  1673. else if (paramval & IW_AUTH_ALG_SHARED_KEY)
  1674. val = 1;
  1675. else
  1676. error = 1;
  1677. if (!error && (error = dev_wlc_intvar_set(dev, "auth", val)))
  1678. return error;
  1679. break;
  1680. case IW_AUTH_WPA_ENABLED:
  1681. if (paramval == 0) {
  1682. val = 0;
  1683. WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
  1684. error = dev_wlc_intvar_set(dev, "wpa_auth", val);
  1685. return error;
  1686. }
  1687. else {
  1688. }
  1689. break;
  1690. case IW_AUTH_DROP_UNENCRYPTED:
  1691. dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)&paramval, 1);
  1692. break;
  1693. case IW_AUTH_RX_UNENCRYPTED_EAPOL:
  1694. dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
  1695. break;
  1696. #if WIRELESS_EXT > 17
  1697. case IW_AUTH_ROAMING_CONTROL:
  1698. WL_TRACE(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
  1699. break;
  1700. case IW_AUTH_PRIVACY_INVOKED:
  1701. WL_TRACE(("%s: IW_AUTH_PRIVACY_INVOKED\n", __FUNCTION__));
  1702. break;
  1703. #endif
  1704. default:
  1705. break;
  1706. }
  1707. return 0;
  1708. }
  1709. #define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK))
  1710. static int
  1711. wl_iw_get_wpaauth(
  1712. struct net_device *dev,
  1713. struct iw_request_info *info,
  1714. struct iw_param *vwrq,
  1715. char *extra
  1716. )
  1717. {
  1718. int error;
  1719. int paramid;
  1720. int paramval = 0;
  1721. int val;
  1722. wl_iw_t *iw = IW_DEV_IF(dev);
  1723. WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name));
  1724. paramid = vwrq->flags & IW_AUTH_INDEX;
  1725. switch (paramid) {
  1726. case IW_AUTH_WPA_VERSION:
  1727. if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
  1728. return error;
  1729. if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED))
  1730. paramval = IW_AUTH_WPA_VERSION_DISABLED;
  1731. else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED))
  1732. paramval = IW_AUTH_WPA_VERSION_WPA;
  1733. else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED))
  1734. paramval = IW_AUTH_WPA_VERSION_WPA2;
  1735. break;
  1736. case IW_AUTH_CIPHER_PAIRWISE:
  1737. paramval = iw->pwsec;
  1738. break;
  1739. case IW_AUTH_CIPHER_GROUP:
  1740. paramval = iw->gwsec;
  1741. break;
  1742. case IW_AUTH_KEY_MGMT:
  1743. if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
  1744. return error;
  1745. if (VAL_PSK(val))
  1746. paramval = IW_AUTH_KEY_MGMT_PSK;
  1747. else
  1748. paramval = IW_AUTH_KEY_MGMT_802_1X;
  1749. break;
  1750. case IW_AUTH_TKIP_COUNTERMEASURES:
  1751. dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)&paramval, 1);
  1752. break;
  1753. case IW_AUTH_DROP_UNENCRYPTED:
  1754. dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)&paramval, 1);
  1755. break;
  1756. case IW_AUTH_RX_UNENCRYPTED_EAPOL:
  1757. dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)&paramval, 1);
  1758. break;
  1759. case IW_AUTH_80211_AUTH_ALG:
  1760. if ((error = dev_wlc_intvar_get(dev, "auth", &val)))
  1761. return error;
  1762. if (!val)
  1763. paramval = IW_AUTH_ALG_OPEN_SYSTEM;
  1764. else
  1765. paramval = IW_AUTH_ALG_SHARED_KEY;
  1766. break;
  1767. case IW_AUTH_WPA_ENABLED:
  1768. if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val)))
  1769. return error;
  1770. if (val)
  1771. paramval = TRUE;
  1772. else
  1773. paramval = FALSE;
  1774. break;
  1775. #if WIRELESS_EXT > 17
  1776. case IW_AUTH_ROAMING_CONTROL:
  1777. WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
  1778. break;
  1779. case IW_AUTH_PRIVACY_INVOKED:
  1780. WL_ERROR(("%s: IW_AUTH_PRIVACY_INVOKED\n", __FUNCTION__));
  1781. break;
  1782. #endif
  1783. }
  1784. vwrq->value = paramval;
  1785. return 0;
  1786. }
  1787. #endif
  1788. static const iw_handler wl_iw_handler[] =
  1789. {
  1790. (iw_handler) wl_iw_config_commit,
  1791. (iw_handler) wl_iw_get_name,
  1792. (iw_handler) NULL,
  1793. (iw_handler) NULL,
  1794. (iw_handler) wl_iw_set_freq,
  1795. (iw_handler) wl_iw_get_freq,
  1796. (iw_handler) wl_iw_set_mode,
  1797. (iw_handler) wl_iw_get_mode,
  1798. (iw_handler) NULL,
  1799. (iw_handler) NULL,
  1800. (iw_handler) NULL,
  1801. (iw_handler) wl_iw_get_range,
  1802. (iw_handler) NULL,
  1803. (iw_handler) NULL,
  1804. (iw_handler) NULL,
  1805. (iw_handler) NULL,
  1806. (iw_handler) wl_iw_set_spy,
  1807. (iw_handler) wl_iw_get_spy,
  1808. (iw_handler) NULL,
  1809. (iw_handler) NULL,
  1810. (iw_handler) wl_iw_set_wap,
  1811. (iw_handler) wl_iw_get_wap,
  1812. #if WIRELESS_EXT > 17
  1813. (iw_handler) wl_iw_mlme,
  1814. #else
  1815. (iw_handler) NULL,
  1816. #endif
  1817. (iw_handler) wl_iw_get_aplist,
  1818. #if WIRELESS_EXT > 13
  1819. (iw_handler) wl_iw_set_scan,
  1820. (iw_handler) wl_iw_get_scan,
  1821. #else
  1822. (iw_handler) NULL,
  1823. (iw_handler) NULL,
  1824. #endif
  1825. (iw_handler) wl_iw_set_essid,
  1826. (iw_handler) wl_iw_get_essid,
  1827. (iw_handler) wl_iw_set_nick,
  1828. (iw_handler) wl_iw_get_nick,
  1829. (iw_handler) NULL,
  1830. (iw_handler) NULL,
  1831. (iw_handler) wl_iw_set_rate,
  1832. (iw_handler) wl_iw_get_rate,
  1833. (iw_handler) wl_iw_set_rts,
  1834. (iw_handler) wl_iw_get_rts,
  1835. (iw_handler) wl_iw_set_frag,
  1836. (iw_handler) wl_iw_get_frag,
  1837. (iw_handler) wl_iw_set_txpow,
  1838. (iw_handler) wl_iw_get_txpow,
  1839. #if WIRELESS_EXT > 10
  1840. (iw_handler) wl_iw_set_retry,
  1841. (iw_handler) wl_iw_get_retry,
  1842. #endif
  1843. (iw_handler) wl_iw_set_encode,
  1844. (iw_handler) wl_iw_get_encode,
  1845. (iw_handler) wl_iw_set_power,
  1846. (iw_handler) wl_iw_get_power,
  1847. #if WIRELESS_EXT > 17
  1848. (iw_handler) NULL,
  1849. (iw_handler) NULL,
  1850. (iw_handler) wl_iw_set_wpaie,
  1851. (iw_handler) wl_iw_get_wpaie,
  1852. (iw_handler) wl_iw_set_wpaauth,
  1853. (iw_handler) wl_iw_get_wpaauth,
  1854. (iw_handler) wl_iw_set_encodeext,
  1855. (iw_handler) wl_iw_get_encodeext,
  1856. (iw_handler) wl_iw_set_pmksa,
  1857. #endif
  1858. };
  1859. #if WIRELESS_EXT > 12
  1860. enum {
  1861. WL_IW_SET_LEDDC = SIOCIWFIRSTPRIV,
  1862. WL_IW_SET_VLANMODE,
  1863. WL_IW_SET_PM
  1864. };
  1865. static iw_handler wl_iw_priv_handler[] = {
  1866. wl_iw_set_leddc,
  1867. wl_iw_set_vlanmode,
  1868. wl_iw_set_pm
  1869. };
  1870. static struct iw_priv_args wl_iw_priv_args[] = {
  1871. {
  1872. WL_IW_SET_LEDDC,
  1873. IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  1874. 0,
  1875. "set_leddc"
  1876. },
  1877. {
  1878. WL_IW_SET_VLANMODE,
  1879. IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
  1880. 0,
  1881. "set_vlanmode"
  1882. },
  1883. {
  1884. WL_IW_SET_PM,
  1885. IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED

Large files files are truncated, but you can click here to view the full file