driver_prism54.c 27 KB

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