driver_prism54.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. /*
  2. * hostapd / Driver interaction with Prism54 PIMFOR interface
  3. * Copyright (c) 2004, Bell Kin <bell_kin@pek.com.tw>
  4. * based on hostap driver.c, ieee802_11.c
  5. * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * Alternatively, this software may be distributed under the terms of BSD
  12. * license.
  13. *
  14. * See README and COPYING for more details.
  15. */
  16. #include "includes.h"
  17. #include <sys/ioctl.h>
  18. #include <sys/select.h>
  19. #ifdef USE_KERNEL_HEADERS
  20. #include <asm/types.h>
  21. #include <linux/if_packet.h>
  22. #include <linux/if_ether.h> /* The L2 protocols */
  23. #include <linux/if_arp.h>
  24. #include <linux/wireless.h>
  25. #else /* USE_KERNEL_HEADERS */
  26. #include <net/if_arp.h>
  27. #include <netpacket/packet.h>
  28. #include "wireless_copy.h"
  29. #endif /* USE_KERNEL_HEADERS */
  30. #include "hostapd.h"
  31. #include "driver.h"
  32. #include "ieee802_1x.h"
  33. #include "eloop.h"
  34. #include "ieee802_11.h"
  35. #include "prism54.h"
  36. #include "wpa.h"
  37. #include "radius/radius.h"
  38. #include "sta_info.h"
  39. #include "accounting.h"
  40. const int PIM_BUF_SIZE = 4096;
  41. struct prism54_driver_data {
  42. struct hostapd_data *hapd;
  43. char iface[IFNAMSIZ + 1];
  44. int sock; /* raw packet socket for 802.3 access */
  45. int pim_sock; /* socket for pimfor packet */
  46. char macs[2007][6];
  47. };
  48. static int mac_id_refresh(struct prism54_driver_data *data, int id, char *mac)
  49. {
  50. if (id < 0 || id > 2006) {
  51. return -1;
  52. }
  53. memcpy(&data->macs[id][0], mac, ETH_ALEN);
  54. return 0;
  55. }
  56. static char * mac_id_get(struct prism54_driver_data *data, int id)
  57. {
  58. if (id < 0 || id > 2006) {
  59. return NULL;
  60. }
  61. return &data->macs[id][0];
  62. }
  63. /* wait for a specific pimfor, timeout in 10ms resolution */
  64. /* pim_sock must be non-block to prevent dead lock from no response */
  65. /* or same response type in series */
  66. static int prism54_waitpim(void *priv, unsigned long oid, void *buf, int len,
  67. int timeout)
  68. {
  69. struct prism54_driver_data *drv = priv;
  70. struct timeval tv, stv, ctv;
  71. fd_set pfd;
  72. int rlen;
  73. pimdev_hdr *pkt;
  74. pkt = malloc(8192);
  75. if (pkt == NULL)
  76. return -1;
  77. FD_ZERO(&pfd);
  78. gettimeofday(&stv, NULL);
  79. do {
  80. FD_SET(drv->pim_sock, &pfd);
  81. tv.tv_sec = 0;
  82. tv.tv_usec = 10000;
  83. if (select(drv->pim_sock + 1, &pfd, NULL, NULL, &tv)) {
  84. rlen = recv(drv->pim_sock, pkt, 8192, 0);
  85. if (rlen > 0) {
  86. if (pkt->oid == htonl(oid)) {
  87. if (rlen <= len) {
  88. if (buf != NULL) {
  89. memcpy(buf, pkt, rlen);
  90. }
  91. free(pkt);
  92. return rlen;
  93. } else {
  94. printf("buffer too small\n");
  95. free(pkt);
  96. return -1;
  97. }
  98. } else {
  99. gettimeofday(&ctv, NULL);
  100. continue;
  101. }
  102. }
  103. }
  104. gettimeofday(&ctv, NULL);
  105. } while (((ctv.tv_sec - stv.tv_sec) * 100 +
  106. (ctv.tv_usec - stv.tv_usec) / 10000) > timeout);
  107. free(pkt);
  108. return 0;
  109. }
  110. /* send an eapol packet */
  111. static int prism54_send_eapol(void *priv, const u8 *addr,
  112. const u8 *data, size_t data_len, int encrypt,
  113. const u8 *own_addr)
  114. {
  115. struct prism54_driver_data *drv = priv;
  116. ieee802_3_hdr *hdr;
  117. size_t len;
  118. u8 *pos;
  119. int res;
  120. len = sizeof(*hdr) + data_len;
  121. hdr = os_zalloc(len);
  122. if (hdr == NULL) {
  123. printf("malloc() failed for prism54_send_data(len=%lu)\n",
  124. (unsigned long) len);
  125. return -1;
  126. }
  127. memcpy(&hdr->da[0], addr, ETH_ALEN);
  128. memcpy(&hdr->sa[0], own_addr, ETH_ALEN);
  129. hdr->type = htons(ETH_P_PAE);
  130. pos = (u8 *) (hdr + 1);
  131. memcpy(pos, data, data_len);
  132. res = send(drv->sock, hdr, len, 0);
  133. free(hdr);
  134. if (res < 0) {
  135. perror("hostapd_send_eapol: send");
  136. printf("hostapd_send_eapol - packet len: %lu - failed\n",
  137. (unsigned long) len);
  138. }
  139. return res;
  140. }
  141. /* open data channel(auth-1) or eapol only(unauth-0) */
  142. static int prism54_set_sta_authorized(void *priv, const u8 *addr,
  143. int authorized)
  144. {
  145. struct prism54_driver_data *drv = priv;
  146. pimdev_hdr *hdr;
  147. char *pos;
  148. hdr = malloc(sizeof(*hdr) + ETH_ALEN);
  149. if (hdr == NULL)
  150. return -1;
  151. hdr->op = htonl(PIMOP_SET);
  152. if (authorized) {
  153. hdr->oid = htonl(DOT11_OID_EAPAUTHSTA);
  154. } else {
  155. hdr->oid = htonl(DOT11_OID_EAPUNAUTHSTA);
  156. }
  157. pos = (char *) (hdr + 1);
  158. memcpy(pos, addr, ETH_ALEN);
  159. send(drv->pim_sock, hdr, sizeof(*hdr) + ETH_ALEN, 0);
  160. prism54_waitpim(priv, hdr->oid, hdr, sizeof(*hdr) + ETH_ALEN, 10);
  161. free(hdr);
  162. return 0;
  163. }
  164. static int
  165. prism54_sta_set_flags(void *priv, const u8 *addr, int total_flags,
  166. int flags_or, int flags_and)
  167. {
  168. /* For now, only support setting Authorized flag */
  169. if (flags_or & WLAN_STA_AUTHORIZED)
  170. return prism54_set_sta_authorized(priv, addr, 1);
  171. if (flags_and & WLAN_STA_AUTHORIZED)
  172. return prism54_set_sta_authorized(priv, addr, 0);
  173. return 0;
  174. }
  175. /* set per station key */
  176. static int prism54_set_encryption(const char *ifname, void *priv,
  177. const char *alg, const u8 *addr,
  178. int idx, const u8 *key, size_t key_len,
  179. int txkey)
  180. {
  181. struct prism54_driver_data *drv = priv;
  182. pimdev_hdr *hdr;
  183. struct obj_stakey *keys;
  184. u8 *buf;
  185. size_t blen;
  186. int ret = 0;
  187. blen = sizeof(struct obj_stakey) + sizeof(pimdev_hdr);
  188. hdr = malloc(blen);
  189. if (hdr == NULL) {
  190. printf("memory low\n");
  191. return -1;
  192. }
  193. keys = (struct obj_stakey *) &hdr[1];
  194. if (!addr) {
  195. memset(&keys->address[0], 0xff, ETH_ALEN);
  196. } else {
  197. memcpy(&keys->address[0], addr, ETH_ALEN);
  198. }
  199. if (!strcmp(alg, "WEP")) {
  200. keys->type = DOT11_PRIV_WEP;
  201. } else if (!strcmp(alg, "TKIP")) {
  202. keys->type = DOT11_PRIV_TKIP;
  203. } else if (!strcmp(alg, "none")) {
  204. /* the only way to clear the key is to deauth it */
  205. /* and prism54 is capable to receive unencrypted packet */
  206. /* so we do nothing here */
  207. free(hdr);
  208. return 0;
  209. } else {
  210. printf("bad auth type: %s\n", alg);
  211. }
  212. buf = (u8 *) &keys->key[0];
  213. keys->length = key_len;
  214. keys->keyid = idx;
  215. keys->options = htons(DOT11_STAKEY_OPTION_DEFAULTKEY);
  216. keys->reserved = 0;
  217. hdr->op = htonl(PIMOP_SET);
  218. hdr->oid = htonl(DOT11_OID_STAKEY);
  219. memcpy(buf, key, key_len);
  220. ret = send(drv->pim_sock, hdr, blen, 0);
  221. if (ret < 0) {
  222. free(hdr);
  223. return ret;
  224. }
  225. prism54_waitpim(priv, hdr->oid, hdr, blen, 10);
  226. free(hdr);
  227. return 0;
  228. }
  229. /* get TKIP station sequence counter, prism54 is only 6 bytes */
  230. static int prism54_get_seqnum(const char *ifname, void *priv, const u8 *addr,
  231. int idx, u8 *seq)
  232. {
  233. struct prism54_driver_data *drv = priv;
  234. struct obj_stasc *stasc;
  235. pimdev_hdr *hdr;
  236. size_t blen;
  237. int ret = 0;
  238. blen = sizeof(*stasc) + sizeof(*hdr);
  239. hdr = malloc(blen);
  240. if (hdr == NULL)
  241. return -1;
  242. stasc = (struct obj_stasc *) &hdr[1];
  243. if (addr == NULL)
  244. memset(&stasc->address[0], 0xff, ETH_ALEN);
  245. else
  246. memcpy(&stasc->address[0], addr, ETH_ALEN);
  247. hdr->oid = htonl(DOT11_OID_STASC);
  248. hdr->op = htonl(PIMOP_GET);
  249. stasc->keyid = idx;
  250. if (send(drv->pim_sock,hdr,blen,0) <= 0) {
  251. free(hdr);
  252. return -1;
  253. }
  254. if (prism54_waitpim(priv, DOT11_OID_STASC, hdr, blen, 10) <= 0) {
  255. ret = -1;
  256. } else {
  257. if (hdr->op == (int) htonl(PIMOP_RESPONSE)) {
  258. memcpy(seq + 2, &stasc->sc_high, ETH_ALEN);
  259. memset(seq, 0, 2);
  260. } else {
  261. ret = -1;
  262. }
  263. }
  264. free(hdr);
  265. return ret;
  266. }
  267. /* include unencrypted, set mlme autolevel to extended */
  268. static int prism54_init_1x(void *priv)
  269. {
  270. struct prism54_driver_data *drv = priv;
  271. pimdev_hdr *hdr;
  272. unsigned long *ul;
  273. int blen = sizeof(*hdr) + sizeof(*ul);
  274. hdr = malloc(blen);
  275. if (hdr == NULL)
  276. return -1;
  277. ul = (unsigned long *) &hdr[1];
  278. hdr->op = htonl(PIMOP_SET);
  279. hdr->oid = htonl(DOT11_OID_EXUNENCRYPTED);
  280. *ul = htonl(DOT11_BOOL_TRUE); /* not accept */
  281. send(drv->pim_sock, hdr, blen, 0);
  282. prism54_waitpim(priv, DOT11_OID_EXUNENCRYPTED, hdr, blen, 10);
  283. hdr->op = htonl(PIMOP_SET);
  284. hdr->oid = htonl(DOT11_OID_MLMEAUTOLEVEL);
  285. *ul = htonl(DOT11_MLME_EXTENDED);
  286. send(drv->pim_sock, hdr, blen, 0);
  287. prism54_waitpim(priv, DOT11_OID_MLMEAUTOLEVEL, hdr, blen, 10);
  288. hdr->op = htonl(PIMOP_SET);
  289. hdr->oid = htonl(DOT11_OID_DOT1XENABLE);
  290. *ul = htonl(DOT11_BOOL_TRUE);
  291. send(drv->pim_sock, hdr, blen, 0);
  292. prism54_waitpim(priv, DOT11_OID_DOT1XENABLE, hdr, blen, 10);
  293. hdr->op = htonl(PIMOP_SET);
  294. hdr->oid = htonl(DOT11_OID_AUTHENABLE);
  295. *ul = htonl(DOT11_AUTH_OS); /* OS */
  296. send(drv->pim_sock, hdr, blen, 0);
  297. prism54_waitpim(priv, DOT11_OID_AUTHENABLE, hdr, blen, 10);
  298. free(hdr);
  299. return 0;
  300. }
  301. static int prism54_set_privacy_invoked(const char *ifname, void *priv,
  302. int flag)
  303. {
  304. struct prism54_driver_data *drv = priv;
  305. pimdev_hdr *hdr;
  306. unsigned long *ul;
  307. int ret;
  308. int blen = sizeof(*hdr) + sizeof(*ul);
  309. hdr = malloc(blen);
  310. if (hdr == NULL)
  311. return -1;
  312. ul = (unsigned long *) &hdr[1];
  313. hdr->op = htonl(PIMOP_SET);
  314. hdr->oid = htonl(DOT11_OID_PRIVACYINVOKED);
  315. if (flag) {
  316. *ul = htonl(DOT11_BOOL_TRUE); /* has privacy */
  317. } else {
  318. *ul = 0;
  319. }
  320. ret = send(drv->pim_sock, hdr, blen, 0);
  321. if (ret >= 0) {
  322. ret = prism54_waitpim(priv, DOT11_OID_PRIVACYINVOKED, hdr,
  323. blen, 10);
  324. }
  325. free(hdr);
  326. return ret;
  327. }
  328. static int prism54_ioctl_setiwessid(const char *ifname, void *priv,
  329. const u8 *buf, int len)
  330. {
  331. #if 0
  332. struct prism54_driver_data *drv = priv;
  333. struct iwreq iwr;
  334. memset(&iwr, 0, sizeof(iwr));
  335. os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
  336. iwr.u.essid.flags = 1; /* SSID active */
  337. iwr.u.essid.pointer = (caddr_t) buf;
  338. iwr.u.essid.length = len + 1;
  339. if (ioctl(drv->pim_sock, SIOCSIWESSID, &iwr) < 0) {
  340. perror("ioctl[SIOCSIWESSID]");
  341. printf("len=%d\n", len);
  342. return -1;
  343. }
  344. #endif
  345. return 0;
  346. }
  347. /* kick all stations */
  348. /* does not work during init, but at least it won't crash firmware */
  349. static int prism54_flush(void *priv)
  350. {
  351. struct prism54_driver_data *drv = priv;
  352. struct obj_mlmeex *mlme;
  353. pimdev_hdr *hdr;
  354. int ret;
  355. unsigned int i;
  356. long *nsta;
  357. int blen = sizeof(*hdr) + sizeof(*mlme);
  358. char *mac_id;
  359. hdr = os_zalloc(blen);
  360. if (hdr == NULL)
  361. return -1;
  362. mlme = (struct obj_mlmeex *) &hdr[1];
  363. nsta = (long *) &hdr[1];
  364. hdr->op = htonl(PIMOP_GET);
  365. hdr->oid = htonl(DOT11_OID_CLIENTS);
  366. ret = send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(long), 0);
  367. ret = prism54_waitpim(priv, DOT11_OID_CLIENTS, hdr, blen, 10);
  368. if ((ret < 0) || (hdr->op != (int) htonl(PIMOP_RESPONSE)) ||
  369. (le_to_host32(*nsta) > 2007)) {
  370. free(hdr);
  371. return 0;
  372. }
  373. for (i = 0; i < le_to_host32(*nsta); i++) {
  374. mlme->id = -1;
  375. mac_id = mac_id_get(drv, i);
  376. if (mac_id)
  377. memcpy(&mlme->address[0], mac_id, ETH_ALEN);
  378. mlme->code = host_to_le16(WLAN_REASON_UNSPECIFIED);
  379. mlme->state = htons(DOT11_STATE_NONE);
  380. mlme->size = 0;
  381. hdr->op = htonl(PIMOP_SET);
  382. hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX);
  383. ret = send(drv->pim_sock, hdr, blen, 0);
  384. prism54_waitpim(priv, DOT11_OID_DISASSOCIATEEX, hdr, blen,
  385. 100);
  386. }
  387. for (i = 0; i < le_to_host32(*nsta); i++) {
  388. mlme->id = -1;
  389. mac_id = mac_id_get(drv, i);
  390. if (mac_id)
  391. memcpy(&mlme->address[0], mac_id, ETH_ALEN);
  392. mlme->code = host_to_le16(WLAN_REASON_UNSPECIFIED);
  393. mlme->state = htons(DOT11_STATE_NONE);
  394. mlme->size = 0;
  395. hdr->op = htonl(PIMOP_SET);
  396. hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX);
  397. ret = send(drv->pim_sock, hdr, blen, 0);
  398. prism54_waitpim(priv, DOT11_OID_DEAUTHENTICATEEX, hdr, blen,
  399. 100);
  400. }
  401. free(hdr);
  402. return 0;
  403. }
  404. static int prism54_sta_deauth(void *priv, const u8 *addr, int reason)
  405. {
  406. struct prism54_driver_data *drv = priv;
  407. pimdev_hdr *hdr;
  408. struct obj_mlmeex *mlme;
  409. int ret;
  410. int blen = sizeof(*hdr) + sizeof(*mlme);
  411. hdr = malloc(blen);
  412. if (hdr == NULL)
  413. return -1;
  414. mlme = (struct obj_mlmeex *) &hdr[1];
  415. hdr->op = htonl(PIMOP_SET);
  416. hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX);
  417. memcpy(&mlme->address[0], addr, ETH_ALEN);
  418. mlme->id = -1;
  419. mlme->state = htons(DOT11_STATE_NONE);
  420. mlme->code = host_to_le16(reason);
  421. mlme->size = 0;
  422. ret = send(drv->pim_sock, hdr, blen, 0);
  423. prism54_waitpim(priv, DOT11_OID_DEAUTHENTICATEEX, hdr, blen, 10);
  424. free(hdr);
  425. return ret;
  426. }
  427. static int prism54_sta_disassoc(void *priv, const u8 *addr, int reason)
  428. {
  429. struct prism54_driver_data *drv = priv;
  430. pimdev_hdr *hdr;
  431. struct obj_mlmeex *mlme;
  432. int ret;
  433. int blen = sizeof(*hdr) + sizeof(*mlme);
  434. hdr = malloc(blen);
  435. if (hdr == NULL)
  436. return -1;
  437. mlme = (struct obj_mlmeex *) &hdr[1];
  438. hdr->op = htonl(PIMOP_SET);
  439. hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX);
  440. memcpy(&mlme->address[0], addr, ETH_ALEN);
  441. mlme->id = -1;
  442. mlme->state = htons(DOT11_STATE_NONE);
  443. mlme->code = host_to_le16(reason);
  444. mlme->size = 0;
  445. ret = send(drv->pim_sock, hdr, blen, 0);
  446. prism54_waitpim(priv, DOT11_OID_DISASSOCIATEEX, hdr, blen, 10);
  447. free(hdr);
  448. return ret;
  449. }
  450. static int prism54_get_inact_sec(void *priv, const u8 *addr)
  451. {
  452. struct prism54_driver_data *drv = priv;
  453. pimdev_hdr *hdr;
  454. struct obj_sta *sta;
  455. int blen = sizeof(*hdr) + sizeof(*sta);
  456. int ret;
  457. hdr = malloc(blen);
  458. if (hdr == NULL)
  459. return -1;
  460. hdr->op = htonl(PIMOP_GET);
  461. hdr->oid = htonl(DOT11_OID_CLIENTFIND);
  462. sta = (struct obj_sta *) &hdr[1];
  463. memcpy(&sta->address[0], addr, ETH_ALEN);
  464. ret = send(drv->pim_sock, hdr, blen, 0);
  465. ret = prism54_waitpim(priv, DOT11_OID_CLIENTFIND, hdr, blen, 10);
  466. if (ret != blen) {
  467. printf("get_inact_sec: bad return %d\n", ret);
  468. free(hdr);
  469. return -1;
  470. }
  471. if (hdr->op != (int) htonl(PIMOP_RESPONSE)) {
  472. printf("get_inact_sec: bad resp\n");
  473. free(hdr);
  474. return -1;
  475. }
  476. free(hdr);
  477. return le_to_host16(sta->age);
  478. }
  479. /* set attachments */
  480. static int prism54_set_generic_elem(const char *ifname, void *priv,
  481. const u8 *elem, size_t elem_len)
  482. {
  483. struct prism54_driver_data *drv = priv;
  484. pimdev_hdr *hdr;
  485. char *pos;
  486. struct obj_attachment_hdr *attach;
  487. size_t blen = sizeof(*hdr) + sizeof(*attach) + elem_len;
  488. hdr = os_zalloc(blen);
  489. if (hdr == NULL) {
  490. printf("%s: memory low\n", __func__);
  491. return -1;
  492. }
  493. hdr->op = htonl(PIMOP_SET);
  494. hdr->oid = htonl(DOT11_OID_ATTACHMENT);
  495. attach = (struct obj_attachment_hdr *)&hdr[1];
  496. attach->type = DOT11_PKT_BEACON;
  497. attach->id = -1;
  498. attach->size = host_to_le16((short)elem_len);
  499. pos = ((char*) attach) + sizeof(*attach);
  500. if (elem)
  501. memcpy(pos, elem, elem_len);
  502. send(drv->pim_sock, hdr, blen, 0);
  503. attach->type = DOT11_PKT_PROBE_RESP;
  504. send(drv->pim_sock, hdr, blen, 0);
  505. free(hdr);
  506. return 0;
  507. }
  508. /* tell the card to auth the sta */
  509. static void prism54_handle_probe(struct prism54_driver_data *drv,
  510. void *buf, size_t len)
  511. {
  512. struct obj_mlmeex *mlme;
  513. pimdev_hdr *hdr;
  514. struct sta_info *sta;
  515. hdr = (pimdev_hdr *)buf;
  516. mlme = (struct obj_mlmeex *) &hdr[1];
  517. sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
  518. if (sta != NULL) {
  519. if (sta->flags & (WLAN_STA_AUTH | WLAN_STA_ASSOC))
  520. return;
  521. }
  522. if (len < sizeof(*mlme)) {
  523. printf("bad probe packet\n");
  524. return;
  525. }
  526. mlme->state = htons(DOT11_STATE_AUTHING);
  527. mlme->code = 0;
  528. hdr->op = htonl(PIMOP_SET);
  529. hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX);
  530. mlme->size = 0;
  531. send(drv->pim_sock, hdr, sizeof(*hdr)+sizeof(*mlme), 0);
  532. }
  533. static void prism54_handle_deauth(struct prism54_driver_data *drv,
  534. void *buf, size_t len)
  535. {
  536. struct obj_mlme *mlme;
  537. pimdev_hdr *hdr;
  538. struct sta_info *sta;
  539. char *mac_id;
  540. hdr = (pimdev_hdr *) buf;
  541. mlme = (struct obj_mlme *) &hdr[1];
  542. sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
  543. mac_id = mac_id_get(drv, mlme->id);
  544. if (sta == NULL || mac_id == NULL)
  545. return;
  546. memcpy(&mlme->address[0], mac_id, ETH_ALEN);
  547. sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
  548. wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
  549. sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
  550. ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
  551. ap_free_sta(drv->hapd, sta);
  552. }
  553. static void prism54_handle_disassoc(struct prism54_driver_data *drv,
  554. void *buf, size_t len)
  555. {
  556. struct obj_mlme *mlme;
  557. pimdev_hdr *hdr;
  558. struct sta_info *sta;
  559. char *mac_id;
  560. hdr = (pimdev_hdr *) buf;
  561. mlme = (struct obj_mlme *) &hdr[1];
  562. mac_id = mac_id_get(drv, mlme->id);
  563. if (mac_id == NULL)
  564. return;
  565. memcpy(&mlme->address[0], mac_id, ETH_ALEN);
  566. sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
  567. if (sta == NULL) {
  568. return;
  569. }
  570. sta->flags &= ~WLAN_STA_ASSOC;
  571. wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
  572. sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
  573. ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
  574. accounting_sta_stop(drv->hapd, sta);
  575. ieee802_1x_free_station(sta);
  576. }
  577. /* to auth it, just allow it now, later for os/sk */
  578. static void prism54_handle_auth(struct prism54_driver_data *drv,
  579. void *buf, size_t len)
  580. {
  581. struct obj_mlmeex *mlme;
  582. pimdev_hdr *hdr;
  583. struct sta_info *sta;
  584. int resp;
  585. hdr = (pimdev_hdr *) buf;
  586. mlme = (struct obj_mlmeex *) &hdr[1];
  587. if (len < sizeof(*mlme)) {
  588. printf("bad auth packet\n");
  589. return;
  590. }
  591. if (mlme->state == htons(DOT11_STATE_AUTHING)) {
  592. sta = ap_sta_add(drv->hapd, (u8 *) &mlme->address[0]);
  593. if (drv->hapd->tkip_countermeasures) {
  594. resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
  595. goto fail;
  596. }
  597. mac_id_refresh(drv, mlme->id, &mlme->address[0]);
  598. if (!sta) {
  599. resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
  600. goto fail;
  601. }
  602. sta->flags &= ~WLAN_STA_PREAUTH;
  603. ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
  604. sta->flags |= WLAN_STA_AUTH;
  605. wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
  606. mlme->code = 0;
  607. mlme->state=htons(DOT11_STATE_AUTH);
  608. hdr->op = htonl(PIMOP_SET);
  609. hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX);
  610. mlme->size = 0;
  611. sta->timeout_next = STA_NULLFUNC;
  612. send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
  613. }
  614. return;
  615. fail:
  616. printf("auth fail: %x\n", resp);
  617. mlme->code = host_to_le16(resp);
  618. mlme->size = 0;
  619. if (sta)
  620. sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
  621. hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX);
  622. hdr->op = htonl(PIMOP_SET);
  623. send(drv->pim_sock, hdr, sizeof(*hdr)+sizeof(*mlme), 0);
  624. }
  625. /* do the wpa thing */
  626. static void prism54_handle_assoc(struct prism54_driver_data *drv,
  627. void *buf, size_t len)
  628. {
  629. pimdev_hdr *hdr;
  630. struct obj_mlmeex *mlme;
  631. struct ieee802_11_elems elems;
  632. struct sta_info *sta;
  633. u8 *wpa_ie;
  634. u8 *cb;
  635. int ieofs = 0;
  636. size_t wpa_ie_len;
  637. int resp, new_assoc;
  638. char *mac_id;
  639. resp = 0;
  640. hdr = (pimdev_hdr *) buf;
  641. mlme = (struct obj_mlmeex *) &hdr[1];
  642. switch (ntohl(hdr->oid)) {
  643. case DOT11_OID_ASSOCIATE:
  644. case DOT11_OID_REASSOCIATE:
  645. mlme->size = 0;
  646. default:
  647. break;
  648. }
  649. if ((mlme->state == (int) htonl(DOT11_STATE_ASSOCING)) ||
  650. (mlme->state == (int) htonl(DOT11_STATE_REASSOCING))) {
  651. if (len < sizeof(pimdev_hdr) + sizeof(struct obj_mlme)) {
  652. printf("bad assoc packet\n");
  653. return;
  654. }
  655. mac_id = mac_id_get(drv, mlme->id);
  656. if (mac_id == NULL)
  657. return;
  658. memcpy(&mlme->address[0], mac_id, ETH_ALEN);
  659. sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
  660. if (sta == NULL) {
  661. printf("cannot get sta\n");
  662. return;
  663. }
  664. cb = (u8 *) &mlme->data[0];
  665. if (hdr->oid == htonl(DOT11_OID_ASSOCIATEEX)) {
  666. ieofs = 4;
  667. } else if (hdr->oid == htonl(DOT11_OID_REASSOCIATEEX)) {
  668. ieofs = 10;
  669. }
  670. if (le_to_host16(mlme->size) <= ieofs) {
  671. printf("attach too small\n");
  672. resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
  673. goto fail;
  674. }
  675. if (ieee802_11_parse_elems(drv->hapd, cb + ieofs,
  676. le_to_host16(mlme->size) - ieofs,
  677. &elems, 1) == ParseFailed) {
  678. printf("STA " MACSTR " sent invalid association "
  679. "request\n", MAC2STR(sta->addr));
  680. resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
  681. goto fail;
  682. }
  683. if ((drv->hapd->conf->wpa & WPA_PROTO_RSN) &&
  684. elems.rsn_ie) {
  685. wpa_ie = elems.rsn_ie;
  686. wpa_ie_len = elems.rsn_ie_len;
  687. } else if ((drv->hapd->conf->wpa & WPA_PROTO_WPA) &&
  688. elems.wpa_ie) {
  689. wpa_ie = elems.wpa_ie;
  690. wpa_ie_len = elems.wpa_ie_len;
  691. } else {
  692. wpa_ie = NULL;
  693. wpa_ie_len = 0;
  694. }
  695. if (drv->hapd->conf->wpa && wpa_ie == NULL) {
  696. printf("STA " MACSTR ": No WPA/RSN IE in association "
  697. "request\n", MAC2STR(sta->addr));
  698. resp = WLAN_STATUS_INVALID_IE;
  699. goto fail;
  700. }
  701. if (drv->hapd->conf->wpa) {
  702. int res;
  703. wpa_ie -= 2;
  704. wpa_ie_len += 2;
  705. if (sta->wpa_sm == NULL)
  706. sta->wpa_sm = wpa_auth_sta_init(
  707. drv->hapd->wpa_auth, sta->addr);
  708. if (sta->wpa_sm == NULL) {
  709. printf("Failed to initialize WPA state "
  710. "machine\n");
  711. resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
  712. goto fail;
  713. }
  714. res = wpa_validate_wpa_ie(drv->hapd->wpa_auth,
  715. sta->wpa_sm,
  716. wpa_ie, wpa_ie_len,
  717. NULL, 0);
  718. if (res == WPA_INVALID_GROUP)
  719. resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
  720. else if (res == WPA_INVALID_PAIRWISE)
  721. resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
  722. else if (res == WPA_INVALID_AKMP)
  723. resp = WLAN_STATUS_AKMP_NOT_VALID;
  724. else if (res == WPA_ALLOC_FAIL)
  725. resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
  726. else if (res != WPA_IE_OK)
  727. resp = WLAN_STATUS_INVALID_IE;
  728. if (resp != WLAN_STATUS_SUCCESS)
  729. goto fail;
  730. }
  731. hdr->oid = (hdr->oid == htonl(DOT11_OID_ASSOCIATEEX)) ?
  732. htonl(DOT11_OID_ASSOCIATEEX) :
  733. htonl(DOT11_OID_REASSOCIATEEX);
  734. hdr->op = htonl(PIMOP_SET);
  735. mlme->code = 0;
  736. mlme->state = htons(DOT11_STATE_ASSOC);
  737. mlme->size = 0;
  738. send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
  739. return;
  740. } else if (mlme->state==htons(DOT11_STATE_ASSOC)) {
  741. if (len < sizeof(pimdev_hdr) + sizeof(struct obj_mlme)) {
  742. printf("bad assoc packet\n");
  743. return;
  744. }
  745. mac_id = mac_id_get(drv, mlme->id);
  746. if (mac_id == NULL)
  747. return;
  748. memcpy(&mlme->address[0], mac_id, ETH_ALEN);
  749. sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
  750. if (sta == NULL) {
  751. printf("cannot get sta\n");
  752. return;
  753. }
  754. new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
  755. sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
  756. wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
  757. hostapd_new_assoc_sta(drv->hapd, sta, !new_assoc);
  758. ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
  759. sta->timeout_next = STA_NULLFUNC;
  760. return;
  761. }
  762. return;
  763. fail:
  764. printf("Prism54: assoc fail: %x\n", resp);
  765. mlme->code = host_to_le16(resp);
  766. mlme->size = 0;
  767. mlme->state = htons(DOT11_STATE_ASSOCING);
  768. hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX);
  769. hdr->op = htonl(PIMOP_SET);
  770. sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
  771. send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
  772. }
  773. static void handle_pim(int sock, void *eloop_ctx, void *sock_ctx)
  774. {
  775. struct prism54_driver_data *drv = eloop_ctx;
  776. int len;
  777. pimdev_hdr *hdr;
  778. hdr = malloc(PIM_BUF_SIZE);
  779. if (hdr == NULL)
  780. return;
  781. len = recv(sock, hdr, PIM_BUF_SIZE, 0);
  782. if (len < 0) {
  783. perror("recv");
  784. free(hdr);
  785. return;
  786. }
  787. if (len < 8) {
  788. printf("handle_pim: too short (%d)\n", len);
  789. free(hdr);
  790. return;
  791. }
  792. if (hdr->op != (int) htonl(PIMOP_TRAP)) {
  793. free(hdr);
  794. return;
  795. }
  796. switch (ntohl(hdr->oid)) {
  797. case DOT11_OID_PROBE:
  798. prism54_handle_probe(drv, hdr, len);
  799. break;
  800. case DOT11_OID_DEAUTHENTICATEEX:
  801. case DOT11_OID_DEAUTHENTICATE:
  802. prism54_handle_deauth(drv, hdr, len);
  803. break;
  804. case DOT11_OID_DISASSOCIATEEX:
  805. case DOT11_OID_DISASSOCIATE:
  806. prism54_handle_disassoc(drv, hdr, len);
  807. break;
  808. case DOT11_OID_AUTHENTICATEEX:
  809. case DOT11_OID_AUTHENTICATE:
  810. prism54_handle_auth(drv, hdr, len);
  811. break;
  812. case DOT11_OID_ASSOCIATEEX:
  813. case DOT11_OID_REASSOCIATEEX:
  814. case DOT11_OID_ASSOCIATE:
  815. case DOT11_OID_REASSOCIATE:
  816. prism54_handle_assoc(drv, hdr, len);
  817. default:
  818. break;
  819. }
  820. free(hdr);
  821. }
  822. static void handle_802_3(int sock, void *eloop_ctx, void *sock_ctx)
  823. {
  824. struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
  825. int len;
  826. ieee802_3_hdr *hdr;
  827. hdr = malloc(PIM_BUF_SIZE);
  828. if (hdr == NULL)
  829. return;
  830. len = recv(sock, hdr, PIM_BUF_SIZE, 0);
  831. if (len < 0) {
  832. perror("recv");
  833. free(hdr);
  834. return;
  835. }
  836. if (len < 14) {
  837. wpa_printf(MSG_MSGDUMP, "handle_802_3: too short (%d)", len);
  838. free(hdr);
  839. return;
  840. }
  841. if (hdr->type == htons(ETH_P_PAE)) {
  842. ieee802_1x_receive(hapd, (u8 *) &hdr->sa[0], (u8 *) &hdr[1],
  843. len - sizeof(*hdr));
  844. }
  845. free(hdr);
  846. }
  847. static int prism54_init_sockets(struct prism54_driver_data *drv)
  848. {
  849. struct hostapd_data *hapd = drv->hapd;
  850. struct ifreq ifr;
  851. struct sockaddr_ll addr;
  852. drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
  853. if (drv->sock < 0) {
  854. perror("socket[PF_PACKET,SOCK_RAW]");
  855. return -1;
  856. }
  857. if (eloop_register_read_sock(drv->sock, handle_802_3, drv->hapd, NULL))
  858. {
  859. printf("Could not register read socket\n");
  860. return -1;
  861. }
  862. memset(&ifr, 0, sizeof(ifr));
  863. if (hapd->conf->bridge[0] != '\0') {
  864. printf("opening bridge: %s\n", hapd->conf->bridge);
  865. os_strlcpy(ifr.ifr_name, hapd->conf->bridge,
  866. sizeof(ifr.ifr_name));
  867. } else {
  868. os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
  869. }
  870. if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
  871. perror("ioctl(SIOCGIFINDEX)");
  872. return -1;
  873. }
  874. memset(&addr, 0, sizeof(addr));
  875. addr.sll_family = AF_PACKET;
  876. addr.sll_ifindex = ifr.ifr_ifindex;
  877. addr.sll_protocol = htons(ETH_P_PAE);
  878. wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
  879. addr.sll_ifindex);
  880. if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  881. perror("bind");
  882. return -1;
  883. }
  884. memset(&ifr, 0, sizeof(ifr));
  885. os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
  886. if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
  887. perror("ioctl(SIOCGIFHWADDR)");
  888. return -1;
  889. }
  890. if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
  891. printf("Invalid HW-addr family 0x%04x\n",
  892. ifr.ifr_hwaddr.sa_family);
  893. return -1;
  894. }
  895. memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
  896. drv->pim_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
  897. if (drv->pim_sock < 0) {
  898. perror("socket[PF_PACKET,SOCK_RAW]");
  899. return -1;
  900. }
  901. if (eloop_register_read_sock(drv->pim_sock, handle_pim, drv, NULL)) {
  902. printf("Could not register read socket\n");
  903. return -1;
  904. }
  905. memset(&ifr, 0, sizeof(ifr));
  906. snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
  907. if (ioctl(drv->pim_sock, SIOCGIFINDEX, &ifr) != 0) {
  908. perror("ioctl(SIOCGIFINDEX)");
  909. return -1;
  910. }
  911. memset(&addr, 0, sizeof(addr));
  912. addr.sll_family = AF_PACKET;
  913. addr.sll_ifindex = ifr.ifr_ifindex;
  914. addr.sll_protocol = htons(ETH_P_ALL);
  915. wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
  916. addr.sll_ifindex);
  917. if (bind(drv->pim_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  918. perror("bind");
  919. return -1;
  920. }
  921. return 0;
  922. }
  923. static void * prism54_driver_init(struct hostapd_data *hapd)
  924. {
  925. struct prism54_driver_data *drv;
  926. drv = os_zalloc(sizeof(struct prism54_driver_data));
  927. if (drv == NULL) {
  928. printf("Could not allocate memory for hostapd Prism54 driver "
  929. "data\n");
  930. return NULL;
  931. }
  932. drv->hapd = hapd;
  933. drv->pim_sock = drv->sock = -1;
  934. memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
  935. if (prism54_init_sockets(drv)) {
  936. free(drv);
  937. return NULL;
  938. }
  939. prism54_init_1x(drv);
  940. /* must clean previous elems */
  941. hostapd_set_generic_elem(hapd, NULL, 0);
  942. return drv;
  943. }
  944. static void prism54_driver_deinit(void *priv)
  945. {
  946. struct prism54_driver_data *drv = priv;
  947. if (drv->pim_sock >= 0)
  948. close(drv->pim_sock);
  949. if (drv->sock >= 0)
  950. close(drv->sock);
  951. free(drv);
  952. }
  953. const struct wpa_driver_ops wpa_driver_prism54_ops = {
  954. .name = "prism54",
  955. .init = prism54_driver_init,
  956. .deinit = prism54_driver_deinit,
  957. /* .set_ieee8021x = prism54_init_1x, */
  958. .set_privacy = prism54_set_privacy_invoked,
  959. .set_encryption = prism54_set_encryption,
  960. .get_seqnum = prism54_get_seqnum,
  961. .flush = prism54_flush,
  962. .set_generic_elem = prism54_set_generic_elem,
  963. .send_eapol = prism54_send_eapol,
  964. .sta_set_flags = prism54_sta_set_flags,
  965. .sta_deauth = prism54_sta_deauth,
  966. .sta_disassoc = prism54_sta_disassoc,
  967. .set_ssid = prism54_ioctl_setiwessid,
  968. .get_inact_sec = prism54_get_inact_sec,
  969. };