Resync with broadcom drivers 5.100.138.20 and utilities #2
[tomato.git] / release / src-rt / wl / eapd / eapd.c
blob372f9404578ed10fdb46651fd63ecbeebee79fac
1 /*
2 * Broadcom EAP dispatcher (EAPD) module main loop
4 * Copyright (C) 2010, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
12 * $Id: eapd.c 241391 2011-02-18 03:35:48Z stakita $
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <net/if.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <typedefs.h>
26 #include <bcmutils.h>
27 #include <proto/ethernet.h>
28 #include <proto/eapol.h>
29 #include <proto/eap.h>
30 #include <wlutils.h>
31 #include <time.h>
32 #include <eapd.h>
33 #include <shutils.h>
34 #include <wlif_utils.h>
35 #include <UdpLib.h>
36 #include <bcmconfig.h>
38 uint eapd_msg_level =
39 #ifdef BCMDBG
40 EAPD_ERROR_VAL;
41 #else
43 #endif /* BCMDBG */
45 #define EAPD_WKSP_MAX_EAP_USER_IDENT 32
46 #define EAPD_WKSP_EAP_USER_NUM 2
47 #define EAP_TYPE_WSC EAP_EXPANDED
49 struct eapd_user_list {
50 unsigned char identity[EAPD_WKSP_MAX_EAP_USER_IDENT];
51 unsigned int identity_len;
52 unsigned char method;
55 static struct eapd_user_list eapdispuserlist[EAPD_WKSP_EAP_USER_NUM] = {
56 {"WFA-SimpleConfig-Enrollee-1-0", 29, EAP_TYPE_WSC},
57 {"WFA-SimpleConfig-Registrar-1-0", 30, EAP_TYPE_WSC}
61 static int eapd_wksp_inited = 0;
63 /* Static function protype define */
64 static int sta_init(eapd_wksp_t *nwksp);
65 static int sta_deinit(eapd_wksp_t *nwksp);
66 static unsigned char eapd_get_method(unsigned char *user);
67 static int event_init(eapd_wksp_t *nwksp);
68 static int event_deinit(eapd_wksp_t *nwksp);
69 static bool eapd_add_interface(eapd_wksp_t *nwksp, char *ifname, eapd_app_mode_t mode);
70 static bool eapd_valid_eapol_start(eapd_wksp_t *nwksp, eapd_brcm_socket_t *from, char *ifname);
72 #ifdef BCMDBG
73 /* #define HEXDUMP */
74 #ifdef HEXDUMP
75 extern int isprint(char i);
76 static void eapd_hexdump_ascii(const char *title, const unsigned char *buf,
77 unsigned int len)
79 int i, llen;
80 const unsigned char *pos = buf;
81 const int line_len = 16;
83 EAPD_PRINT("%s - (data len=%lu):\n", title, (unsigned long) len);
84 while (len) {
85 llen = len > line_len ? line_len : len;
86 EAPD_PRINT(" ");
87 for (i = 0; i < llen; i++)
88 EAPD_PRINT(" %02x", pos[i]);
89 for (i = llen; i < line_len; i++)
90 EAPD_PRINT(" ");
91 EAPD_PRINT(" ");
92 for (i = 0; i < llen; i++) {
93 if (isprint(pos[i]))
94 EAPD_PRINT("%c", pos[i]);
95 else
96 EAPD_PRINT("*");
98 for (i = llen; i < line_len; i++)
99 EAPD_PRINT(" ");
100 EAPD_PRINT("\n");
101 pos += llen;
102 len -= llen;
106 #define HEXDUMP_ASCII(title, buf, len) eapd_hexdump_ascii(title, buf, len)
107 #else
108 #define HEXDUMP_ASCII(title, buf, len)
109 #endif /* HEXDUMP */
110 #endif /* BCMDBG */
112 #ifdef EAPDDUMP
113 /* dump brcm and preauth socket information */
114 static void
115 eapd_dump(eapd_wksp_t *nwksp)
117 int i, j, flag;
118 eapd_brcm_socket_t *brcmSocket;
119 eapd_preauth_socket_t *preauthSocket;
120 eapd_wps_t *wps;
121 eapd_ses_t *ses;
122 eapd_nas_t *nas;
123 #ifdef BCM_DCS
124 eapd_dcs_t *dcs;
125 #endif
126 eapd_cb_t *cb;
127 eapd_sta_t *sta;
128 char eabuf[ETHER_ADDR_STR_LEN], bssidbuf[ETHER_ADDR_STR_LEN];
131 if (nwksp == NULL) {
132 EAPD_PRINT("Wrong argument...\n");
133 return;
136 EAPD_PRINT("\n***************************\n");
138 EAPD_PRINT("WPS:\n");
139 wps = &nwksp->wps;
140 cb = wps->cb;
141 if (cb) {
142 EAPD_PRINT(" wps-monitor appSocket %d for %s", wps->appSocket, cb->ifname);
143 /* print each cb ifname */
144 cb = cb->next;
145 while (cb) {
146 EAPD_PRINT(" %s", cb->ifname);
147 cb = cb->next;
149 EAPD_PRINT("\n");
151 EAPD_PRINT(" interested wireless interfaces [%s]\n", wps->ifnames);
153 /* bitvec for brcmevent */
154 flag = 1;
155 for (i = 0; i < WL_EVENTING_MASK_LEN; i++) {
156 for (j = 0; j < 8; j++) {
157 if (isset(&wps->bitvec[i], j)) {
158 if (flag) {
159 EAPD_PRINT(" interested event message id [%d",
160 (i*8+j));
161 flag = 0;
163 else {
164 EAPD_PRINT(" %d", (i*8+j));
169 EAPD_PRINT("]\n");
171 cb = wps->cb;
172 while (cb) {
173 if (cb->brcmSocket) {
174 brcmSocket = cb->brcmSocket;
175 EAPD_PRINT(" [rfp=0x%x] drvSocket %d on %s for brcm event packet\n",
176 (uint) brcmSocket, brcmSocket->drvSocket, brcmSocket->ifname);
178 cb = cb->next;
179 if (cb)
180 EAPD_PRINT(" ----\n");
182 EAPD_PRINT("\n");
184 EAPD_PRINT("SES:\n");
185 ses = &nwksp->ses;
186 cb = ses->cb;
187 if (cb) {
188 EAPD_PRINT(" ses appSocket %d for %s", ses->appSocket, cb->ifname);
189 /* print each cb ifname */
190 cb = cb->next;
191 while (cb) {
192 EAPD_PRINT(" %s", cb->ifname);
193 cb = cb->next;
195 EAPD_PRINT("\n");
197 EAPD_PRINT(" interested wireless interfaces [%s]\n", ses->ifnames);
199 /* bitvec for brcmevent */
200 flag = 1;
201 for (i = 0; i < WL_EVENTING_MASK_LEN; i++) {
202 for (j = 0; j < 8; j++) {
203 if (isset(&ses->bitvec[i], j)) {
204 if (flag) {
205 EAPD_PRINT(" interested event message id [%d",
206 (i*8+j));
207 flag = 0;
209 else {
210 EAPD_PRINT(" %d", (i*8+j));
215 EAPD_PRINT("]\n");
217 cb = ses->cb;
218 while (cb) {
219 if (cb->brcmSocket) {
220 brcmSocket = cb->brcmSocket;
221 EAPD_PRINT(" [rfp=0x%x] drvSocket %d on %s for brcm event packet\n",
222 (uint) brcmSocket, brcmSocket->drvSocket, brcmSocket->ifname);
224 cb = cb->next;
225 if (cb)
226 EAPD_PRINT(" ----\n");
228 EAPD_PRINT("\n");
230 EAPD_PRINT("NAS:\n");
231 nas = &nwksp->nas;
232 cb = nas->cb;
233 if (cb) {
234 EAPD_PRINT(" nas appSocket %d for %s", nas->appSocket, cb->ifname);
235 /* print each cb ifname */
236 cb = cb->next;
237 while (cb) {
238 EAPD_PRINT(" %s", cb->ifname);
239 cb = cb->next;
241 EAPD_PRINT("\n");
243 EAPD_PRINT(" interested wireless interfaces [%s]\n", nas->ifnames);
245 /* bitvec for brcmevent */
246 flag = 1;
247 for (i = 0; i < WL_EVENTING_MASK_LEN; i++) {
248 for (j = 0; j < 8; j++) {
249 if (isset(&nas->bitvec[i], j)) {
250 if (flag) {
251 EAPD_PRINT(" interested event message id [%d",
252 (i*8+j));
253 flag = 0;
255 else {
256 EAPD_PRINT(" %d", (i*8+j));
261 EAPD_PRINT("]\n");
263 cb = nas->cb;
264 while (cb) {
265 preauthSocket = &cb->preauthSocket;
266 if (preauthSocket->drvSocket >= 0) {
267 EAPD_PRINT(" [0x%x] drvSocket %d on %s for preauth packet\n",
268 (uint) preauthSocket, preauthSocket->drvSocket,
269 preauthSocket->ifname);
271 if (cb->brcmSocket) {
272 brcmSocket = cb->brcmSocket;
273 EAPD_PRINT(" [rfp=0x%x] drvSocket %d on %s for brcm event packet\n",
274 (uint) brcmSocket, brcmSocket->drvSocket, brcmSocket->ifname);
276 cb = cb->next;
277 if (cb)
278 EAPD_PRINT(" ----\n");
280 EAPD_PRINT("\n");
283 #ifdef BCM_DCS
284 EAPD_PRINT("DCS:\n");
285 dcs = &nwksp->dcs;
286 cb = dcs->cb;
287 if (cb) {
288 EAPD_PRINT(" dcs appSocket %d for %s", dcs->appSocket, cb->ifname);
289 /* print each cb ifname */
290 cb = cb->next;
291 while (cb) {
292 EAPD_PRINT(" %s", cb->ifname);
293 cb = cb->next;
295 EAPD_PRINT("\n");
297 EAPD_PRINT(" interested wireless interfaces [%s]\n", dcs->ifnames);
299 /* bitvec for brcmevent */
300 flag = 1;
301 for (i = 0; i < WL_EVENTING_MASK_LEN; i++) {
302 for (j = 0; j < 8; j++) {
303 if (isset(&dcs->bitvec[i], j)) {
304 if (flag) {
305 EAPD_PRINT(" interested event message id [%d",
306 (i*8+j));
307 flag = 0;
309 else {
310 EAPD_PRINT(" %d", (i*8+j));
315 EAPD_PRINT("]\n");
317 cb = dcs->cb;
318 while (cb) {
319 if (cb->brcmSocket) {
320 brcmSocket = cb->brcmSocket;
321 EAPD_PRINT(" [rfp=0x%x] drvSocket %d on %s for brcm event packet\n",
322 (uint) brcmSocket, brcmSocket->drvSocket, brcmSocket->ifname);
324 cb = cb->next;
325 if (cb)
326 EAPD_PRINT(" ----\n");
328 EAPD_PRINT("\n");
329 #endif /* BCM_DCS */
331 EAPD_PRINT("BRCM (brcm event):\n");
332 for (i = 0; i < nwksp->brcmSocketCount; i++) {
333 brcmSocket = &nwksp->brcmSocket[i];
334 EAPD_PRINT(" [0x%x] [inuseCount=%d] drvSocket %d on %s for "
335 "brcm event packet\n", (uint) brcmSocket,
336 brcmSocket->inuseCount, brcmSocket->drvSocket,
337 brcmSocket->ifname);
340 EAPD_PRINT("\n");
342 EAPD_PRINT("Stations Info:\n");
343 j = 0;
344 for (i = 0; i < EAPD_WKSP_MAX_SUPPLICANTS; i++) {
345 for (sta = nwksp->sta_hashed[i]; sta; sta = sta->next) {
346 EAPD_PRINT(" [%d] %s from %s[%s]\n", j++,
347 ether_etoa((uchar *)&sta->ea, eabuf), sta->ifname,
348 ether_etoa((uchar *)&sta->bssid, bssidbuf));
351 EAPD_PRINT("***************************\n");
353 #endif /* EAPDDUMP */
355 #ifdef BCMDBG
356 void
357 eapd_wksp_display_usage(void)
359 EAPD_PRINT("\nUsage: eapd [options]\n\n");
360 EAPD_PRINT("\n-wps ifname(s)\n");
361 EAPD_PRINT("\n-nas ifname(s)\n");
362 EAPD_PRINT("\n-ses ifname\n");
363 #ifdef BCM_DCS
364 EAPD_PRINT("\n-dcs ifname(s)\n");
365 #endif /* BCM_DCS */
366 EAPD_PRINT("\n\n");
368 #endif /* BCMDBG */
370 #ifdef EAPD_WKSP_AUTO_CONFIG
372 eapd_wksp_auto_config(eapd_wksp_t *nwksp)
374 int i;
375 char ifnames[256], tmp_ifname[128], tmp_ifnames[128], name[IFNAMSIZ];
376 char *next;
377 bool needStart = FALSE;
379 /* lan */
380 for (i = 0; i < EAPD_WKSP_MAX_NO_BRIDGE; i++) {
381 memset(tmp_ifname, 0, sizeof(tmp_ifname));
382 memset(tmp_ifnames, 0, sizeof(tmp_ifnames));
383 if (i == 0) {
384 sprintf(tmp_ifname, "lan_ifname");
385 sprintf(tmp_ifnames, "lan_ifnames");
387 else {
388 sprintf(tmp_ifname, "lan%d_ifname", i);
389 sprintf(tmp_ifnames, "lan%d_ifnames", i);
392 memset(ifnames, 0, sizeof(ifnames));
393 memset(name, 0, sizeof(name));
394 eapd_safe_get_conf(ifnames, sizeof(ifnames), tmp_ifnames);
395 if (!strcmp(ifnames, "")) {
396 eapd_safe_get_conf(ifnames, sizeof(ifnames), tmp_ifname);
397 if (!strcmp(ifnames, ""))
398 continue;
400 foreach(name, ifnames, next) {
401 if (wps_app_enabled(name))
402 needStart |= eapd_add_interface(nwksp, name, EAPD_APP_WPS);
403 if (nas_app_enabled(name))
404 needStart |= eapd_add_interface(nwksp, name, EAPD_APP_NAS);
405 if (i == 0 && ses_app_enabled(name)) /* SES only running on lan_ifname */
406 needStart |= eapd_add_interface(nwksp, name, EAPD_APP_SES);
408 #ifdef BCM_DCS
409 if (dcs_app_enabled(name))
410 needStart |= eapd_add_interface(nwksp, name, EAPD_APP_DCS);
411 #endif /* BCM_DCS */
415 /* wan */
416 memset(ifnames, 0, sizeof(ifnames));
417 memset(name, 0, sizeof(name));
418 eapd_safe_get_conf(ifnames, sizeof(ifnames), "wan_ifnames");
419 foreach(name, ifnames, next) {
420 if (wps_app_enabled(name))
421 needStart |= eapd_add_interface(nwksp, name, EAPD_APP_WPS);
422 if (nas_app_enabled(name))
423 needStart |= eapd_add_interface(nwksp, name, EAPD_APP_NAS);
424 #ifdef BCM_DCS
425 if (dcs_app_enabled(name))
426 needStart |= eapd_add_interface(nwksp, name, EAPD_APP_DCS);
427 #endif /* BCM_DCS */
430 return ((needStart == TRUE) ? 0 : -1);
432 #endif /* EAPD_WKSP_AUTO_CONFIG */
434 static bool
435 eapd_add_interface(eapd_wksp_t *nwksp, char *ifname, eapd_app_mode_t mode)
437 int unit;
438 char os_name[IFNAMSIZ], prefix[8];
439 uchar mac[ETHER_ADDR_LEN];
440 char *lanifname;
441 eapd_app_t *app;
442 eapd_cb_t *cb;
443 void (*app_set_eventmask)(eapd_app_t *app) = NULL;
445 if (ifname == NULL)
446 return FALSE;
448 switch (mode) {
449 case EAPD_APP_NAS:
450 app = &nwksp->nas;
451 app_set_eventmask = (void*) nas_app_set_eventmask;
452 break;
453 case EAPD_APP_WPS:
454 app = &nwksp->wps;
455 app_set_eventmask = (void*) wps_app_set_eventmask;
456 break;
457 case EAPD_APP_SES:
458 app = &nwksp->ses;
459 if (app->cb)
460 return FALSE; /* ses already set */
461 app_set_eventmask = (void*) ses_app_set_eventmask;
462 break;
463 #ifdef BCM_DCS
464 case EAPD_APP_DCS:
465 app = &nwksp->dcs;
466 app_set_eventmask = (void*) dcs_app_set_eventmask;
467 break;
468 #endif /* BCM_DCS */
469 default:
470 return FALSE;
473 /* verify ifname */
474 if (nvifname_to_osifname(ifname, os_name, sizeof(os_name)) < 0)
475 return FALSE;
476 if (wl_probe(os_name) ||
477 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit)))
478 return FALSE;
479 /* convert eth name to wl name */
480 if (osifname_to_nvifname(ifname, prefix, sizeof(prefix)) != 0)
481 return FALSE;
483 /* check ifname in ifnames list */
484 if (find_in_list(app->ifnames, prefix))
485 return FALSE; /* duplicate */
486 /* find ifname in which lan?_ifnames or wan_ifnames */
487 (void) wl_hwaddr(os_name, mac);
488 if ((lanifname = get_ifname_by_wlmac(mac, ifname)) == NULL)
489 return FALSE;
491 /* check lanifname in cb list */
492 cb = app->cb;
493 while (cb) {
494 if (!strcmp(cb->ifname, lanifname))
495 break;
496 cb = cb->next;
499 if (!cb) {
500 /* prepare application structure */
501 cb = (eapd_cb_t *)malloc(sizeof(eapd_cb_t));
502 if (cb == NULL) {
503 EAPD_ERROR("app cb allocate fail...\n");
504 return FALSE;
506 memset(cb, 0, sizeof(eapd_cb_t));
508 /* add cb to the head */
509 cb->next = app->cb;
510 app->cb = cb;
512 /* save ifname */
513 strcpy(cb->ifname, lanifname);
515 /* save bcm event bitvec */
516 if (app_set_eventmask)
517 app_set_eventmask(app);
519 EAPD_INFO("add one interface cb for %s\n", cb->ifname);
522 /* save prefix name to ifnames */
523 add_to_list(prefix, app->ifnames, sizeof(app->ifnames));
525 return TRUE;
529 eapd_wksp_parse_cmd(int argc, char *argv[], eapd_wksp_t *nwksp)
531 int i = 1;
532 bool needStart = FALSE;
533 eapd_app_mode_t current_mode = EAPD_APP_UNKNOW;
535 if (nwksp == NULL)
536 return -1;
538 /* dispatch parse command */
539 while (i < argc) {
540 if (!strncmp(argv[i], "-wps", 4)) {
541 current_mode = EAPD_APP_WPS;
543 else if (!strncmp(argv[i], "-nas", 4)) {
544 current_mode = EAPD_APP_NAS;
546 else if (!strncmp(argv[i], "-ses", 4)) {
547 current_mode = EAPD_APP_SES;
549 #ifdef BCM_DCS
550 else if (!strncmp(argv[i], "-dcs", 4)) {
551 current_mode = EAPD_APP_DCS;
553 #endif /* BCM_DCS */
554 else {
555 needStart |= eapd_add_interface(nwksp, argv[i], current_mode);
557 i++;
559 return ((needStart == TRUE) ? 0 : -1);
562 eapd_wksp_t *
563 eapd_wksp_alloc_workspace(void)
565 eapd_wksp_t *nwksp = (eapd_wksp_t *)malloc(sizeof(eapd_wksp_t));
567 if (!nwksp)
568 return NULL;
569 memset(nwksp, 0, sizeof(eapd_wksp_t));
570 FD_ZERO(&nwksp->fdset);
571 nwksp->fdmax = -1;
572 nwksp->wps.appSocket = -1;
573 nwksp->nas.appSocket = -1;
574 nwksp->ses.appSocket = -1;
575 #ifdef BCM_DCS
576 nwksp->dcs.appSocket = -1;
577 #endif /* BCM_DCS */
579 EAPD_INFO("allocated EAPD workspace\n");
581 return nwksp;
584 void
585 eapd_wksp_free_workspace(eapd_wksp_t * nwksp)
587 if (!nwksp)
588 return;
589 free(nwksp);
590 EAPD_INFO("free EAPD workspace\n");
591 return;
595 eapd_wksp_init(eapd_wksp_t *nwksp)
597 if (nwksp == NULL)
598 return -1;
600 /* initial sta list */
601 if (sta_init(nwksp)) {
602 EAPD_ERROR("sta_init fail...\n");
603 return -1;
606 /* initial wps */
607 if (wps_app_init(nwksp)) {
608 EAPD_ERROR("wps_app_init fail...\n");
609 return -1;
612 /* initial nas */
613 if (nas_app_init(nwksp)) {
614 EAPD_ERROR("nas_app_init fail...\n");
615 return -1;
618 /* initial ses */
619 if (ses_app_init(nwksp)) {
620 EAPD_ERROR("ses_app_init fail...\n");
621 return -1;
625 #ifdef BCM_DCS
626 /* initial dcs */
627 if (dcs_app_init(nwksp)) {
628 EAPD_ERROR("dcs_app_init fail...\n");
629 return -1;
631 #endif /* BCM_DCS */
633 /* apply bcmevent bitvec */
634 if (event_init(nwksp)) {
635 EAPD_ERROR("event_init fail...\n");
636 return -1;
639 return 0;
643 eapd_wksp_deinit(eapd_wksp_t *nwksp)
645 if (nwksp == NULL) {
646 EAPD_ERROR("Wrong argument...\n");
647 return -1;
650 sta_deinit(nwksp);
651 wps_app_deinit(nwksp);
652 ses_app_deinit(nwksp);
653 nas_app_deinit(nwksp);
654 #ifdef BCM_DCS
655 dcs_app_deinit(nwksp);
656 #endif /* BCM_DCS */
657 event_deinit(nwksp);
659 return 0;
662 void
663 eapd_wksp_cleanup(eapd_wksp_t *nwksp)
665 eapd_wksp_deinit(nwksp);
666 eapd_wksp_free_workspace(nwksp);
669 static eapd_cb_t *
670 eapd_wksp_find_cb(eapd_app_t *app, char *wlifname, uint8 *mac)
672 eapd_cb_t *cb = NULL;
673 char *ifname;
675 if (!app)
676 return NULL;
678 ifname = get_ifname_by_wlmac(mac, wlifname);
679 if (ifname) {
680 cb = app->cb;
681 while (cb) {
682 if (!strcmp(ifname, cb->ifname))
683 break;
684 cb = cb->next;
688 if (!cb)
689 EAPD_ERROR("No cb found\n");
691 return cb;
694 void
695 eapd_wksp_dispatch(eapd_wksp_t *nwksp)
697 fd_set fdset;
698 struct timeval tv = {1, 0}; /* timed out every second */
699 int status, len, i, bytes;
700 uint8 *pkt;
701 eapd_brcm_socket_t *brcmSocket;
702 #ifdef BCMWPA2
703 eapd_preauth_socket_t *preauthSocket;
704 #endif
705 eapd_cb_t *cb;
706 eapd_wps_t *wps;
707 eapd_ses_t *ses;
708 eapd_nas_t *nas;
709 #ifdef BCM_DCS
710 eapd_dcs_t *dcs;
711 #endif /* BCM_DCS */
713 FD_ZERO(&nwksp->fdset);
714 nwksp->fdmax = -1;
716 pkt = &nwksp->packet[IFNAMSIZ];
717 len = sizeof(nwksp->packet) - IFNAMSIZ;
719 /* add brcm drvSocket */
720 for (i = 0; i < nwksp->brcmSocketCount; i++) {
721 brcmSocket = &nwksp->brcmSocket[i];
722 if (brcmSocket->inuseCount > 0) {
723 FD_SET(brcmSocket->drvSocket, &nwksp->fdset);
724 if (brcmSocket->drvSocket > nwksp->fdmax)
725 nwksp->fdmax = brcmSocket->drvSocket;
729 /* add wps appSocket */
730 wps = &nwksp->wps;
731 if (wps->appSocket >= 0) {
732 FD_SET(wps->appSocket, &nwksp->fdset);
733 if (wps->appSocket > nwksp->fdmax)
734 nwksp->fdmax = wps->appSocket;
737 /* add ses appSocket */
738 ses = &nwksp->ses;
739 if (ses->appSocket >= 0) {
740 FD_SET(ses->appSocket, &nwksp->fdset);
741 if (ses->appSocket > nwksp->fdmax)
742 nwksp->fdmax = ses->appSocket;
745 /* add nas appSocket */
746 nas = &nwksp->nas;
747 if (nas->appSocket >= 0) {
748 FD_SET(nas->appSocket, &nwksp->fdset);
749 if (nas->appSocket > nwksp->fdmax)
750 nwksp->fdmax = nas->appSocket;
753 #if BCMWPA2
754 /* add nas preauth drvSocket */
755 cb = nas->cb;
756 while (cb) {
757 preauthSocket = &cb->preauthSocket;
758 if (preauthSocket->drvSocket >= 0) {
759 FD_SET(preauthSocket->drvSocket, &nwksp->fdset);
760 if (preauthSocket->drvSocket > nwksp->fdmax)
761 nwksp->fdmax = preauthSocket->drvSocket;
763 cb = cb->next;
765 #endif
768 #ifdef BCM_DCS
769 /* add dcs appSocket */
770 dcs = &nwksp->dcs;
771 if (dcs->appSocket >= 0) {
772 FD_SET(dcs->appSocket, &nwksp->fdset);
773 if (dcs->appSocket > nwksp->fdmax)
774 nwksp->fdmax = dcs->appSocket;
776 #endif /* BCM_DCS */
778 if (nwksp->fdmax == -1) {
779 /* do shutdown procedure */
780 nwksp->flags = EAPD_WKSP_FLAG_SHUTDOWN;
781 EAPD_ERROR("There is no any sockets in the fd set, shutdown...\n");
782 return;
785 fdset = nwksp->fdset;
786 status = select(nwksp->fdmax+1, &fdset, NULL, NULL, &tv);
787 if (status > 0) {
788 /* check brcm drvSocket */
789 for (i = 0; i < nwksp->brcmSocketCount; i++) {
790 brcmSocket = &nwksp->brcmSocket[i];
791 if (brcmSocket->inuseCount > 0 &&
792 FD_ISSET(brcmSocket->drvSocket, &fdset)) {
794 * Use read instead of recv to receive BRCM packets,
795 * this change allow the drvSocket is a file descriptor,
797 bytes = read(brcmSocket->drvSocket, pkt, len);
798 if (bytes > 0) {
799 /* call brcm recv handler */
800 eapd_brcm_recv_handler(nwksp, brcmSocket, pkt, &bytes);
805 /* check wps appSocket */
806 if (wps->appSocket >= 0 &&
807 FD_ISSET(wps->appSocket, &fdset)) {
808 bytes = recv(wps->appSocket, pkt, len, 0);
809 if (bytes > ETHER_HDR_LEN) {
810 char *ifname = (char *) pkt;
811 struct ether_header *eth;
812 #ifdef BCMDBG
813 HEXDUMP_ASCII("EAPD:: data from WPS app", pkt, bytes);
814 #endif
815 /* ether header */
816 eth = (struct ether_header*)(ifname + IFNAMSIZ);
817 bytes -= IFNAMSIZ;
819 cb = eapd_wksp_find_cb(wps, ifname, eth->ether_shost);
820 /* send message data out. */
821 if (cb)
822 wps_app_recv_handler(nwksp, ifname, cb, (uint8 *)eth,
823 &bytes, (struct ether_addr *)&eth->ether_shost);
827 /* check ses appSocket */
828 if (ses->appSocket >= 0 &&
829 FD_ISSET(ses->appSocket, &fdset)) {
830 bytes = recv(ses->appSocket, pkt, len, 0);
831 if (bytes > ETHER_HDR_LEN) {
832 char *ifname = (char *) pkt;
833 struct ether_header *eth;
834 #ifdef BCMDBG
835 HEXDUMP_ASCII("EAPD:: data from SES app", pkt, bytes);
836 #endif
838 /* ether header */
839 eth = (struct ether_header*)(ifname + IFNAMSIZ);
840 bytes -= IFNAMSIZ;
842 cb = eapd_wksp_find_cb(ses, ifname, eth->ether_shost);
843 /* send message data out. */
844 if (cb)
845 ses_app_recv_handler(nwksp, ifname, cb, (uint8 *)eth,
846 &bytes);
850 /* check nas appSocket */
851 if (nas->appSocket >= 0 &&
852 FD_ISSET(nas->appSocket, &fdset)) {
853 bytes = recv(nas->appSocket, pkt, len, 0);
854 if (bytes > ETHER_HDR_LEN) {
855 char *ifname = (char *) pkt;
856 struct ether_header *eth;
858 #ifdef BCMDBG
859 HEXDUMP_ASCII("EAPD:: data from NAS app", pkt, bytes);
860 #endif
861 /* ether header */
862 eth = (struct ether_header*)(ifname + IFNAMSIZ);
863 bytes -= IFNAMSIZ;
865 cb = eapd_wksp_find_cb(nas, ifname, eth->ether_shost);
866 /* send message data out. */
867 if (cb)
868 nas_app_recv_handler(nwksp, ifname, cb, (uint8 *)eth,
869 &bytes);
873 #if BCMWPA2
874 /* check preauth drvSocket */
875 cb = nas->cb;
876 while (cb) {
877 preauthSocket = &cb->preauthSocket;
878 if (preauthSocket->drvSocket >= 0 &&
879 FD_ISSET(preauthSocket->drvSocket, &fdset)) {
881 * Use read instead of recv to receive PREAUTH packets,
882 * this change allow the drvSocket is a file descriptor,
884 bytes = read(preauthSocket->drvSocket, pkt, len);
885 if (bytes > 0) {
886 #ifdef BCMDBG
887 HEXDUMP_ASCII("EAPD:: data from PREAUTH Driver",
888 pkt, bytes);
889 #endif
890 /* call preauth recv handler */
891 eapd_preauth_recv_handler(nwksp, cb->ifname,
892 pkt, &bytes);
896 cb = cb->next;
898 #endif /* BCMWPA2 */
901 #ifdef BCM_DCS
902 /* check dcs appSocket */
903 if (dcs->appSocket >= 0 &&
904 FD_ISSET(dcs->appSocket, &fdset)) {
905 bytes = recv(dcs->appSocket, pkt, len, 0);
906 if (bytes > ETHER_HDR_LEN) {
907 char *ifname = (char *) pkt;
908 struct ether_header *eth;
909 #ifdef BCMDBG
910 HEXDUMP_ASCII("EAPD:: data from DCS app", pkt, bytes);
911 #endif
912 /* ether header */
913 eth = (struct ether_header*)(ifname + IFNAMSIZ);
914 bytes -= IFNAMSIZ;
916 cb = eapd_wksp_find_cb(dcs, ifname, eth->ether_shost);
917 /* send message data out. */
918 if (cb)
919 dcs_app_recv_handler(nwksp, cb, (uint8 *)eth, &bytes);
922 #endif /* BCM_DCS */
925 return;
929 eapd_wksp_main_loop(eapd_wksp_t *nwksp)
931 int ret;
933 /* init eapd */
934 ret = eapd_wksp_init(nwksp);
936 /* eapd wksp initialization finished */
937 eapd_wksp_inited = 1;
938 if (ret) {
939 EAPD_ERROR("Unable to initialize EAPD. Quitting...\n");
940 eapd_wksp_cleanup(nwksp);
941 return -1;
944 #if !defined(DEBUG) && !defined(__ECOS)
945 /* Daemonize */
946 if (daemon(1, 1) == -1) {
947 eapd_wksp_cleanup(nwksp);
948 perror("eapd_wksp_main_loop: daemon\n");
949 exit(errno);
951 #endif
953 while (1) {
954 /* check user command for shutdown */
955 if (nwksp->flags & EAPD_WKSP_FLAG_SHUTDOWN) {
956 eapd_wksp_cleanup(nwksp);
957 EAPD_INFO("NAS shutdown...\n");
958 return 0;
961 #ifdef EAPDDUMP
962 /* check dump */
963 if (nwksp->flags & EAPD_WKSP_FLAG_DUMP) {
964 eapd_dump(nwksp);
965 nwksp->flags &= ~EAPD_WKSP_FLAG_DUMP;
967 #endif
969 /* do packets dispatch */
970 eapd_wksp_dispatch(nwksp);
974 static int
975 eapd_brcm_dispatch(eapd_wksp_t *nwksp, eapd_brcm_socket_t *from, uint8 *pData, int Len)
977 if (nwksp == NULL || pData == NULL) {
978 EAPD_ERROR("Wrong arguments...\n");
979 return -1;
983 /* check nas application */
984 nas_app_handle_event(nwksp, pData, Len, from->ifname);
986 /* check wps application */
987 wps_app_handle_event(nwksp, pData, Len, from->ifname);
989 /* check ses application */
990 ses_app_handle_event(nwksp, pData, Len, from->ifname);
993 #ifdef BCM_DCS
994 /* check dcs application */
995 dcs_app_handle_event(nwksp, pData, Len, from->ifname);
996 #endif /* BCM_DCS */
997 return 0;
1002 * look for a raw brcm event socket connected to
1003 * interface "ifname".
1005 eapd_brcm_socket_t*
1006 eapd_find_brcm(eapd_wksp_t *nwksp, char *ifname)
1008 int i, brcmSocketCount;
1009 eapd_brcm_socket_t *brcmSocket;
1011 if (nwksp == NULL || ifname == NULL) {
1012 EAPD_ERROR("Wrong arguments...\n");
1013 return NULL;
1016 brcmSocketCount = nwksp->brcmSocketCount;
1017 for (i = 0; i < brcmSocketCount; i++) {
1018 brcmSocket = &nwksp->brcmSocket[i];
1019 if (brcmSocket->inuseCount > 0) {
1020 if (!strcmp(brcmSocket->ifname, ifname)) {
1021 EAPD_INFO("Find brcm interface %s\n", ifname);
1022 return brcmSocket;
1028 EAPD_INFO("Not found brcm interface %s\n", ifname);
1029 return NULL;
1033 eapd_brcm_socket_t*
1034 eapd_add_brcm(eapd_wksp_t *nwksp, char *ifname)
1036 int i;
1037 eapd_brcm_socket_t *brcmSocket;
1039 if (nwksp == NULL || ifname == NULL) {
1040 EAPD_ERROR("Wrong arguments...\n");
1041 return NULL;
1044 brcmSocket = eapd_find_brcm(nwksp, ifname);
1045 if (brcmSocket) {
1046 brcmSocket->inuseCount++;
1047 return brcmSocket;
1051 /* not found, find inuseCount is zero first */
1052 for (i = 0; i < nwksp->brcmSocketCount; i++) {
1053 brcmSocket = &nwksp->brcmSocket[i];
1054 if (brcmSocket->inuseCount == 0)
1055 break;
1059 /* not found inuseCount is zero */
1060 if (i == nwksp->brcmSocketCount) {
1061 if (nwksp->brcmSocketCount >= EAPD_WKSP_MAX_NO_BRCM) {
1062 EAPD_ERROR("brcmSocket number is not enough, max %d\n",
1063 EAPD_WKSP_MAX_NO_BRCM);
1064 return NULL;
1066 nwksp->brcmSocketCount++;
1069 brcmSocket = &nwksp->brcmSocket[i];
1071 memset(brcmSocket, 0, sizeof(eapd_brcm_socket_t));
1072 strcpy(brcmSocket->ifname, ifname);
1073 if (eapd_brcm_open(nwksp, brcmSocket) < 0) {
1074 EAPD_ERROR("open brcm socket on %s error!!\n", ifname);
1075 return NULL;
1078 return brcmSocket;
1082 eapd_del_brcm(eapd_wksp_t *nwksp, eapd_brcm_socket_t *sock)
1084 int i;
1085 eapd_brcm_socket_t *brcmSocket;
1087 if (nwksp == NULL || sock == NULL) {
1088 EAPD_ERROR("Wrong arguments...\n");
1089 return -1;
1092 /* find it first. */
1093 for (i = 0; i < nwksp->brcmSocketCount; i++) {
1094 brcmSocket = &nwksp->brcmSocket[i];
1095 if (brcmSocket->inuseCount > 0 &&
1096 !strcmp(brcmSocket->ifname, sock->ifname)) {
1097 EAPD_INFO("Find brcm interface %s, brcmSocket->inuseCount=%d\n",
1098 sock->ifname, brcmSocket->inuseCount);
1099 brcmSocket->inuseCount--;
1100 if (brcmSocket->inuseCount == 0) {
1101 EAPD_INFO("close brcm drvSocket %d\n", brcmSocket->drvSocket);
1102 eapd_brcm_close(brcmSocket->drvSocket);
1103 brcmSocket->drvSocket = -1;
1105 return 0;
1109 /* not found */
1110 EAPD_INFO("Not found brcm interface to del %s\n", sock->ifname);
1111 return -1;
1114 /* dispatch EAPOL packet from brcmevent. */
1115 static void
1116 eapd_eapol_dispatch(eapd_wksp_t *nwksp, eapd_brcm_socket_t *from, uint8 *pData, int *pLen)
1118 eapd_sta_t *sta;
1119 eapol_header_t *eapol;
1120 eap_header_t *eap;
1121 char *ifname;
1123 if (!nwksp || !from || !pData) {
1124 EAPD_ERROR("Wrong argument...\n");
1125 return;
1128 #ifdef BCMDBG
1129 HEXDUMP_ASCII("EAPD:: eapol data from BRCM driver", pData, *pLen);
1130 #endif
1132 /* incoming ifname */
1133 ifname = (char *) pData;
1135 /* eapol header */
1136 eapol = (eapol_header_t *)(ifname + IFNAMSIZ);
1137 eap = (eap_header_t *) eapol->body;
1139 sta = sta_lookup(nwksp, (struct ether_addr *) eapol->eth.ether_shost,
1140 (struct ether_addr *) eapol->eth.ether_dhost, ifname, EAPD_SEARCH_ENTER);
1141 if (!sta) {
1142 EAPD_ERROR("no STA struct available\n");
1143 return;
1146 if (eapol->version < sta->eapol_version) {
1147 EAPD_ERROR("EAPOL version %d packet received, current version is %d\n",
1148 eapol->version, sta->eapol_version);
1151 EAPD_INFO("sta->pae_state=%d sta->mode=%d\n", sta->pae_state, sta->mode);
1153 /* Pass EAP_RESPONSE to WPS module. */
1154 if (sta->pae_state >= EAPD_IDENTITY &&
1155 (sta->mode == EAPD_STA_MODE_WPS || sta->mode == EAPD_STA_MODE_WPS_ENR) &&
1156 eapol->type == EAP_PACKET &&
1157 (eap->type == EAP_EXPANDED || eap->code == EAP_FAILURE)) {
1158 switch (eap->code) {
1159 case EAP_REQUEST:
1160 case EAP_FAILURE:
1161 /* in case of router running enr */
1162 EAPD_INFO("EAP %s Packet received...\n",
1163 eap->code == EAP_REQUEST ? "Request" : "Failure");
1165 /* Send to wps-monitor */
1166 if (sta->mode == EAPD_STA_MODE_WPS_ENR) {
1167 /* monitor eapol packet */
1168 if (eap->code == EAP_FAILURE || eap->code == EAP_SUCCESS) {
1169 sta_remove(nwksp, sta);
1171 #ifdef BCMDBG
1172 HEXDUMP_ASCII("Receive, EAP Request", pData, *pLen);
1173 #endif
1174 wps_app_monitor_sendup(nwksp, pData, *pLen, from->ifname);
1176 else
1177 return;
1178 break;
1180 case EAP_RESPONSE:
1181 EAPD_INFO("EAP Response Packet received...\n");
1183 /* Send to wps-monitor */
1184 if (sta->mode == EAPD_STA_MODE_WPS)
1185 wps_app_monitor_sendup(nwksp, pData, *pLen, from->ifname);
1186 else
1187 return;
1188 break;
1190 default:
1191 /* Do nothing */
1192 break;
1195 return;
1198 /* Check SES IDENTITY */
1199 if ((eapol->type == EAP_PACKET) &&
1200 (eap->type == EAP_EXPANDED) &&
1201 (eap->data[2] == (BCM_SMI_ID & 0xff)) &&
1202 (eap->data[1] == ((BCM_SMI_ID & 0xff00) >> 8)) &&
1203 (eap->data[0] == ((BCM_SMI_ID & 0xff000) >> 16))) {
1204 /* Send to SES module. */
1205 ses_app_sendup(nwksp, pData, *pLen, from->ifname);
1207 sta->mode = EAPD_STA_MODE_SES;
1208 sta->pae_state = EAPD_IDENTITY;
1210 return;
1213 /* We handle
1214 * 1. Receive EAPOL-Start and send EAP_REQUEST for EAP_IDENTITY
1215 * 2. Receive EAP_IDENTITY and pass it to NAS if not a WPS IDENTITY,
1216 * NAS need to record identity.
1217 * 3. Pass NAS other EAPOL type
1219 switch (eapol->type) {
1220 case EAP_PACKET:
1221 if (ntohs(eapol->length) >= (EAP_HEADER_LEN + 1)) {
1222 EAPD_INFO("STA State=%d EAP Packet Type=%d Id=%d code=%d\n",
1223 sta->pae_state, eap->type, eap->id, eap->code);
1225 switch (eap->type) {
1226 case EAP_IDENTITY:
1227 EAPD_INFO("Receive , eap code=%d, id = %d, length=%d, type=%d\n",
1228 eap->code, eap->id, ntohs(eap->length), eap->type);
1229 #ifdef BCMDBG
1230 HEXDUMP_ASCII("Receive, EAP Identity", eap->data,
1231 ntohs(eap->length) - EAP_HEADER_LEN - 1);
1232 #endif
1233 /* Store which interface sta come from */
1234 memcpy(&sta->bssid, &eapol->eth.ether_dhost, ETHER_ADDR_LEN);
1235 memcpy(&sta->ifname, ifname, IFNAMSIZ);
1237 if (eapd_get_method(eap->data) == EAP_TYPE_WSC) {
1238 EAPD_INFO("This is a wps eap identity response!\n");
1240 /* Send to WPS-Monitor module. */
1241 wps_app_monitor_sendup(nwksp, pData, *pLen, from->ifname);
1243 sta->mode = EAPD_STA_MODE_WPS;
1244 } else if (sta->mode == EAPD_STA_MODE_WPS_ENR) {
1245 EAPD_INFO("This is a wps eap identity request!\n");
1247 /* Send to WPS-Monitor module. */
1248 wps_app_monitor_sendup(nwksp, pData, *pLen, from->ifname);
1251 * sta mode EAPD_STA_MODE_WPS_ENR set in
1252 * wps_app_recv_handler, when enr initial send
1253 * EAPOL-START.
1256 else {
1257 /* Send to NAS module. */
1258 nas_app_sendup(nwksp, pData, *pLen, from->ifname);
1259 sta->mode = EAPD_STA_MODE_NAS;
1261 sta->pae_state = EAPD_IDENTITY;
1262 break;
1265 #ifdef __CONFIG_WFI__
1266 case EAP_NAK:
1267 if (sta->mode == EAPD_STA_MODE_UNKNOW &&
1268 sta->pae_state == EAPD_INITIALIZE &&
1269 eap->code == EAP_RESPONSE) {
1271 * EAP-RESPONSE-NAK for WFI reject.
1272 * Send to WPS-Monitor module.
1274 wps_app_monitor_sendup(nwksp, pData, *pLen, from->ifname);
1275 break;
1277 /* Fall through */
1278 #endif /* __CONFIG_WFI__ */
1282 default:
1283 /* Send to NAS module. */
1284 nas_app_sendup(nwksp, pData, *pLen, from->ifname);
1285 sta->mode = EAPD_STA_MODE_UNKNOW;
1286 break;
1289 break;
1291 case EAPOL_START:
1292 EAPD_INFO("EAPOL Start\n");
1294 sta->pae_id = 0;
1295 memcpy(&sta->bssid, &eapol->eth.ether_dhost, ETHER_ADDR_LEN);
1296 memcpy(&sta->ifname, ifname, IFNAMSIZ);
1298 /* check EAPD interface application capability first */
1299 if (!eapd_valid_eapol_start(nwksp, from, ifname))
1300 break;
1302 /* break out if STA is only PSK */
1303 if (sta->mode == EAPD_STA_MODE_NAS_PSK)
1304 break;
1306 eapd_eapol_canned_send(nwksp, from, sta, EAP_REQUEST, EAP_IDENTITY);
1307 sta->mode = EAPD_STA_MODE_UNKNOW;
1308 break;
1310 case EAPOL_LOGOFF:
1311 EAPD_INFO("EAPOL Logoff sta mode %d\n", sta->mode);
1313 /* Send EAPOL_LOGOFF to application. */
1314 switch (sta->mode) {
1315 case EAPD_STA_MODE_WPS:
1316 case EAPD_STA_MODE_WPS_ENR:
1317 wps_app_monitor_sendup(nwksp, pData, *pLen, from->ifname);
1318 break;
1320 case EAPD_STA_MODE_NAS:
1321 case EAPD_STA_MODE_NAS_PSK:
1322 nas_app_sendup(nwksp, pData, *pLen, from->ifname);
1323 break;
1325 default:
1326 EAPD_INFO("Ignore EAPOL Logoff\n");
1327 break;
1329 break;
1331 default:
1332 EAPD_INFO("unknown EAPOL type %d\n", eapol->type);
1334 /* Send to NAS module. */
1335 nas_app_sendup(nwksp, pData, *pLen, from->ifname);
1336 break;
1339 return;
1343 /* Handle brcmevent type packet from any interface */
1344 void
1345 eapd_brcm_recv_handler(eapd_wksp_t *nwksp, eapd_brcm_socket_t *from, uint8 *pData, int *pLen)
1347 eapol_header_t *eapol;
1348 bcm_event_t *dpkt = (bcm_event_t *)pData;
1349 unsigned int len;
1350 char *ifname, ifname_tmp[BCM_MSG_IFNAME_MAX];
1352 if (nwksp == NULL || from == NULL || dpkt == NULL) {
1353 EAPD_ERROR("Wrong argument...\n");
1354 return;
1357 switch (ntohs(dpkt->bcm_hdr.usr_subtype)) {
1358 case BCMILCP_BCM_SUBTYPE_EVENT:
1359 switch (ntohl(dpkt->event.event_type)) {
1360 case WLC_E_EAPOL_MSG:
1361 EAPD_INFO("%s: recved wl eapol packet in brcmevent bytes: %d\n",
1362 dpkt->event.ifname, *pLen);
1364 len = ntohl(dpkt->event.datalen);
1366 /* Reconstructs a EAPOL packet from the received packet */
1367 /* Point the EAPOL packet to the start of the data portion of the
1368 * received packet minus some space to add the ethernet header to the
1369 * EAPOL packet
1371 eapol = (eapol_header_t *)((char *)(dpkt + 1) - ETHER_HDR_LEN);
1372 ifname = (char *)eapol - BCM_MSG_IFNAME_MAX;
1374 /* Save incoming interface name to temp_ifname */
1375 bcopy(dpkt->event.ifname, ifname_tmp, BCM_MSG_IFNAME_MAX);
1377 /* Now move the received packet's ethernet header to the head of the
1378 * EAPOL packet
1380 memmove((char *)eapol, (char *)pData, ETHER_HDR_LEN);
1382 /* Set the EAPOL packet type correctly */
1383 eapol->eth.ether_type = htons(ETHER_TYPE_802_1X);
1385 /* The correct shost address was encapsulated to the event struct by the
1386 * driver, copy it to the EAPOL packet's ethernet header
1388 bcopy(dpkt->event.addr.octet, eapol->eth.ether_shost, ETHER_ADDR_LEN);
1390 /* Save incoming interface name */
1391 bcopy(ifname_tmp, ifname, BCM_MSG_IFNAME_MAX);
1393 len = len + ETHER_HDR_LEN + BCM_MSG_IFNAME_MAX;
1394 eapd_eapol_dispatch(nwksp, from, (void *)ifname, (int *)&len);
1395 return;
1397 default:
1398 /* dispatch brcnevent to wps, ses(?), nas, wapid */
1399 eapd_brcm_dispatch(nwksp, from, pData, *pLen);
1400 return;
1402 break;
1404 default: /* not a NAS supported message so return an error */
1405 EAPD_ERROR("%s: ERROR: recved unknown packet interface subtype "
1406 "0x%x bytes: %d\n", dpkt->event.ifname,
1407 ntohs(dpkt->bcm_hdr.usr_subtype), *pLen);
1408 return;
1411 return;
1414 #if BCMWPA2
1415 /* Handle PreAuth packet from any interface for nas
1416 * Receive it and just pass to nas
1418 void
1419 eapd_preauth_recv_handler(eapd_wksp_t *nwksp, char *from, uint8 *pData, int *pLen)
1421 if (!nwksp || !from || !pData) {
1422 EAPD_ERROR("Wrong argument...\n");
1423 return;
1426 /* prepend ifname, we reserved IFNAMSIZ length already */
1427 pData -= IFNAMSIZ;
1428 *pLen += IFNAMSIZ;
1429 memcpy(pData, from, IFNAMSIZ);
1431 /* Do not parse it right now, just pass to NAS */
1432 nas_app_sendup(nwksp, pData, *pLen, from);
1433 return;
1435 #endif /* BCMWPA2 */
1437 static unsigned char
1438 eapd_get_method(unsigned char *user)
1440 unsigned char ret = 0;
1441 int i;
1443 for (i = 0; i < EAPD_WKSP_EAP_USER_NUM; i++) {
1444 if (memcmp(user, eapdispuserlist[i].identity,
1445 eapdispuserlist[i].identity_len) == 0) {
1446 ret = eapdispuserlist[i].method;
1447 break;
1451 return ret;
1455 static int
1456 sta_init(eapd_wksp_t *nwksp)
1458 return 0;
1461 static int
1462 sta_deinit(eapd_wksp_t *nwksp)
1464 return 0;
1467 void
1468 sta_remove(eapd_wksp_t *nwksp, eapd_sta_t *sta)
1470 eapd_sta_t *sta_list;
1471 uint hash;
1473 EAPD_INFO("sta %s remove\n", ether_etoa((uchar *)&sta->ea, eabuf));
1475 if (sta == NULL) {
1476 EAPD_ERROR("called with NULL STA ponter\n");
1477 return;
1480 /* Remove this one from its hashed list. */
1481 hash = EAPD_PAE_HASH(&sta->ea);
1482 sta_list = nwksp->sta_hashed[hash];
1484 if (sta_list == sta) {
1485 /* It was the head, so its next is the new head. */
1486 nwksp->sta_hashed[hash] = sta->next;
1489 else {
1490 /* Find the one that points to it and change the pointer. */
1491 while ((sta_list != NULL) && (sta_list->next != sta))
1492 sta_list = sta_list->next;
1493 if (sta_list == NULL) {
1494 EAPD_INFO("sta %s not in hash list\n",
1495 ether_etoa((uchar *)&sta->ea, eabuf));
1497 else {
1498 sta_list->next = sta->next;
1501 sta->used = FALSE;
1502 return;
1506 * Search for or create a STA struct.
1507 * If `mode' is not EAPD_SEARCH_ENTER, do not create it when one is not found.
1508 * NOTE: bssid_ea is a spoof mac.
1510 eapd_sta_t*
1511 sta_lookup(eapd_wksp_t *nwksp, struct ether_addr *sta_ea, struct ether_addr *bssid_ea,
1512 char *ifname, eapd_lookup_mode_t mode)
1514 unsigned int hash;
1515 eapd_sta_t *sta;
1516 time_t now, oldest;
1518 EAPD_INFO("lookup for sta %s\n", ether_etoa((uchar *)sta_ea, eabuf));
1520 hash = EAPD_PAE_HASH(sta_ea);
1522 /* Search for entry in the hash table */
1523 for (sta = nwksp->sta_hashed[hash];
1524 sta && memcmp(&sta->ea, sta_ea, ETHER_ADDR_LEN);
1525 sta = sta->next);
1527 /* One second resolution is probably good enough. */
1528 (void) time(&now);
1530 /* Not found in sta_hashed, allocate a new entry */
1531 if (!sta) {
1532 int i, old_idx = -1;
1534 /* Don't make an unwanted entry. */
1535 if (mode == EAPD_SEARCH_ONLY)
1536 return NULL;
1538 oldest = now;
1539 for (i = 0; i < EAPD_WKSP_MAX_SUPPLICANTS; i++) {
1540 if (!nwksp->sta[i].used)
1541 break;
1542 else if (nwksp->sta[i].last_use < oldest) {
1543 oldest = nwksp->sta[i].last_use;
1544 old_idx = i;
1548 if (i < EAPD_WKSP_MAX_SUPPLICANTS) {
1549 sta = &nwksp->sta[i];
1551 else if (old_idx == -1) {
1552 /* Full up with all the same timestamp? Can
1553 * this really happen?
1555 return NULL;
1557 else {
1558 /* Didn't find one unused, so age out LRU not wps entry. */
1559 sta = &nwksp->sta[old_idx];
1560 sta_remove(nwksp, sta);
1563 /* Initialize entry */
1564 memset(sta, 0, (sizeof(eapd_sta_t)));
1565 memcpy(&sta->ea, sta_ea, ETHER_ADDR_LEN);
1566 memcpy(&sta->bssid, bssid_ea, ETHER_ADDR_LEN);
1567 memcpy(&sta->ifname, ifname, IFNAMSIZ);
1568 sta->used = TRUE;
1569 sta->eapol_version = WPA_EAPOL_VERSION;
1571 /* Initial STA state */
1572 sta->pae_state = EAPD_INITIALIZE;
1574 /* initial mode */
1575 sta->mode = EAPD_STA_MODE_UNKNOW;
1576 EAPD_INFO("Create eapd sta %s\n", ether_etoa((uchar *)&sta->ea, eabuf));
1578 /* Add entry to the cache */
1579 sta->next = nwksp->sta_hashed[hash];
1580 nwksp->sta_hashed[hash] = sta;
1582 else if (bssid_ea &&
1583 (memcmp(&sta->bssid, bssid_ea, ETHER_ADDR_LEN) || strcmp(sta->ifname, ifname))) {
1584 /* from different wl */
1585 memcpy(&sta->bssid, bssid_ea, ETHER_ADDR_LEN);
1586 memcpy(&sta->ifname, ifname, IFNAMSIZ);
1588 /* Initial STA state */
1589 sta->pae_state = EAPD_INITIALIZE;
1591 /* initial mode */
1592 sta->mode = EAPD_STA_MODE_UNKNOW;
1593 EAPD_INFO("sta %s come from changed.\n", ether_etoa((uchar *)&sta->ea, eabuf));
1596 sta->last_use = now;
1597 return sta;
1600 static int
1601 event_init(eapd_wksp_t *nwksp)
1603 int i, ret, unit, wlunit[16];
1604 eapd_wps_t *wps;
1605 eapd_nas_t *nas;
1606 eapd_ses_t *ses;
1607 #ifdef BCM_DCS
1608 eapd_dcs_t *dcs;
1609 #endif /* BCM_DCS */
1610 char name[IFNAMSIZ], os_name[IFNAMSIZ], all_ifnames[IFNAMSIZ * EAPD_WKSP_MAX_NO_IFNAMES];
1611 char *next;
1612 uchar bitvec[WL_EVENTING_MASK_LEN];
1614 memset(wlunit, -1, sizeof(wlunit));
1615 memset(name, 0, sizeof(name));
1616 memset(all_ifnames, 0, sizeof(all_ifnames));
1617 wps = &nwksp->wps;
1618 nas = &nwksp->nas;
1619 ses = &nwksp->ses;
1620 #ifdef BCM_DCS
1621 dcs = &nwksp->dcs;
1622 #endif /* BCM_DCS */
1624 /* add all application ifnames to all_ifnames */
1625 strcpy(all_ifnames, wps->ifnames);
1626 foreach(name, nas->ifnames, next) {
1627 add_to_list(name, all_ifnames, sizeof(all_ifnames));
1629 memset(name, 0, sizeof(name));
1630 foreach(name, ses->ifnames, next) {
1631 add_to_list(name, all_ifnames, sizeof(all_ifnames));
1633 #ifdef BCM_DCS
1634 memset(name, 0, sizeof(name));
1635 foreach(name, dcs->ifnames, next) {
1636 add_to_list(name, all_ifnames, sizeof(all_ifnames));
1638 #endif /* BCM_DCS */
1639 /* check each name in all_ifnames */
1640 memset(name, 0, sizeof(name));
1641 foreach(name, all_ifnames, next) {
1642 /* apply bitvec to driver */
1643 memset(bitvec, 0, WL_EVENTING_MASK_LEN);
1644 memset(os_name, 0, sizeof(os_name));
1645 if (nvifname_to_osifname(name, os_name, sizeof(os_name)) < 0)
1646 continue;
1647 if (wl_probe(os_name) ||
1648 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit)))
1649 continue;
1652 * NOTE: Because wl0.1 wl0.2 have same event queue as wl0, we can not
1653 * have separate event bitvec just like bsscfg.
1655 if (wlunit[unit] != -1) {
1656 /* get current bitvec value */
1657 ret = wl_iovar_get(os_name, "event_msgs", bitvec, sizeof(bitvec));
1658 if (ret) {
1659 EAPD_ERROR("Get event_msg error %d on %s[%s]\n",
1660 ret, name, os_name);
1661 continue;
1665 /* is wps have this name */
1666 if (find_in_list(wps->ifnames, name)) {
1667 for (i = 0; i < WL_EVENTING_MASK_LEN; i++) {
1668 bitvec[i] |= wps->bitvec[i];
1671 /* is nas have this name */
1672 if (find_in_list(nas->ifnames, name)) {
1673 for (i = 0; i < WL_EVENTING_MASK_LEN; i++) {
1674 bitvec[i] |= nas->bitvec[i];
1677 /* is ses have this name */
1678 if (find_in_list(ses->ifnames, name)) {
1679 for (i = 0; i < WL_EVENTING_MASK_LEN; i++) {
1680 bitvec[i] |= ses->bitvec[i];
1684 #ifdef BCM_DCS
1685 /* is dcs have this name */
1686 if (find_in_list(dcs->ifnames, name)) {
1687 for (i = 0; i < WL_EVENTING_MASK_LEN; i++) {
1688 bitvec[i] |= dcs->bitvec[i];
1691 #endif /* BCM_DCS */
1693 ret = wl_iovar_set(os_name, "event_msgs", bitvec, sizeof(bitvec));
1694 wlunit[unit] = unit;
1695 if (ret) {
1696 EAPD_ERROR("Set event_msg error %d on %s[%s]\n", ret, name, os_name);
1698 else {
1699 #ifdef BCMDBG
1700 int j, flag;
1701 if (eapd_msg_level) {
1702 flag = 1;
1703 for (i = 0; i < WL_EVENTING_MASK_LEN; i++) {
1704 for (j = 0; j < 8; j++) {
1705 if (isset(&bitvec[i], j)) {
1706 if (flag) {
1707 EAPD_PRINT("Set event_msg bitvec [%d",
1708 (i*8+j));
1709 flag = 0;
1711 else {
1712 EAPD_PRINT(" %d", (i*8+j));
1717 EAPD_PRINT("] on %s[%s]\n", name, os_name);
1719 #endif /* BCMDBG */
1723 return 0;
1726 static int
1727 event_deinit(eapd_wksp_t *nwksp)
1729 return 0;
1732 /* Validate handling EAPOL START packet on this receive interface */
1733 static bool
1734 eapd_valid_eapol_start(eapd_wksp_t *nwksp, eapd_brcm_socket_t *from, char *ifname)
1736 eapd_nas_t *nas;
1737 eapd_wps_t *wps;
1738 char nv_name[IFNAMSIZ];
1739 bool needHandle = FALSE;
1741 if (!nwksp || !from || !ifname)
1742 return FALSE;
1744 /* convert eth ifname to wl name (nv name) */
1745 if (osifname_to_nvifname(ifname, nv_name, sizeof(nv_name)) != 0)
1746 return FALSE;
1748 nas = &nwksp->nas;
1749 wps = &nwksp->wps;
1751 /* Is this brcmSocket have to handle EAPOL START */
1752 if (from->flag & (EAPD_CAP_NAS | EAPD_CAP_WPS)) {
1753 /* Is this receive interface have to handle EAPOL START */
1754 /* check nas */
1755 if (find_in_list(nas->ifnames, nv_name))
1756 needHandle = TRUE;
1758 /* check wps */
1759 if (find_in_list(wps->ifnames, nv_name))
1760 needHandle = TRUE;
1763 return needHandle;
1766 void
1767 eapd_wksp_clear_inited()
1769 eapd_wksp_inited = 0;
1772 int eapd_wksp_is_inited()
1774 return eapd_wksp_inited;