]> git.ipfire.org Git - thirdparty/hostap.git/blob - hostapd/driver_prism54.c
Re-initialize hostapd/wpa_supplicant git repository based on 0.6.3 release
[thirdparty/hostap.git] / hostapd / driver_prism54.c
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
17 #include "includes.h"
18 #include <sys/ioctl.h>
19 #include <sys/select.h>
20
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 */
32
33 #include "hostapd.h"
34 #include "driver.h"
35 #include "ieee802_1x.h"
36 #include "eloop.h"
37 #include "ieee802_11.h"
38 #include "prism54.h"
39 #include "wpa.h"
40 #include "radius/radius.h"
41 #include "sta_info.h"
42 #include "accounting.h"
43
44 const int PIM_BUF_SIZE = 4096;
45
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
54
55 static int mac_id_refresh(struct prism54_driver_data *data, int id, char *mac)
56 {
57 if (id < 0 || id > 2006) {
58 return -1;
59 }
60 memcpy(&data->macs[id][0], mac, ETH_ALEN);
61 return 0;
62 }
63
64
65 static char * mac_id_get(struct prism54_driver_data *data, int id)
66 {
67 if (id < 0 || id > 2006) {
68 return NULL;
69 }
70 return &data->macs[id][0];
71 }
72
73
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,
78 int timeout)
79 {
80 struct prism54_driver_data *drv = priv;
81 struct timeval tv, stv, ctv;
82 fd_set pfd;
83 int rlen;
84 pimdev_hdr *pkt;
85
86 pkt = malloc(8192);
87 if (pkt == NULL)
88 return -1;
89
90 FD_ZERO(&pfd);
91 gettimeofday(&stv, NULL);
92 do {
93 FD_SET(drv->pim_sock, &pfd);
94 tv.tv_sec = 0;
95 tv.tv_usec = 10000;
96 if (select(drv->pim_sock + 1, &pfd, NULL, NULL, &tv)) {
97 rlen = recv(drv->pim_sock, pkt, 8192, 0);
98 if (rlen > 0) {
99 if (pkt->oid == htonl(oid)) {
100 if (rlen <= len) {
101 if (buf != NULL) {
102 memcpy(buf, pkt, rlen);
103 }
104 free(pkt);
105 return rlen;
106 } else {
107 printf("buffer too small\n");
108 free(pkt);
109 return -1;
110 }
111 } else {
112 gettimeofday(&ctv, NULL);
113 continue;
114 }
115 }
116 }
117 gettimeofday(&ctv, NULL);
118 } while (((ctv.tv_sec - stv.tv_sec) * 100 +
119 (ctv.tv_usec - stv.tv_usec) / 10000) > timeout);
120 free(pkt);
121 return 0;
122 }
123
124
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,
128 const u8 *own_addr)
129 {
130 struct prism54_driver_data *drv = priv;
131 ieee802_3_hdr *hdr;
132 size_t len;
133 u8 *pos;
134 int res;
135
136 len = sizeof(*hdr) + data_len;
137 hdr = os_zalloc(len);
138 if (hdr == NULL) {
139 printf("malloc() failed for prism54_send_data(len=%lu)\n",
140 (unsigned long) len);
141 return -1;
142 }
143
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);
149
150 res = send(drv->sock, hdr, len, 0);
151 free(hdr);
152
153 if (res < 0) {
154 perror("hostapd_send_eapol: send");
155 printf("hostapd_send_eapol - packet len: %lu - failed\n",
156 (unsigned long) len);
157 }
158
159 return res;
160 }
161
162
163 /* open data channel(auth-1) or eapol only(unauth-0) */
164 static int prism54_set_sta_authorized(void *priv, const u8 *addr,
165 int authorized)
166 {
167 struct prism54_driver_data *drv = priv;
168 pimdev_hdr *hdr;
169 char *pos;
170
171 hdr = malloc(sizeof(*hdr) + ETH_ALEN);
172 if (hdr == NULL)
173 return -1;
174 hdr->op = htonl(PIMOP_SET);
175 if (authorized) {
176 hdr->oid = htonl(DOT11_OID_EAPAUTHSTA);
177 } else {
178 hdr->oid = htonl(DOT11_OID_EAPUNAUTHSTA);
179 }
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);
184 free(hdr);
185 return 0;
186 }
187
188
189 static int
190 prism54_sta_set_flags(void *priv, const u8 *addr, int total_flags,
191 int flags_or, int flags_and)
192 {
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);
198 return 0;
199 }
200
201
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,
206 int txkey)
207 {
208 struct prism54_driver_data *drv = priv;
209 pimdev_hdr *hdr;
210 struct obj_stakey *keys;
211 u8 *buf;
212 size_t blen;
213 int ret = 0;
214
215 blen = sizeof(struct obj_stakey) + sizeof(pimdev_hdr);
216 hdr = malloc(blen);
217 if (hdr == NULL) {
218 printf("memory low\n");
219 return -1;
220 }
221 keys = (struct obj_stakey *) &hdr[1];
222 if (!addr) {
223 memset(&keys->address[0], 0xff, ETH_ALEN);
224 } else {
225 memcpy(&keys->address[0], addr, ETH_ALEN);
226 }
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 */
235 free(hdr);
236 return 0;
237 } else {
238 printf("bad auth type: %s\n", alg);
239 }
240 buf = (u8 *) &keys->key[0];
241 keys->length = key_len;
242 keys->keyid = idx;
243 keys->options = htons(DOT11_STAKEY_OPTION_DEFAULTKEY);
244 keys->reserved = 0;
245
246 hdr->op = htonl(PIMOP_SET);
247 hdr->oid = htonl(DOT11_OID_STAKEY);
248
249 memcpy(buf, key, key_len);
250
251 ret = send(drv->pim_sock, hdr, blen, 0);
252 if (ret < 0) {
253 free(hdr);
254 return ret;
255 }
256 prism54_waitpim(priv, hdr->oid, hdr, blen, 10);
257
258 free(hdr);
259
260 return 0;
261 }
262
263
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,
266 int idx, u8 *seq)
267 {
268 struct prism54_driver_data *drv = priv;
269 struct obj_stasc *stasc;
270 pimdev_hdr *hdr;
271 size_t blen;
272 int ret = 0;
273
274 blen = sizeof(*stasc) + sizeof(*hdr);
275 hdr = malloc(blen);
276 if (hdr == NULL)
277 return -1;
278
279 stasc = (struct obj_stasc *) &hdr[1];
280
281 if (addr == NULL)
282 memset(&stasc->address[0], 0xff, ETH_ALEN);
283 else
284 memcpy(&stasc->address[0], addr, ETH_ALEN);
285
286 hdr->oid = htonl(DOT11_OID_STASC);
287 hdr->op = htonl(PIMOP_GET);
288 stasc->keyid = idx;
289 if (send(drv->pim_sock,hdr,blen,0) <= 0) {
290 free(hdr);
291 return -1;
292 }
293 if (prism54_waitpim(priv, DOT11_OID_STASC, hdr, blen, 10) <= 0) {
294 ret = -1;
295 } else {
296 if (hdr->op == (int) htonl(PIMOP_RESPONSE)) {
297 memcpy(seq + 2, &stasc->sc_high, ETH_ALEN);
298 memset(seq, 0, 2);
299 } else {
300 ret = -1;
301 }
302 }
303 free(hdr);
304
305 return ret;
306 }
307
308
309 /* include unencrypted, set mlme autolevel to extended */
310 static int prism54_init_1x(void *priv)
311 {
312 struct prism54_driver_data *drv = priv;
313 pimdev_hdr *hdr;
314 unsigned long *ul;
315 int blen = sizeof(*hdr) + sizeof(*ul);
316
317 hdr = malloc(blen);
318 if (hdr == NULL)
319 return -1;
320
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);
342 free(hdr);
343 return 0;
344 }
345
346
347 static int prism54_set_privacy_invoked(const char *ifname, void *priv,
348 int flag)
349 {
350 struct prism54_driver_data *drv = priv;
351 pimdev_hdr *hdr;
352 unsigned long *ul;
353 int ret;
354 int blen = sizeof(*hdr) + sizeof(*ul);
355 hdr = malloc(blen);
356 if (hdr == NULL)
357 return -1;
358 ul = (unsigned long *) &hdr[1];
359 hdr->op = htonl(PIMOP_SET);
360 hdr->oid = htonl(DOT11_OID_PRIVACYINVOKED);
361 if (flag) {
362 *ul = htonl(DOT11_BOOL_TRUE); /* has privacy */
363 } else {
364 *ul = 0;
365 }
366 ret = send(drv->pim_sock, hdr, blen, 0);
367 if (ret >= 0) {
368 ret = prism54_waitpim(priv, DOT11_OID_PRIVACYINVOKED, hdr,
369 blen, 10);
370 }
371 free(hdr);
372 return ret;
373 }
374
375
376 static int prism54_ioctl_setiwessid(const char *ifname, void *priv,
377 const u8 *buf, int len)
378 {
379 #if 0
380 struct prism54_driver_data *drv = priv;
381 struct iwreq iwr;
382
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;
388
389 if (ioctl(drv->pim_sock, SIOCSIWESSID, &iwr) < 0) {
390 perror("ioctl[SIOCSIWESSID]");
391 printf("len=%d\n", len);
392 return -1;
393 }
394 #endif
395 return 0;
396 }
397
398
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)
402 {
403 struct prism54_driver_data *drv = priv;
404 struct obj_mlmeex *mlme;
405 pimdev_hdr *hdr;
406 int ret;
407 unsigned int i;
408 long *nsta;
409 int blen = sizeof(*hdr) + sizeof(*mlme);
410 char *mac_id;
411
412 hdr = os_zalloc(blen);
413 if (hdr == NULL)
414 return -1;
415
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)) {
424 free(hdr);
425 return 0;
426 }
427 for (i = 0; i < le_to_host32(*nsta); i++) {
428 mlme->id = -1;
429 mac_id = mac_id_get(drv, i);
430 if (mac_id)
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);
434 mlme->size = 0;
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,
439 100);
440 }
441 for (i = 0; i < le_to_host32(*nsta); i++) {
442 mlme->id = -1;
443 mac_id = mac_id_get(drv, i);
444 if (mac_id)
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);
448 mlme->size = 0;
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,
453 100);
454 }
455 free(hdr);
456 return 0;
457 }
458
459
460 static int prism54_sta_deauth(void *priv, const u8 *addr, int reason)
461 {
462 struct prism54_driver_data *drv = priv;
463 pimdev_hdr *hdr;
464 struct obj_mlmeex *mlme;
465 int ret;
466 int blen = sizeof(*hdr) + sizeof(*mlme);
467 hdr = malloc(blen);
468 if (hdr == NULL)
469 return -1;
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);
474 mlme->id = -1;
475 mlme->state = htons(DOT11_STATE_NONE);
476 mlme->code = host_to_le16(reason);
477 mlme->size = 0;
478 ret = send(drv->pim_sock, hdr, blen, 0);
479 prism54_waitpim(priv, DOT11_OID_DEAUTHENTICATEEX, hdr, blen, 10);
480 free(hdr);
481 return ret;
482 }
483
484
485 static int prism54_sta_disassoc(void *priv, const u8 *addr, int reason)
486 {
487 struct prism54_driver_data *drv = priv;
488 pimdev_hdr *hdr;
489 struct obj_mlmeex *mlme;
490 int ret;
491 int blen = sizeof(*hdr) + sizeof(*mlme);
492 hdr = malloc(blen);
493 if (hdr == NULL)
494 return -1;
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);
499 mlme->id = -1;
500 mlme->state = htons(DOT11_STATE_NONE);
501 mlme->code = host_to_le16(reason);
502 mlme->size = 0;
503 ret = send(drv->pim_sock, hdr, blen, 0);
504 prism54_waitpim(priv, DOT11_OID_DISASSOCIATEEX, hdr, blen, 10);
505 free(hdr);
506 return ret;
507 }
508
509
510 static int prism54_get_inact_sec(void *priv, const u8 *addr)
511 {
512 struct prism54_driver_data *drv = priv;
513 pimdev_hdr *hdr;
514 struct obj_sta *sta;
515 int blen = sizeof(*hdr) + sizeof(*sta);
516 int ret;
517
518 hdr = malloc(blen);
519 if (hdr == NULL)
520 return -1;
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);
527 if (ret != blen) {
528 printf("get_inact_sec: bad return %d\n", ret);
529 free(hdr);
530 return -1;
531 }
532 if (hdr->op != (int) htonl(PIMOP_RESPONSE)) {
533 printf("get_inact_sec: bad resp\n");
534 free(hdr);
535 return -1;
536 }
537 free(hdr);
538 return le_to_host16(sta->age);
539 }
540
541
542 /* set attachments */
543 static int prism54_set_generic_elem(const char *ifname, void *priv,
544 const u8 *elem, size_t elem_len)
545 {
546 struct prism54_driver_data *drv = priv;
547 pimdev_hdr *hdr;
548 char *pos;
549 struct obj_attachment_hdr *attach;
550 size_t blen = sizeof(*hdr) + sizeof(*attach) + elem_len;
551 hdr = os_zalloc(blen);
552 if (hdr == NULL) {
553 printf("%s: memory low\n", __func__);
554 return -1;
555 }
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;
560 attach->id = -1;
561 attach->size = host_to_le16((short)elem_len);
562 pos = ((char*) attach) + sizeof(*attach);
563 if (elem)
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);
568 free(hdr);
569 return 0;
570 }
571
572
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)
576 {
577 struct obj_mlmeex *mlme;
578 pimdev_hdr *hdr;
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]);
583 if (sta != NULL) {
584 if (sta->flags & (WLAN_STA_AUTH | WLAN_STA_ASSOC))
585 return;
586 }
587 if (len < sizeof(*mlme)) {
588 printf("bad probe packet\n");
589 return;
590 }
591 mlme->state = htons(DOT11_STATE_AUTHING);
592 mlme->code = 0;
593 hdr->op = htonl(PIMOP_SET);
594 hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX);
595 mlme->size = 0;
596 send(drv->pim_sock, hdr, sizeof(*hdr)+sizeof(*mlme), 0);
597 }
598
599
600 static void prism54_handle_deauth(struct prism54_driver_data *drv,
601 void *buf, size_t len)
602 {
603 struct obj_mlme *mlme;
604 pimdev_hdr *hdr;
605 struct sta_info *sta;
606 char *mac_id;
607
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)
613 return;
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);
620 }
621
622
623 static void prism54_handle_disassoc(struct prism54_driver_data *drv,
624 void *buf, size_t len)
625 {
626 struct obj_mlme *mlme;
627 pimdev_hdr *hdr;
628 struct sta_info *sta;
629 char *mac_id;
630
631 hdr = (pimdev_hdr *) buf;
632 mlme = (struct obj_mlme *) &hdr[1];
633 mac_id = mac_id_get(drv, mlme->id);
634 if (mac_id == NULL)
635 return;
636 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
637 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
638 if (sta == NULL) {
639 return;
640 }
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);
647 }
648
649
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)
653 {
654 struct obj_mlmeex *mlme;
655 pimdev_hdr *hdr;
656 struct sta_info *sta;
657 int resp;
658
659 hdr = (pimdev_hdr *) buf;
660 mlme = (struct obj_mlmeex *) &hdr[1];
661 if (len < sizeof(*mlme)) {
662 printf("bad auth packet\n");
663 return;
664 }
665
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;
670 goto fail;
671 }
672 mac_id_refresh(drv, mlme->id, &mlme->address[0]);
673 if (!sta) {
674 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
675 goto fail;
676 }
677 sta->flags &= ~WLAN_STA_PREAUTH;
678
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);
682 mlme->code = 0;
683 mlme->state=htons(DOT11_STATE_AUTH);
684 hdr->op = htonl(PIMOP_SET);
685 hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX);
686 mlme->size = 0;
687 sta->timeout_next = STA_NULLFUNC;
688 send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
689 }
690 return;
691
692 fail:
693 printf("auth fail: %x\n", resp);
694 mlme->code = host_to_le16(resp);
695 mlme->size = 0;
696 if (sta)
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);
701 }
702
703
704 /* do the wpa thing */
705 static void prism54_handle_assoc(struct prism54_driver_data *drv,
706 void *buf, size_t len)
707 {
708 pimdev_hdr *hdr;
709 struct obj_mlmeex *mlme;
710 struct ieee802_11_elems elems;
711 struct sta_info *sta;
712 u8 *wpa_ie;
713 u8 *cb;
714 int ieofs = 0;
715 size_t wpa_ie_len;
716 int resp, new_assoc;
717 char *mac_id;
718
719 resp = 0;
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:
725 mlme->size = 0;
726 default:
727 break;
728 }
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");
733 return;
734 }
735 mac_id = mac_id_get(drv, mlme->id);
736 if (mac_id == NULL)
737 return;
738 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
739 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
740 if (sta == NULL) {
741 printf("cannot get sta\n");
742 return;
743 }
744 cb = (u8 *) &mlme->data[0];
745 if (hdr->oid == htonl(DOT11_OID_ASSOCIATEEX)) {
746 ieofs = 4;
747 } else if (hdr->oid == htonl(DOT11_OID_REASSOCIATEEX)) {
748 ieofs = 10;
749 }
750 if (le_to_host16(mlme->size) <= ieofs) {
751 printf("attach too small\n");
752 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
753 goto fail;
754 }
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;
761 goto fail;
762 }
763 if ((drv->hapd->conf->wpa & WPA_PROTO_RSN) &&
764 elems.rsn_ie) {
765 wpa_ie = elems.rsn_ie;
766 wpa_ie_len = elems.rsn_ie_len;
767 } else if ((drv->hapd->conf->wpa & WPA_PROTO_WPA) &&
768 elems.wpa_ie) {
769 wpa_ie = elems.wpa_ie;
770 wpa_ie_len = elems.wpa_ie_len;
771 } else {
772 wpa_ie = NULL;
773 wpa_ie_len = 0;
774 }
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;
779 goto fail;
780 }
781 if (drv->hapd->conf->wpa) {
782 int res;
783 wpa_ie -= 2;
784 wpa_ie_len += 2;
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 "
790 "machine\n");
791 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
792 goto fail;
793 }
794 res = wpa_validate_wpa_ie(drv->hapd->wpa_auth,
795 sta->wpa_sm,
796 wpa_ie, wpa_ie_len,
797 NULL, 0);
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)
809 goto fail;
810 }
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);
815 mlme->code = 0;
816 mlme->state = htons(DOT11_STATE_ASSOC);
817 mlme->size = 0;
818 send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0);
819 return;
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");
823 return;
824 }
825 mac_id = mac_id_get(drv, mlme->id);
826 if (mac_id == NULL)
827 return;
828 memcpy(&mlme->address[0], mac_id, ETH_ALEN);
829 sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]);
830 if (sta == NULL) {
831 printf("cannot get sta\n");
832 return;
833 }
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;
840 return;
841 }
842 return;
843
844 fail:
845 printf("Prism54: assoc fail: %x\n", resp);
846 mlme->code = host_to_le16(resp);
847 mlme->size = 0;
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);
853 }
854
855
856 static void handle_pim(int sock, void *eloop_ctx, void *sock_ctx)
857 {
858 struct prism54_driver_data *drv = eloop_ctx;
859 int len;
860 pimdev_hdr *hdr;
861
862 hdr = malloc(PIM_BUF_SIZE);
863 if (hdr == NULL)
864 return;
865 len = recv(sock, hdr, PIM_BUF_SIZE, 0);
866 if (len < 0) {
867 perror("recv");
868 free(hdr);
869 return;
870 }
871 if (len < 8) {
872 printf("handle_pim: too short (%d)\n", len);
873 free(hdr);
874 return;
875 }
876
877 if (hdr->op != (int) htonl(PIMOP_TRAP)) {
878 free(hdr);
879 return;
880 }
881 switch (ntohl(hdr->oid)) {
882 case DOT11_OID_PROBE:
883 prism54_handle_probe(drv, hdr, len);
884 break;
885 case DOT11_OID_DEAUTHENTICATEEX:
886 case DOT11_OID_DEAUTHENTICATE:
887 prism54_handle_deauth(drv, hdr, len);
888 break;
889 case DOT11_OID_DISASSOCIATEEX:
890 case DOT11_OID_DISASSOCIATE:
891 prism54_handle_disassoc(drv, hdr, len);
892 break;
893 case DOT11_OID_AUTHENTICATEEX:
894 case DOT11_OID_AUTHENTICATE:
895 prism54_handle_auth(drv, hdr, len);
896 break;
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);
902 default:
903 break;
904 }
905
906 free(hdr);
907 }
908
909
910 static void handle_802_3(int sock, void *eloop_ctx, void *sock_ctx)
911 {
912 struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
913 int len;
914 ieee802_3_hdr *hdr;
915
916 hdr = malloc(PIM_BUF_SIZE);
917 if (hdr == NULL)
918 return;
919 len = recv(sock, hdr, PIM_BUF_SIZE, 0);
920 if (len < 0) {
921 perror("recv");
922 free(hdr);
923 return;
924 }
925 if (len < 14) {
926 wpa_printf(MSG_MSGDUMP, "handle_802_3: too short (%d)", len);
927 free(hdr);
928 return;
929 }
930 if (hdr->type == htons(ETH_P_PAE)) {
931 ieee802_1x_receive(hapd, (u8 *) &hdr->sa[0], (u8 *) &hdr[1],
932 len - sizeof(*hdr));
933 }
934 free(hdr);
935 }
936
937
938 static int prism54_init_sockets(struct prism54_driver_data *drv)
939 {
940 struct hostapd_data *hapd = drv->hapd;
941 struct ifreq ifr;
942 struct sockaddr_ll addr;
943
944 drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
945 if (drv->sock < 0) {
946 perror("socket[PF_PACKET,SOCK_RAW]");
947 return -1;
948 }
949
950 if (eloop_register_read_sock(drv->sock, handle_802_3, drv->hapd, NULL))
951 {
952 printf("Could not register read socket\n");
953 return -1;
954 }
955
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));
961 } else {
962 os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
963 }
964 if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
965 perror("ioctl(SIOCGIFINDEX)");
966 return -1;
967 }
968
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",
974 addr.sll_ifindex);
975
976 if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
977 perror("bind");
978 return -1;
979 }
980
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)");
985 return -1;
986 }
987
988 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
989 printf("Invalid HW-addr family 0x%04x\n",
990 ifr.ifr_hwaddr.sa_family);
991 return -1;
992 }
993 memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
994
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]");
998 return -1;
999 }
1000
1001 if (eloop_register_read_sock(drv->pim_sock, handle_pim, drv, NULL)) {
1002 printf("Could not register read socket\n");
1003 return -1;
1004 }
1005
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)");
1010 return -1;
1011 }
1012
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",
1018 addr.sll_ifindex);
1019
1020 if (bind(drv->pim_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1021 perror("bind");
1022 return -1;
1023 }
1024
1025 return 0;
1026 }
1027
1028
1029 static void * prism54_driver_init(struct hostapd_data *hapd)
1030 {
1031 struct prism54_driver_data *drv;
1032
1033 drv = os_zalloc(sizeof(struct prism54_driver_data));
1034 if (drv == NULL) {
1035 printf("Could not allocate memory for hostapd Prism54 driver "
1036 "data\n");
1037 return NULL;
1038 }
1039
1040 drv->hapd = hapd;
1041 drv->pim_sock = drv->sock = -1;
1042 memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
1043
1044 if (prism54_init_sockets(drv)) {
1045 free(drv);
1046 return NULL;
1047 }
1048 prism54_init_1x(drv);
1049 /* must clean previous elems */
1050 hostapd_set_generic_elem(hapd, NULL, 0);
1051
1052 return drv;
1053 }
1054
1055
1056 static void prism54_driver_deinit(void *priv)
1057 {
1058 struct prism54_driver_data *drv = priv;
1059
1060 if (drv->pim_sock >= 0)
1061 close(drv->pim_sock);
1062
1063 if (drv->sock >= 0)
1064 close(drv->sock);
1065
1066 free(drv);
1067 }
1068
1069
1070 const struct wpa_driver_ops wpa_driver_prism54_ops = {
1071 .name = "prism54",
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,
1086 };