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>
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.
11 * Alternatively, this software may be distributed under the terms of BSD
14 * See README and COPYING for more details.
18 #include <sys/ioctl.h>
19 #include <sys/select.h>
21 #ifdef USE_KERNEL_HEADERS
22 #include <asm/types.h>
23 #include <linux/if_packet.h>
24 #include <linux/if_ether.h> /* The L2 protocols */
25 #include <linux/if_arp.h>
26 #include <linux/wireless.h>
27 #else /* USE_KERNEL_HEADERS */
28 #include <net/if_arp.h>
29 #include <netpacket/packet.h>
30 #include "wireless_copy.h"
31 #endif /* USE_KERNEL_HEADERS */
35 #include "ieee802_1x.h"
37 #include "ieee802_11.h"
40 #include "radius/radius.h"
42 #include "accounting.h"
44 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 */
55 static int mac_id_refresh(struct prism54_driver_data *data, int id, char *mac)
57 if (id < 0 || id > 2006) {
60 memcpy(&data->macs[id][0], mac, ETH_ALEN);
65 static char * mac_id_get(struct prism54_driver_data *data, int id)
67 if (id < 0 || id > 2006) {
70 return &data->macs[id][0];
74 /* wait for a specific pimfor, timeout in 10ms resolution */
75 /* pim_sock must be non-block to prevent dead lock from no response */
76 /* or same response type in series */
77 static int prism54_waitpim(void *priv, unsigned long oid, void *buf, int len,
80 struct prism54_driver_data *drv = priv;
81 struct timeval tv, stv, ctv;
91 gettimeofday(&stv, NULL);
93 FD_SET(drv->pim_sock, &pfd);
96 if (select(drv->pim_sock + 1, &pfd, NULL, NULL, &tv)) {
97 rlen = recv(drv->pim_sock, pkt, 8192, 0);
99 if (pkt->oid == htonl(oid)) {
102 memcpy(buf, pkt, rlen);
107 printf("buffer too small\n");
112 gettimeofday(&ctv, NULL);
117 gettimeofday(&ctv, NULL);
118 } while (((ctv.tv_sec - stv.tv_sec) * 100 +
119 (ctv.tv_usec - stv.tv_usec) / 10000) > timeout);
125 /* send an eapol packet */
126 static int prism54_send_eapol(void *priv, const u8 *addr,
127 const u8 *data, size_t data_len, int encrypt,
130 struct prism54_driver_data *drv = priv;
136 len = sizeof(*hdr) + data_len;
137 hdr = os_zalloc(len);
139 printf("malloc() failed for prism54_send_data(len=%lu)\n",
140 (unsigned long) len);
144 memcpy(&hdr->da[0], addr, ETH_ALEN);
145 memcpy(&hdr->sa[0], own_addr, ETH_ALEN);
146 hdr->type = htons(ETH_P_PAE);
147 pos = (u8 *) (hdr + 1);
148 memcpy(pos, data, data_len);
150 res = send(drv->sock, hdr, len, 0);
154 perror("hostapd_send_eapol: send");
155 printf("hostapd_send_eapol - packet len: %lu - failed\n",
156 (unsigned long) len);
163 /* open data channel(auth-1) or eapol only(unauth-0) */
164 static int prism54_set_sta_authorized(void *priv, const u8 *addr,
167 struct prism54_driver_data *drv = priv;
171 hdr = malloc(sizeof(*hdr) + ETH_ALEN);
174 hdr->op = htonl(PIMOP_SET);
176 hdr->oid = htonl(DOT11_OID_EAPAUTHSTA);
178 hdr->oid = htonl(DOT11_OID_EAPUNAUTHSTA);
180 pos = (char *) (hdr + 1);
181 memcpy(pos, addr, ETH_ALEN);
182 send(drv->pim_sock, hdr, sizeof(*hdr) + ETH_ALEN, 0);
183 prism54_waitpim(priv, hdr->oid, hdr, sizeof(*hdr) + ETH_ALEN, 10);
190 prism54_sta_set_flags(void *priv, const u8 *addr, int total_flags,
191 int flags_or, int flags_and)
193 /* For now, only support setting Authorized flag */
194 if (flags_or & WLAN_STA_AUTHORIZED)
195 return prism54_set_sta_authorized(priv, addr, 1);
196 if (flags_and & WLAN_STA_AUTHORIZED)
197 return prism54_set_sta_authorized(priv, addr, 0);
202 /* set per station key */
203 static int prism54_set_encryption(const char *ifname, void *priv,
204 const char *alg, const u8 *addr,
205 int idx, const u8 *key, size_t key_len,
208 struct prism54_driver_data *drv = priv;
210 struct obj_stakey *keys;
215 blen = sizeof(struct obj_stakey) + sizeof(pimdev_hdr);
218 printf("memory low\n");
221 keys = (struct obj_stakey *) &hdr[1];
223 memset(&keys->address[0], 0xff, ETH_ALEN);
225 memcpy(&keys->address[0], addr, ETH_ALEN);
227 if (!strcmp(alg, "WEP")) {
228 keys->type = DOT11_PRIV_WEP;
229 } else if (!strcmp(alg, "TKIP")) {
230 keys->type = DOT11_PRIV_TKIP;
231 } else if (!strcmp(alg, "none")) {
232 /* the only way to clear the key is to deauth it */
233 /* and prism54 is capable to receive unencrypted packet */
234 /* so we do nothing here */
238 printf("bad auth type: %s\n", alg);
240 buf = (u8 *) &keys->key[0];
241 keys->length = key_len;
243 keys->options = htons(DOT11_STAKEY_OPTION_DEFAULTKEY);
246 hdr->op = htonl(PIMOP_SET);
247 hdr->oid = htonl(DOT11_OID_STAKEY);
249 memcpy(buf, key, key_len);
251 ret = send(drv->pim_sock, hdr, blen, 0);
256 prism54_waitpim(priv, hdr->oid, hdr, blen, 10);
264 /* get TKIP station sequence counter, prism54 is only 6 bytes */
265 static int prism54_get_seqnum(const char *ifname, void *priv, const u8 *addr,
268 struct prism54_driver_data *drv = priv;
269 struct obj_stasc *stasc;
274 blen = sizeof(*stasc) + sizeof(*hdr);
279 stasc = (struct obj_stasc *) &hdr[1];
282 memset(&stasc->address[0], 0xff, ETH_ALEN);
284 memcpy(&stasc->address[0], addr, ETH_ALEN);
286 hdr->oid = htonl(DOT11_OID_STASC);
287 hdr->op = htonl(PIMOP_GET);
289 if (send(drv->pim_sock,hdr,blen,0) <= 0) {
293 if (prism54_waitpim(priv, DOT11_OID_STASC, hdr, blen, 10) <= 0) {
296 if (hdr->op == (int) htonl(PIMOP_RESPONSE)) {
297 memcpy(seq + 2, &stasc->sc_high, ETH_ALEN);
309 /* include unencrypted, set mlme autolevel to extended */
310 static int prism54_init_1x(void *priv)
312 struct prism54_driver_data *drv = priv;
315 int blen = sizeof(*hdr) + sizeof(*ul);
321 ul = (unsigned long *) &hdr[1];
322 hdr->op = htonl(PIMOP_SET);
323 hdr->oid = htonl(DOT11_OID_EXUNENCRYPTED);
324 *ul = htonl(DOT11_BOOL_TRUE); /* not accept */
325 send(drv->pim_sock, hdr, blen, 0);
326 prism54_waitpim(priv, DOT11_OID_EXUNENCRYPTED, hdr, blen, 10);
327 hdr->op = htonl(PIMOP_SET);
328 hdr->oid = htonl(DOT11_OID_MLMEAUTOLEVEL);
329 *ul = htonl(DOT11_MLME_EXTENDED);
330 send(drv->pim_sock, hdr, blen, 0);
331 prism54_waitpim(priv, DOT11_OID_MLMEAUTOLEVEL, hdr, blen, 10);
332 hdr->op = htonl(PIMOP_SET);
333 hdr->oid = htonl(DOT11_OID_DOT1XENABLE);
334 *ul = htonl(DOT11_BOOL_TRUE);
335 send(drv->pim_sock, hdr, blen, 0);
336 prism54_waitpim(priv, DOT11_OID_DOT1XENABLE, hdr, blen, 10);
337 hdr->op = htonl(PIMOP_SET);
338 hdr->oid = htonl(DOT11_OID_AUTHENABLE);
339 *ul = htonl(DOT11_AUTH_OS); /* OS */
340 send(drv->pim_sock, hdr, blen, 0);
341 prism54_waitpim(priv, DOT11_OID_AUTHENABLE, hdr, blen, 10);
347 static int prism54_set_privacy_invoked(const char *ifname, void *priv,
350 struct prism54_driver_data *drv = priv;
354 int blen = sizeof(*hdr) + sizeof(*ul);
358 ul = (unsigned long *) &hdr[1];
359 hdr->op = htonl(PIMOP_SET);
360 hdr->oid = htonl(DOT11_OID_PRIVACYINVOKED);
362 *ul = htonl(DOT11_BOOL_TRUE); /* has privacy */
366 ret = send(drv->pim_sock, hdr, blen, 0);
368 ret = prism54_waitpim(priv, DOT11_OID_PRIVACYINVOKED, hdr,
376 static int prism54_ioctl_setiwessid(const char *ifname, void *priv,
377 const u8 *buf, int len)
380 struct prism54_driver_data *drv = priv;
383 memset(&iwr, 0, sizeof(iwr));
384 os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
385 iwr.u.essid.flags = 1; /* SSID active */
386 iwr.u.essid.pointer = (caddr_t) buf;
387 iwr.u.essid.length = len + 1;
389 if (ioctl(drv->pim_sock, SIOCSIWESSID, &iwr) < 0) {
390 perror("ioctl[SIOCSIWESSID]");
391 printf("len=%d\n", len);
399 /* kick all stations */
400 /* does not work during init, but at least it won't crash firmware */
401 static int prism54_flush(void *priv)
403 struct prism54_driver_data *drv = priv;
404 struct obj_mlmeex *mlme;
409 int blen = sizeof(*hdr) + sizeof(*mlme);
412 hdr = os_zalloc(blen);
416 mlme = (struct obj_mlmeex *) &hdr[1];
417 nsta = (long *) &hdr[1];
418 hdr->op = htonl(PIMOP_GET);
419 hdr->oid = htonl(DOT11_OID_CLIENTS);
420 ret = send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(long), 0);
421 ret = prism54_waitpim(priv, DOT11_OID_CLIENTS, hdr, blen, 10);
422 if ((ret < 0) || (hdr->op != (int) htonl(PIMOP_RESPONSE)) ||
423 (le_to_host32(*nsta) > 2007)) {
427 for (i = 0; i < le_to_host32(*nsta); i++) {
429 mac_id = mac_id_get(drv, i);
431 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
432 mlme->code = host_to_le16(WLAN_REASON_UNSPECIFIED);
433 mlme->state = htons(DOT11_STATE_NONE);
435 hdr->op = htonl(PIMOP_SET);
436 hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX);
437 ret = send(drv->pim_sock, hdr, blen, 0);
438 prism54_waitpim(priv, DOT11_OID_DISASSOCIATEEX, hdr, blen,
441 for (i = 0; i < le_to_host32(*nsta); i++) {
443 mac_id = mac_id_get(drv, i);
445 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
446 mlme->code = host_to_le16(WLAN_REASON_UNSPECIFIED);
447 mlme->state = htons(DOT11_STATE_NONE);
449 hdr->op = htonl(PIMOP_SET);
450 hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX);
451 ret = send(drv->pim_sock, hdr, blen, 0);
452 prism54_waitpim(priv, DOT11_OID_DEAUTHENTICATEEX, hdr, blen,
460 static int prism54_sta_deauth(void *priv, const u8 *addr, int reason)
462 struct prism54_driver_data *drv = priv;
464 struct obj_mlmeex *mlme;
466 int blen = sizeof(*hdr) + sizeof(*mlme);
470 mlme = (struct obj_mlmeex *) &hdr[1];
471 hdr->op = htonl(PIMOP_SET);
472 hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX);
473 memcpy(&mlme->address[0], addr, ETH_ALEN);
475 mlme->state = htons(DOT11_STATE_NONE);
476 mlme->code = host_to_le16(reason);
478 ret = send(drv->pim_sock, hdr, blen, 0);
479 prism54_waitpim(priv, DOT11_OID_DEAUTHENTICATEEX, hdr, blen, 10);
485 static int prism54_sta_disassoc(void *priv, const u8 *addr, int reason)
487 struct prism54_driver_data *drv = priv;
489 struct obj_mlmeex *mlme;
491 int blen = sizeof(*hdr) + sizeof(*mlme);
495 mlme = (struct obj_mlmeex *) &hdr[1];
496 hdr->op = htonl(PIMOP_SET);
497 hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX);
498 memcpy(&mlme->address[0], addr, ETH_ALEN);
500 mlme->state = htons(DOT11_STATE_NONE);
501 mlme->code = host_to_le16(reason);
503 ret = send(drv->pim_sock, hdr, blen, 0);
504 prism54_waitpim(priv, DOT11_OID_DISASSOCIATEEX, hdr, blen, 10);
510 static int prism54_get_inact_sec(void *priv, const u8 *addr)
512 struct prism54_driver_data *drv = priv;
515 int blen = sizeof(*hdr) + sizeof(*sta);
521 hdr->op = htonl(PIMOP_GET);
522 hdr->oid = htonl(DOT11_OID_CLIENTFIND);
523 sta = (struct obj_sta *) &hdr[1];
524 memcpy(&sta->address[0], addr, ETH_ALEN);
525 ret = send(drv->pim_sock, hdr, blen, 0);
526 ret = prism54_waitpim(priv, DOT11_OID_CLIENTFIND, hdr, blen, 10);
528 printf("get_inact_sec: bad return %d\n", ret);
532 if (hdr->op != (int) htonl(PIMOP_RESPONSE)) {
533 printf("get_inact_sec: bad resp\n");
538 return le_to_host16(sta->age);
542 /* set attachments */
543 static int prism54_set_generic_elem(const char *ifname, void *priv,
544 const u8 *elem, size_t elem_len)
546 struct prism54_driver_data *drv = priv;
549 struct obj_attachment_hdr *attach;
550 size_t blen = sizeof(*hdr) + sizeof(*attach) + elem_len;
551 hdr = os_zalloc(blen);
553 printf("%s: memory low\n", __func__);
556 hdr->op = htonl(PIMOP_SET);
557 hdr->oid = htonl(DOT11_OID_ATTACHMENT);
558 attach = (struct obj_attachment_hdr *)&hdr[1];
559 attach->type = DOT11_PKT_BEACON;
561 attach->size = host_to_le16((short)elem_len);
562 pos = ((char*) attach) + sizeof(*attach);
564 memcpy(pos, elem, elem_len);
565 send(drv->pim_sock, hdr, blen, 0);
566 attach->type = DOT11_PKT_PROBE_RESP;
567 send(drv->pim_sock, hdr, blen, 0);
573 /* tell the card to auth the sta */
574 static void prism54_handle_probe(struct prism54_driver_data *drv,
575 void *buf, size_t len)
577 struct obj_mlmeex *mlme;
579 struct sta_info *sta;
580 hdr = (pimdev_hdr *)buf;
581 mlme = (struct obj_mlmeex *) &hdr[1];
582 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
584 if (sta->flags & (WLAN_STA_AUTH | WLAN_STA_ASSOC))
587 if (len < sizeof(*mlme)) {
588 printf("bad probe packet\n");
591 mlme->state = htons(DOT11_STATE_AUTHING);
593 hdr->op = htonl(PIMOP_SET);
594 hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX);
596 send(drv->pim_sock, hdr, sizeof(*hdr)+sizeof(*mlme), 0);
600 static void prism54_handle_deauth(struct prism54_driver_data *drv,
601 void *buf, size_t len)
603 struct obj_mlme *mlme;
605 struct sta_info *sta;
608 hdr = (pimdev_hdr *) buf;
609 mlme = (struct obj_mlme *) &hdr[1];
610 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
611 mac_id = mac_id_get(drv, mlme->id);
612 if (sta == NULL || mac_id == NULL)
614 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
615 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
616 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
617 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
618 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
619 ap_free_sta(drv->hapd, sta);
623 static void prism54_handle_disassoc(struct prism54_driver_data *drv,
624 void *buf, size_t len)
626 struct obj_mlme *mlme;
628 struct sta_info *sta;
631 hdr = (pimdev_hdr *) buf;
632 mlme = (struct obj_mlme *) &hdr[1];
633 mac_id = mac_id_get(drv, mlme->id);
636 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
637 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
641 sta->flags &= ~WLAN_STA_ASSOC;
642 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
643 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
644 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
645 accounting_sta_stop(drv->hapd, sta);
646 ieee802_1x_free_station(sta);
650 /* to auth it, just allow it now, later for os/sk */
651 static void prism54_handle_auth(struct prism54_driver_data *drv,
652 void *buf, size_t len)
654 struct obj_mlmeex *mlme;
656 struct sta_info *sta;
659 hdr = (pimdev_hdr *) buf;
660 mlme = (struct obj_mlmeex *) &hdr[1];
661 if (len < sizeof(*mlme)) {
662 printf("bad auth packet\n");
666 if (mlme->state == htons(DOT11_STATE_AUTHING)) {
667 sta = ap_sta_add(drv->hapd, (u8 *) &mlme->address[0]);
668 if (drv->hapd->tkip_countermeasures) {
669 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
672 mac_id_refresh(drv, mlme->id, &mlme->address[0]);
674 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
677 sta->flags &= ~WLAN_STA_PREAUTH;
679 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
680 sta->flags |= WLAN_STA_AUTH;
681 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
683 mlme->state=htons(DOT11_STATE_AUTH);
684 hdr->op = htonl(PIMOP_SET);
685 hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX);
687 sta->timeout_next = STA_NULLFUNC;
688 send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
693 printf("auth fail: %x\n", resp);
694 mlme->code = host_to_le16(resp);
697 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
698 hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX);
699 hdr->op = htonl(PIMOP_SET);
700 send(drv->pim_sock, hdr, sizeof(*hdr)+sizeof(*mlme), 0);
704 /* do the wpa thing */
705 static void prism54_handle_assoc(struct prism54_driver_data *drv,
706 void *buf, size_t len)
709 struct obj_mlmeex *mlme;
710 struct ieee802_11_elems elems;
711 struct sta_info *sta;
720 hdr = (pimdev_hdr *) buf;
721 mlme = (struct obj_mlmeex *) &hdr[1];
722 switch (ntohl(hdr->oid)) {
723 case DOT11_OID_ASSOCIATE:
724 case DOT11_OID_REASSOCIATE:
729 if ((mlme->state == (int) htonl(DOT11_STATE_ASSOCING)) ||
730 (mlme->state == (int) htonl(DOT11_STATE_REASSOCING))) {
731 if (len < sizeof(pimdev_hdr) + sizeof(struct obj_mlme)) {
732 printf("bad assoc packet\n");
735 mac_id = mac_id_get(drv, mlme->id);
738 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
739 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
741 printf("cannot get sta\n");
744 cb = (u8 *) &mlme->data[0];
745 if (hdr->oid == htonl(DOT11_OID_ASSOCIATEEX)) {
747 } else if (hdr->oid == htonl(DOT11_OID_REASSOCIATEEX)) {
750 if (le_to_host16(mlme->size) <= ieofs) {
751 printf("attach too small\n");
752 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
755 if (ieee802_11_parse_elems(drv->hapd, cb + ieofs,
756 le_to_host16(mlme->size) - ieofs,
757 &elems, 1) == ParseFailed) {
758 printf("STA " MACSTR " sent invalid association "
759 "request\n", MAC2STR(sta->addr));
760 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
763 if ((drv->hapd->conf->wpa & WPA_PROTO_RSN) &&
765 wpa_ie = elems.rsn_ie;
766 wpa_ie_len = elems.rsn_ie_len;
767 } else if ((drv->hapd->conf->wpa & WPA_PROTO_WPA) &&
769 wpa_ie = elems.wpa_ie;
770 wpa_ie_len = elems.wpa_ie_len;
775 if (drv->hapd->conf->wpa && wpa_ie == NULL) {
776 printf("STA " MACSTR ": No WPA/RSN IE in association "
777 "request\n", MAC2STR(sta->addr));
778 resp = WLAN_STATUS_INVALID_IE;
781 if (drv->hapd->conf->wpa) {
785 if (sta->wpa_sm == NULL)
786 sta->wpa_sm = wpa_auth_sta_init(
787 drv->hapd->wpa_auth, sta->addr);
788 if (sta->wpa_sm == NULL) {
789 printf("Failed to initialize WPA state "
791 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
794 res = wpa_validate_wpa_ie(drv->hapd->wpa_auth,
798 if (res == WPA_INVALID_GROUP)
799 resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
800 else if (res == WPA_INVALID_PAIRWISE)
801 resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
802 else if (res == WPA_INVALID_AKMP)
803 resp = WLAN_STATUS_AKMP_NOT_VALID;
804 else if (res == WPA_ALLOC_FAIL)
805 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
806 else if (res != WPA_IE_OK)
807 resp = WLAN_STATUS_INVALID_IE;
808 if (resp != WLAN_STATUS_SUCCESS)
811 hdr->oid = (hdr->oid == htonl(DOT11_OID_ASSOCIATEEX)) ?
812 htonl(DOT11_OID_ASSOCIATEEX) :
813 htonl(DOT11_OID_REASSOCIATEEX);
814 hdr->op = htonl(PIMOP_SET);
816 mlme->state = htons(DOT11_STATE_ASSOC);
818 send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
820 } else if (mlme->state==htons(DOT11_STATE_ASSOC)) {
821 if (len < sizeof(pimdev_hdr) + sizeof(struct obj_mlme)) {
822 printf("bad assoc packet\n");
825 mac_id = mac_id_get(drv, mlme->id);
828 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
829 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
831 printf("cannot get sta\n");
834 new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
835 sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
836 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
837 hostapd_new_assoc_sta(drv->hapd, sta, !new_assoc);
838 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
839 sta->timeout_next = STA_NULLFUNC;
845 printf("Prism54: assoc fail: %x\n", resp);
846 mlme->code = host_to_le16(resp);
848 mlme->state = htons(DOT11_STATE_ASSOCING);
849 hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX);
850 hdr->op = htonl(PIMOP_SET);
851 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
852 send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
856 static void handle_pim(int sock, void *eloop_ctx, void *sock_ctx)
858 struct prism54_driver_data *drv = eloop_ctx;
862 hdr = malloc(PIM_BUF_SIZE);
865 len = recv(sock, hdr, PIM_BUF_SIZE, 0);
872 printf("handle_pim: too short (%d)\n", len);
877 if (hdr->op != (int) htonl(PIMOP_TRAP)) {
881 switch (ntohl(hdr->oid)) {
882 case DOT11_OID_PROBE:
883 prism54_handle_probe(drv, hdr, len);
885 case DOT11_OID_DEAUTHENTICATEEX:
886 case DOT11_OID_DEAUTHENTICATE:
887 prism54_handle_deauth(drv, hdr, len);
889 case DOT11_OID_DISASSOCIATEEX:
890 case DOT11_OID_DISASSOCIATE:
891 prism54_handle_disassoc(drv, hdr, len);
893 case DOT11_OID_AUTHENTICATEEX:
894 case DOT11_OID_AUTHENTICATE:
895 prism54_handle_auth(drv, hdr, len);
897 case DOT11_OID_ASSOCIATEEX:
898 case DOT11_OID_REASSOCIATEEX:
899 case DOT11_OID_ASSOCIATE:
900 case DOT11_OID_REASSOCIATE:
901 prism54_handle_assoc(drv, hdr, len);
910 static void handle_802_3(int sock, void *eloop_ctx, void *sock_ctx)
912 struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
916 hdr = malloc(PIM_BUF_SIZE);
919 len = recv(sock, hdr, PIM_BUF_SIZE, 0);
926 wpa_printf(MSG_MSGDUMP, "handle_802_3: too short (%d)", len);
930 if (hdr->type == htons(ETH_P_PAE)) {
931 ieee802_1x_receive(hapd, (u8 *) &hdr->sa[0], (u8 *) &hdr[1],
938 static int prism54_init_sockets(struct prism54_driver_data *drv)
940 struct hostapd_data *hapd = drv->hapd;
942 struct sockaddr_ll addr;
944 drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
946 perror("socket[PF_PACKET,SOCK_RAW]");
950 if (eloop_register_read_sock(drv->sock, handle_802_3, drv->hapd, NULL))
952 printf("Could not register read socket\n");
956 memset(&ifr, 0, sizeof(ifr));
957 if (hapd->conf->bridge[0] != '\0') {
958 printf("opening bridge: %s\n", hapd->conf->bridge);
959 os_strlcpy(ifr.ifr_name, hapd->conf->bridge,
960 sizeof(ifr.ifr_name));
962 os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
964 if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
965 perror("ioctl(SIOCGIFINDEX)");
969 memset(&addr, 0, sizeof(addr));
970 addr.sll_family = AF_PACKET;
971 addr.sll_ifindex = ifr.ifr_ifindex;
972 addr.sll_protocol = htons(ETH_P_PAE);
973 wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
976 if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
981 memset(&ifr, 0, sizeof(ifr));
982 os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
983 if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
984 perror("ioctl(SIOCGIFHWADDR)");
988 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
989 printf("Invalid HW-addr family 0x%04x\n",
990 ifr.ifr_hwaddr.sa_family);
993 memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
995 drv->pim_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
996 if (drv->pim_sock < 0) {
997 perror("socket[PF_PACKET,SOCK_RAW]");
1001 if (eloop_register_read_sock(drv->pim_sock, handle_pim, drv, NULL)) {
1002 printf("Could not register read socket\n");
1006 memset(&ifr, 0, sizeof(ifr));
1007 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
1008 if (ioctl(drv->pim_sock, SIOCGIFINDEX, &ifr) != 0) {
1009 perror("ioctl(SIOCGIFINDEX)");
1013 memset(&addr, 0, sizeof(addr));
1014 addr.sll_family = AF_PACKET;
1015 addr.sll_ifindex = ifr.ifr_ifindex;
1016 addr.sll_protocol = htons(ETH_P_ALL);
1017 wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
1020 if (bind(drv->pim_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1029 static void * prism54_driver_init(struct hostapd_data *hapd)
1031 struct prism54_driver_data *drv;
1033 drv = os_zalloc(sizeof(struct prism54_driver_data));
1035 printf("Could not allocate memory for hostapd Prism54 driver "
1041 drv->pim_sock = drv->sock = -1;
1042 memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
1044 if (prism54_init_sockets(drv)) {
1048 prism54_init_1x(drv);
1049 /* must clean previous elems */
1050 hostapd_set_generic_elem(hapd, NULL, 0);
1056 static void prism54_driver_deinit(void *priv)
1058 struct prism54_driver_data *drv = priv;
1060 if (drv->pim_sock >= 0)
1061 close(drv->pim_sock);
1070 const struct wpa_driver_ops wpa_driver_prism54_ops = {
1072 .init = prism54_driver_init,
1073 .deinit = prism54_driver_deinit,
1074 /* .set_ieee8021x = prism54_init_1x, */
1075 .set_privacy = prism54_set_privacy_invoked,
1076 .set_encryption = prism54_set_encryption,
1077 .get_seqnum = prism54_get_seqnum,
1078 .flush = prism54_flush,
1079 .set_generic_elem = prism54_set_generic_elem,
1080 .send_eapol = prism54_send_eapol,
1081 .sta_set_flags = prism54_sta_set_flags,
1082 .sta_deauth = prism54_sta_deauth,
1083 .sta_disassoc = prism54_sta_disassoc,
1084 .set_ssid = prism54_ioctl_setiwessid,
1085 .get_inact_sec = prism54_get_inact_sec,