driver_prism54.c 27 KB

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