hostap.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. /*
  2. * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * File: hostap.c
  20. *
  21. * Purpose: handle hostap deamon ioctl input/out functions
  22. *
  23. * Author: Lyndon Chen
  24. *
  25. * Date: Oct. 20, 2003
  26. *
  27. * Functions:
  28. *
  29. * Revision History:
  30. *
  31. */
  32. #include "hostap.h"
  33. #include "iocmd.h"
  34. #include "mac.h"
  35. #include "card.h"
  36. #include "baseband.h"
  37. #include "wpactl.h"
  38. #include "key.h"
  39. #define VIAWGET_HOSTAPD_MAX_BUF_SIZE 1024
  40. #define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT0
  41. #define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
  42. #define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
  43. /*--------------------- Static Definitions -------------------------*/
  44. /*--------------------- Static Classes ----------------------------*/
  45. /*--------------------- Static Functions --------------------------*/
  46. /*--------------------- Export Variables --------------------------*/
  47. /*
  48. * Description:
  49. * register net_device (AP) for hostap deamon
  50. *
  51. * Parameters:
  52. * In:
  53. * pDevice -
  54. * rtnl_locked -
  55. * Out:
  56. *
  57. * Return Value:
  58. *
  59. */
  60. static int hostap_enable_hostapd(struct vnt_private *pDevice, int rtnl_locked)
  61. {
  62. struct vnt_private *apdev_priv;
  63. struct net_device *dev = pDevice->dev;
  64. int ret;
  65. const struct net_device_ops apdev_netdev_ops = {
  66. .ndo_start_xmit = pDevice->tx_80211,
  67. };
  68. pr_debug("%s: Enabling hostapd mode\n", dev->name);
  69. pDevice->apdev = alloc_etherdev(sizeof(*apdev_priv));
  70. if (pDevice->apdev == NULL)
  71. return -ENOMEM;
  72. apdev_priv = netdev_priv(pDevice->apdev);
  73. *apdev_priv = *pDevice;
  74. eth_hw_addr_inherit(pDevice->apdev, dev);
  75. pDevice->apdev->netdev_ops = &apdev_netdev_ops;
  76. pDevice->apdev->type = ARPHRD_IEEE80211;
  77. pDevice->apdev->base_addr = dev->base_addr;
  78. pDevice->apdev->irq = dev->irq;
  79. pDevice->apdev->mem_start = dev->mem_start;
  80. pDevice->apdev->mem_end = dev->mem_end;
  81. sprintf(pDevice->apdev->name, "%sap", dev->name);
  82. if (rtnl_locked)
  83. ret = register_netdevice(pDevice->apdev);
  84. else
  85. ret = register_netdev(pDevice->apdev);
  86. if (ret) {
  87. pr_debug("%s: register_netdevice(AP) failed!\n",
  88. dev->name);
  89. free_netdev(pDevice->apdev);
  90. pDevice->apdev = NULL;
  91. return -1;
  92. }
  93. pr_debug("%s: Registered netdevice %s for AP management\n",
  94. dev->name, pDevice->apdev->name);
  95. KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
  96. return 0;
  97. }
  98. /*
  99. * Description:
  100. * unregister net_device(AP)
  101. *
  102. * Parameters:
  103. * In:
  104. * pDevice -
  105. * rtnl_locked -
  106. * Out:
  107. *
  108. * Return Value:
  109. *
  110. */
  111. static int hostap_disable_hostapd(struct vnt_private *pDevice, int rtnl_locked)
  112. {
  113. pr_debug("%s: disabling hostapd mode\n", pDevice->dev->name);
  114. if (pDevice->apdev && pDevice->apdev->name && pDevice->apdev->name[0]) {
  115. if (rtnl_locked)
  116. unregister_netdevice(pDevice->apdev);
  117. else
  118. unregister_netdev(pDevice->apdev);
  119. pr_debug("%s: Netdevice %s unregistered\n",
  120. pDevice->dev->name, pDevice->apdev->name);
  121. }
  122. if (pDevice->apdev)
  123. free_netdev(pDevice->apdev);
  124. pDevice->apdev = NULL;
  125. pDevice->bEnable8021x = false;
  126. pDevice->bEnableHostWEP = false;
  127. pDevice->bEncryptionEnable = false;
  128. /* 4.2007-0118-03,<Add> by EinsnLiu */
  129. /* execute some clear work */
  130. pDevice->pMgmt->byCSSPK = KEY_CTL_NONE;
  131. pDevice->pMgmt->byCSSGK = KEY_CTL_NONE;
  132. KeyvInitTable(&pDevice->sKey, pDevice->PortOffset);
  133. return 0;
  134. }
  135. /*
  136. * Description:
  137. * Set enable/disable hostapd mode
  138. *
  139. * Parameters:
  140. * In:
  141. * pDevice -
  142. * rtnl_locked -
  143. * Out:
  144. *
  145. * Return Value:
  146. *
  147. */
  148. int vt6655_hostap_set_hostapd(struct vnt_private *pDevice,
  149. int val, int rtnl_locked)
  150. {
  151. if (val < 0 || val > 1)
  152. return -EINVAL;
  153. if (pDevice->bEnableHostapd == val)
  154. return 0;
  155. pDevice->bEnableHostapd = val;
  156. if (val)
  157. return hostap_enable_hostapd(pDevice, rtnl_locked);
  158. else
  159. return hostap_disable_hostapd(pDevice, rtnl_locked);
  160. }
  161. /*
  162. * Description:
  163. * remove station function supported for hostap deamon
  164. *
  165. * Parameters:
  166. * In:
  167. * pDevice -
  168. * param -
  169. * Out:
  170. *
  171. * Return Value:
  172. *
  173. */
  174. static int hostap_remove_sta(struct vnt_private *pDevice,
  175. struct viawget_hostapd_param *param)
  176. {
  177. unsigned int uNodeIndex;
  178. if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, param->sta_addr, &uNodeIndex))
  179. BSSvRemoveOneNode(pDevice, uNodeIndex);
  180. else
  181. return -ENOENT;
  182. return 0;
  183. }
  184. /*
  185. * Description:
  186. * add a station from hostap deamon
  187. *
  188. * Parameters:
  189. * In:
  190. * pDevice -
  191. * param -
  192. * Out:
  193. *
  194. * Return Value:
  195. *
  196. */
  197. static int hostap_add_sta(struct vnt_private *pDevice,
  198. struct viawget_hostapd_param *param)
  199. {
  200. PSMgmtObject pMgmt = pDevice->pMgmt;
  201. unsigned int uNodeIndex;
  202. if (!BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex))
  203. BSSvCreateOneNode(pDevice, &uNodeIndex);
  204. memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, param->sta_addr, WLAN_ADDR_LEN);
  205. pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC;
  206. pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = param->u.add_sta.capability;
  207. /* TODO listenInterval */
  208. pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = false;
  209. pMgmt->sNodeDBTable[uNodeIndex].bySuppRate = param->u.add_sta.tx_supp_rates;
  210. /* set max tx rate */
  211. pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate =
  212. pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate;
  213. /* set max basic rate */
  214. pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate = RATE_2M;
  215. /* Todo: check sta preamble, if ap can't support, set status code */
  216. pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble =
  217. WLAN_GET_CAP_INFO_SHORTPREAMBLE(pMgmt->sNodeDBTable[uNodeIndex].wCapInfo);
  218. pMgmt->sNodeDBTable[uNodeIndex].wAID = (unsigned short)param->u.add_sta.aid;
  219. pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = jiffies;
  220. pr_debug("Add STA AID= %d\n", pMgmt->sNodeDBTable[uNodeIndex].wAID);
  221. pr_debug("MAC=%pM\n", param->sta_addr);
  222. pr_debug("Max Support rate = %d\n",
  223. pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);
  224. return 0;
  225. }
  226. /*
  227. * Description:
  228. * get station info
  229. *
  230. * Parameters:
  231. * In:
  232. * pDevice -
  233. * param -
  234. * Out:
  235. *
  236. * Return Value:
  237. *
  238. */
  239. static int hostap_get_info_sta(struct vnt_private *pDevice,
  240. struct viawget_hostapd_param *param)
  241. {
  242. PSMgmtObject pMgmt = pDevice->pMgmt;
  243. unsigned int uNodeIndex;
  244. if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
  245. param->u.get_info_sta.inactive_sec =
  246. (jiffies - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ;
  247. } else {
  248. return -ENOENT;
  249. }
  250. return 0;
  251. }
  252. /*
  253. * Description:
  254. * set station flag
  255. *
  256. * Parameters:
  257. * In:
  258. * pDevice -
  259. * param -
  260. * Out:
  261. *
  262. * Return Value:
  263. *
  264. */
  265. static int hostap_set_flags_sta(struct vnt_private *pDevice,
  266. struct viawget_hostapd_param *param)
  267. {
  268. PSMgmtObject pMgmt = pDevice->pMgmt;
  269. unsigned int uNodeIndex;
  270. if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) {
  271. pMgmt->sNodeDBTable[uNodeIndex].dwFlags |= param->u.set_flags_sta.flags_or;
  272. pMgmt->sNodeDBTable[uNodeIndex].dwFlags &= param->u.set_flags_sta.flags_and;
  273. pr_debug(" dwFlags = %x\n",
  274. (unsigned int)pMgmt->sNodeDBTable[uNodeIndex].dwFlags);
  275. } else {
  276. return -ENOENT;
  277. }
  278. return 0;
  279. }
  280. /*
  281. * Description:
  282. * set generic element (wpa ie)
  283. *
  284. * Parameters:
  285. * In:
  286. * pDevice -
  287. * param -
  288. * Out:
  289. *
  290. * Return Value:
  291. *
  292. */
  293. static int hostap_set_generic_element(struct vnt_private *pDevice,
  294. struct viawget_hostapd_param *param)
  295. {
  296. PSMgmtObject pMgmt = pDevice->pMgmt;
  297. if (param->u.generic_elem.len > sizeof(pMgmt->abyWPAIE))
  298. return -EINVAL;
  299. memcpy(pMgmt->abyWPAIE,
  300. param->u.generic_elem.data,
  301. param->u.generic_elem.len
  302. );
  303. pMgmt->wWPAIELen = param->u.generic_elem.len;
  304. pr_debug("pMgmt->wWPAIELen = %d\n", pMgmt->wWPAIELen);
  305. /* disable wpa */
  306. if (pMgmt->wWPAIELen == 0) {
  307. pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
  308. pr_debug(" No WPAIE, Disable WPA\n");
  309. } else {
  310. /* enable wpa */
  311. if ((pMgmt->abyWPAIE[0] == WLAN_EID_RSN_WPA) ||
  312. (pMgmt->abyWPAIE[0] == WLAN_EID_RSN)) {
  313. pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
  314. pr_debug("Set WPAIE enable WPA\n");
  315. } else
  316. return -EINVAL;
  317. }
  318. return 0;
  319. }
  320. /*
  321. * Description:
  322. * flush station nodes table.
  323. *
  324. * Parameters:
  325. * In:
  326. * pDevice -
  327. * Out:
  328. *
  329. * Return Value:
  330. *
  331. */
  332. static void hostap_flush_sta(struct vnt_private *pDevice)
  333. {
  334. /* reserved node index =0 for multicast node. */
  335. BSSvClearNodeDBTable(pDevice, 1);
  336. pDevice->uAssocCount = 0;
  337. }
  338. /*
  339. * Description:
  340. * set each stations encryption key
  341. *
  342. * Parameters:
  343. * In:
  344. * pDevice -
  345. * param -
  346. * Out:
  347. *
  348. * Return Value:
  349. *
  350. */
  351. static int hostap_set_encryption(struct vnt_private *pDevice,
  352. struct viawget_hostapd_param *param,
  353. int param_len)
  354. {
  355. PSMgmtObject pMgmt = pDevice->pMgmt;
  356. unsigned long dwKeyIndex = 0;
  357. unsigned char abyKey[MAX_KEY_LEN];
  358. unsigned char abySeq[MAX_KEY_LEN];
  359. u64 KeyRSC;
  360. unsigned char byKeyDecMode = KEY_CTL_WEP;
  361. int iNodeIndex = -1;
  362. int ii;
  363. bool bKeyTableFull = false;
  364. unsigned short wKeyCtl = 0;
  365. param->u.crypt.err = 0;
  366. if (param->u.crypt.alg > WPA_ALG_CCMP)
  367. return -EINVAL;
  368. if ((param->u.crypt.idx > 3) || (param->u.crypt.key_len > MAX_KEY_LEN)) {
  369. param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED;
  370. pr_debug(" HOSTAP_CRYPT_ERR_KEY_SET_FAILED\n");
  371. return -EINVAL;
  372. }
  373. if (is_broadcast_ether_addr(param->sta_addr)) {
  374. if (param->u.crypt.idx >= MAX_GROUP_KEY)
  375. return -EINVAL;
  376. iNodeIndex = 0;
  377. } else {
  378. if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == false) {
  379. param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
  380. pr_debug(" HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
  381. return -EINVAL;
  382. }
  383. }
  384. pr_debug(" hostap_set_encryption: sta_index %d\n", iNodeIndex);
  385. pr_debug(" hostap_set_encryption: alg %d\n", param->u.crypt.alg);
  386. if (param->u.crypt.alg == WPA_ALG_NONE) {
  387. if (pMgmt->sNodeDBTable[iNodeIndex].bOnFly) {
  388. if (!KeybRemoveKey(&(pDevice->sKey),
  389. param->sta_addr,
  390. pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex,
  391. pDevice->PortOffset)) {
  392. pr_debug("KeybRemoveKey fail\n");
  393. }
  394. pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
  395. }
  396. pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = 0;
  397. pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = 0;
  398. pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = 0;
  399. pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = 0;
  400. pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0;
  401. pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0;
  402. pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = 0;
  403. memset(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
  404. 0,
  405. MAX_KEY_LEN
  406. );
  407. return 0;
  408. }
  409. memcpy(abyKey, param->u.crypt.key, param->u.crypt.key_len);
  410. /* copy to node key tbl */
  411. pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = param->u.crypt.idx;
  412. pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = param->u.crypt.key_len;
  413. memcpy(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
  414. param->u.crypt.key,
  415. param->u.crypt.key_len
  416. );
  417. dwKeyIndex = (unsigned long)(param->u.crypt.idx);
  418. if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
  419. pDevice->byKeyIndex = (unsigned char)dwKeyIndex;
  420. pDevice->bTransmitKey = true;
  421. dwKeyIndex |= (1 << 31);
  422. }
  423. if (param->u.crypt.alg == WPA_ALG_WEP) {
  424. if ((pDevice->bEnable8021x == false) || (iNodeIndex == 0)) {
  425. KeybSetDefaultKey(&(pDevice->sKey),
  426. dwKeyIndex & ~(BIT30 | USE_KEYRSC),
  427. param->u.crypt.key_len,
  428. NULL,
  429. abyKey,
  430. KEY_CTL_WEP,
  431. pDevice->PortOffset,
  432. pDevice->byLocalID);
  433. } else {
  434. /* 8021x enable, individual key */
  435. dwKeyIndex |= (1 << 30); /* set pairwise key */
  436. if (KeybSetKey(&(pDevice->sKey),
  437. &param->sta_addr[0],
  438. dwKeyIndex & ~(USE_KEYRSC),
  439. param->u.crypt.key_len,
  440. (u64 *) &KeyRSC,
  441. (unsigned char *)abyKey,
  442. KEY_CTL_WEP,
  443. pDevice->PortOffset,
  444. pDevice->byLocalID)) {
  445. pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
  446. } else {
  447. /* Key Table Full */
  448. pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
  449. bKeyTableFull = true;
  450. }
  451. }
  452. pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
  453. pDevice->bEncryptionEnable = true;
  454. pMgmt->byCSSPK = KEY_CTL_WEP;
  455. pMgmt->byCSSGK = KEY_CTL_WEP;
  456. pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = KEY_CTL_WEP;
  457. pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex;
  458. return 0;
  459. }
  460. if (param->u.crypt.seq) {
  461. memcpy(&abySeq, param->u.crypt.seq, 8);
  462. for (ii = 0; ii < 8; ii++)
  463. KeyRSC |= (u64)abySeq[ii] << (ii * 8);
  464. dwKeyIndex |= 1 << 29;
  465. pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = KeyRSC;
  466. }
  467. if (param->u.crypt.alg == WPA_ALG_TKIP) {
  468. if (param->u.crypt.key_len != MAX_KEY_LEN)
  469. return -EINVAL;
  470. pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
  471. byKeyDecMode = KEY_CTL_TKIP;
  472. pMgmt->byCSSPK = KEY_CTL_TKIP;
  473. pMgmt->byCSSGK = KEY_CTL_TKIP;
  474. }
  475. if (param->u.crypt.alg == WPA_ALG_CCMP) {
  476. if ((param->u.crypt.key_len != AES_KEY_LEN) ||
  477. (pDevice->byLocalID <= REV_ID_VT3253_A1))
  478. return -EINVAL;
  479. pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
  480. byKeyDecMode = KEY_CTL_CCMP;
  481. pMgmt->byCSSPK = KEY_CTL_CCMP;
  482. pMgmt->byCSSGK = KEY_CTL_CCMP;
  483. }
  484. if (iNodeIndex == 0) {
  485. KeybSetDefaultKey(&(pDevice->sKey),
  486. dwKeyIndex,
  487. param->u.crypt.key_len,
  488. (u64 *) &KeyRSC,
  489. abyKey,
  490. byKeyDecMode,
  491. pDevice->PortOffset,
  492. pDevice->byLocalID);
  493. pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
  494. } else {
  495. dwKeyIndex |= (1 << 30); /* set pairwise key */
  496. if (KeybSetKey(&(pDevice->sKey),
  497. &param->sta_addr[0],
  498. dwKeyIndex,
  499. param->u.crypt.key_len,
  500. (u64 *) &KeyRSC,
  501. (unsigned char *)abyKey,
  502. byKeyDecMode,
  503. pDevice->PortOffset,
  504. pDevice->byLocalID)) {
  505. pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;
  506. } else {
  507. /* Key Table Full */
  508. pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
  509. bKeyTableFull = true;
  510. pr_debug(" Key Table Full\n");
  511. }
  512. }
  513. if (bKeyTableFull) {
  514. wKeyCtl &= 0x7F00; /* clear all key control filed */
  515. wKeyCtl |= (byKeyDecMode << 4);
  516. wKeyCtl |= (byKeyDecMode);
  517. wKeyCtl |= 0x0044; /* use group key for all address */
  518. wKeyCtl |= 0x4000; /* disable KeyTable[MAX_KEY_TABLE-1] on-fly to genernate rx int */
  519. MACvSetDefaultKeyCtl(pDevice->PortOffset, wKeyCtl, MAX_KEY_TABLE-1, pDevice->byLocalID);
  520. }
  521. pr_debug(" Set key sta_index= %d\n", iNodeIndex);
  522. pr_debug(" tx_index=%d len=%d\n",
  523. param->u.crypt.idx, param->u.crypt.key_len);
  524. pr_debug(" key=%x-%x-%x-%x-%x-xxxxx\n",
  525. pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0],
  526. pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[1],
  527. pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[2],
  528. pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[3],
  529. pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[4]);
  530. /* set wep key */
  531. pDevice->bEncryptionEnable = true;
  532. pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = byKeyDecMode;
  533. pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex;
  534. pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0;
  535. pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0;
  536. return 0;
  537. }
  538. /*
  539. * Description:
  540. * get each stations encryption key
  541. *
  542. * Parameters:
  543. * In:
  544. * pDevice -
  545. * param -
  546. * Out:
  547. *
  548. * Return Value:
  549. *
  550. */
  551. static int hostap_get_encryption(struct vnt_private *pDevice,
  552. struct viawget_hostapd_param *param,
  553. int param_len)
  554. {
  555. PSMgmtObject pMgmt = pDevice->pMgmt;
  556. int ii;
  557. int iNodeIndex = 0;
  558. param->u.crypt.err = 0;
  559. if (is_broadcast_ether_addr(param->sta_addr)) {
  560. iNodeIndex = 0;
  561. } else {
  562. if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == false) {
  563. param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
  564. pr_debug("hostap_get_encryption: HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
  565. return -EINVAL;
  566. }
  567. }
  568. pr_debug("hostap_get_encryption: %d\n", iNodeIndex);
  569. memset(param->u.crypt.seq, 0, 8);
  570. for (ii = 0; ii < 8; ii++)
  571. param->u.crypt.seq[ii] = (unsigned char)pMgmt->sNodeDBTable[iNodeIndex].KeyRSC >> (ii * 8);
  572. return 0;
  573. }
  574. /*
  575. * Description:
  576. * vt6655_hostap_ioctl main function supported for hostap deamon.
  577. *
  578. * Parameters:
  579. * In:
  580. * pDevice -
  581. * iw_point -
  582. * Out:
  583. *
  584. * Return Value:
  585. *
  586. */
  587. int vt6655_hostap_ioctl(struct vnt_private *pDevice, struct iw_point *p)
  588. {
  589. struct viawget_hostapd_param *param;
  590. int ret = 0;
  591. int ap_ioctl = 0;
  592. if (p->length < sizeof(struct viawget_hostapd_param) ||
  593. p->length > VIAWGET_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
  594. return -EINVAL;
  595. param = kmalloc((int)p->length, GFP_KERNEL);
  596. if (param == NULL)
  597. return -ENOMEM;
  598. if (copy_from_user(param, p->pointer, p->length)) {
  599. ret = -EFAULT;
  600. goto out;
  601. }
  602. switch (param->cmd) {
  603. case VIAWGET_HOSTAPD_SET_ENCRYPTION:
  604. pr_debug("VIAWGET_HOSTAPD_SET_ENCRYPTION\n");
  605. spin_lock_irq(&pDevice->lock);
  606. ret = hostap_set_encryption(pDevice, param, p->length);
  607. spin_unlock_irq(&pDevice->lock);
  608. break;
  609. case VIAWGET_HOSTAPD_GET_ENCRYPTION:
  610. pr_debug("VIAWGET_HOSTAPD_GET_ENCRYPTION\n");
  611. spin_lock_irq(&pDevice->lock);
  612. ret = hostap_get_encryption(pDevice, param, p->length);
  613. spin_unlock_irq(&pDevice->lock);
  614. break;
  615. case VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR:
  616. pr_debug("VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR\n");
  617. ret = -EOPNOTSUPP;
  618. goto out;
  619. case VIAWGET_HOSTAPD_FLUSH:
  620. pr_debug("VIAWGET_HOSTAPD_FLUSH\n");
  621. spin_lock_irq(&pDevice->lock);
  622. hostap_flush_sta(pDevice);
  623. spin_unlock_irq(&pDevice->lock);
  624. break;
  625. case VIAWGET_HOSTAPD_ADD_STA:
  626. pr_debug("VIAWGET_HOSTAPD_ADD_STA\n");
  627. spin_lock_irq(&pDevice->lock);
  628. ret = hostap_add_sta(pDevice, param);
  629. spin_unlock_irq(&pDevice->lock);
  630. break;
  631. case VIAWGET_HOSTAPD_REMOVE_STA:
  632. pr_debug("VIAWGET_HOSTAPD_REMOVE_STA\n");
  633. spin_lock_irq(&pDevice->lock);
  634. ret = hostap_remove_sta(pDevice, param);
  635. spin_unlock_irq(&pDevice->lock);
  636. break;
  637. case VIAWGET_HOSTAPD_GET_INFO_STA:
  638. pr_debug("VIAWGET_HOSTAPD_GET_INFO_STA\n");
  639. ret = hostap_get_info_sta(pDevice, param);
  640. ap_ioctl = 1;
  641. break;
  642. case VIAWGET_HOSTAPD_SET_FLAGS_STA:
  643. pr_debug("VIAWGET_HOSTAPD_SET_FLAGS_STA\n");
  644. ret = hostap_set_flags_sta(pDevice, param);
  645. break;
  646. case VIAWGET_HOSTAPD_MLME:
  647. pr_debug("VIAWGET_HOSTAPD_MLME\n");
  648. ret = -EOPNOTSUPP;
  649. goto out;
  650. case VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT:
  651. pr_debug("VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT\n");
  652. ret = hostap_set_generic_element(pDevice, param);
  653. break;
  654. case VIAWGET_HOSTAPD_SCAN_REQ:
  655. pr_debug("VIAWGET_HOSTAPD_SCAN_REQ\n");
  656. ret = -EOPNOTSUPP;
  657. goto out;
  658. case VIAWGET_HOSTAPD_STA_CLEAR_STATS:
  659. pr_debug("VIAWGET_HOSTAPD_STA_CLEAR_STATS\n");
  660. ret = -EOPNOTSUPP;
  661. goto out;
  662. default:
  663. pr_debug("vt6655_hostap_ioctl: unknown cmd=%d\n",
  664. (int)param->cmd);
  665. ret = -EOPNOTSUPP;
  666. goto out;
  667. }
  668. if ((ret == 0) && ap_ioctl) {
  669. if (copy_to_user(p->pointer, param, p->length))
  670. ret = -EFAULT;
  671. }
  672. out:
  673. kfree(param);
  674. return ret;
  675. }