Migrate UI cleanup phase 4 from MIPS into ARM
[tomato.git] / release / src-rt-6.x.4708 / router / eapd_arm / nas_eap.c
blob0c8116e48a35ca5657da07b424c1ba4bf1884c08
1 /*
2 * Application-specific portion of EAPD
3 * (NAS)
5 * Copyright (C) 2013, Broadcom Corporation
6 * All Rights Reserved.
7 *
8 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
9 * the contents of this file may not be disclosed to third parties, copied
10 * or duplicated in any form, in whole or in part, without the prior
11 * written permission of Broadcom Corporation.
13 * $Id: nas_eap.c 386296 2013-02-20 05:48:14Z $
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.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 <bcmendian.h>
31 #include <wlutils.h>
32 #include <eapd.h>
33 #include <shutils.h>
34 #include <UdpLib.h>
35 #include <nas.h>
36 #include <security_ipc.h>
37 #include <bcmwpa.h>
39 /* mapping from WPA_CIPHER_XXXX to wsec */
40 #define NAS_APP_WPA_CIPHER2WSEC(cipher) ((cipher) == WPA_CIPHER_WEP_40 ? WEP_ENABLED : \
41 (cipher) == WPA_CIPHER_WEP_104 ? WEP_ENABLED : \
42 (cipher) == WPA_CIPHER_TKIP ? TKIP_ENABLED : \
43 (cipher) == WPA_CIPHER_AES_CCM ? AES_ENABLED : \
46 static uint32
47 nas_app_wpa_akm2auth(uint32 akm)
49 switch (akm) {
50 case RSN_AKM_PSK:
51 return WPA_AUTH_PSK;
52 case RSN_AKM_UNSPECIFIED:
53 return WPA_AUTH_UNSPECIFIED;
54 case RSN_AKM_NONE:
55 default:
56 return WPA_AUTH_NONE;
60 static uint32
61 nas_app_wpa2_akm2auth(uint32 akm)
63 switch (akm) {
64 case RSN_AKM_PSK:
65 return WPA2_AUTH_PSK;
66 case RSN_AKM_UNSPECIFIED:
67 return WPA2_AUTH_UNSPECIFIED;
68 case RSN_AKM_NONE:
69 default:
70 return WPA_AUTH_NONE;
74 static int
75 nas_app_wpa_auth2mode(int auth)
77 switch (auth) {
78 case WPA_AUTH_PSK:
79 return WPA_PSK;
80 case WPA_AUTH_UNSPECIFIED:
81 return WPA;
82 case WPA2_AUTH_PSK:
83 return WPA2_PSK;
84 case WPA2_AUTH_UNSPECIFIED:
85 return WPA2;
86 case WPA_AUTH_DISABLED:
87 default:
88 return RADIUS;
92 static bool
93 nas_app_is_wpa_ie(uint8 *ie, uint8 **tlvs, uint *tlvs_len)
95 /* If the contents match the WPA_OUI and type=1 */
96 if ((ie[TLV_LEN_OFF] > (WPA_OUI_LEN+1)) &&
97 !bcmp(&ie[TLV_BODY_OFF], WPA_OUI "\x01", WPA_OUI_LEN + 1)) {
98 return TRUE;
101 /* point to the next ie */
102 ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
103 /* calculate the length of the rest of the buffer */
104 *tlvs_len -= (int)(ie - *tlvs);
105 /* update the pointer to the start of the buffer */
106 *tlvs = ie;
108 return FALSE;
111 static bool
112 nas_app_is_wps_ie(uint8 *ie, uint8 **tlvs, uint *tlvs_len)
114 /* If the contents match the WPA_OUI and type=4 */
115 if ((ie[TLV_LEN_OFF] > (WPA_OUI_LEN+1)) &&
116 !bcmp(&ie[TLV_BODY_OFF], WPA_OUI "\x04", WPA_OUI_LEN + 1)) {
117 return TRUE;
120 /* point to the next ie */
121 ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
122 /* calculate the length of the rest of the buffer */
123 *tlvs_len -= (int)(ie - *tlvs);
124 /* update the pointer to the start of the buffer */
125 *tlvs = ie;
127 return FALSE;
130 static bcm_tlv_t *
131 nas_app_parse_tlvs(void *buf, int buflen, uint key)
133 bcm_tlv_t *elt;
134 int totlen;
136 elt = (bcm_tlv_t*)buf;
137 totlen = buflen;
139 /* find tagged parameter */
140 while (totlen >= 2) {
141 int len = elt->len;
143 /* validate remaining totlen */
144 if ((elt->id == key) && (totlen >= (len + 2)))
145 return (elt);
147 elt = (bcm_tlv_t*)((uint8*)elt + (len + 2));
148 totlen -= (len + 2);
151 return NULL;
154 static wpa_ie_fixed_t *
155 nas_app_find_wpaie(uint8 *parse, uint len)
157 bcm_tlv_t *ie;
159 while ((ie = nas_app_parse_tlvs(parse, len, DOT11_MNG_WPA_ID))) {
160 if (nas_app_is_wpa_ie((uint8*)ie, &parse, &len)) {
161 return (wpa_ie_fixed_t *)ie;
164 return NULL;
167 static wpa_ie_fixed_t *
168 nas_app_find_wpsie(uint8 *data, uint data_len)
170 uint8 *parse = data;
171 uint len = data_len;
172 bcm_tlv_t *ie;
174 while ((ie = nas_app_parse_tlvs(parse, len, DOT11_MNG_WPA_ID))) {
175 if (nas_app_is_wps_ie((uint8*)ie, &parse, &len)) {
176 return (wpa_ie_fixed_t *)ie;
179 return NULL;
182 /* decode WPA IE to retrieve supplicant wsec, auth mode, and pmk cached */
183 /* pmkc - 0:no pmkid in ie, -1:pmkid not found, 1:pmkid found */
184 static int
185 nas_app_parse_ie(uint8 *ie, int ie_len, uint32 *wsec, uint32 *mode)
187 int len;
188 wpa_suite_mcast_t *mcast = NULL;
189 wpa_suite_ucast_t *ucast = NULL;
190 wpa_suite_auth_key_mgmt_t *mgmt = NULL;
191 uint8 *oui;
193 uint16 count;
194 uint32 m = 0;
195 uint32 (*akm2auth)(uint32 akm) = NULL;
196 wpa_ie_fixed_t *wpaie = NULL;
197 uint8 *parse = ie;
198 int parse_len = ie_len;
201 /* Search WPA IE */
202 wpaie = nas_app_find_wpaie(parse, parse_len);
203 /* Search RSN IE */
204 if (!wpaie)
205 wpaie = (wpa_ie_fixed_t *)nas_app_parse_tlvs(ie, ie_len, DOT11_MNG_RSN_ID);
207 /* No WPA or RSN IE */
208 if (!wpaie)
209 return -1;
211 /* type specific header processing */
212 switch (wpaie->tag) {
213 case DOT11_MNG_RSN_ID: {
214 wpa_rsn_ie_fixed_t *rsnie = (wpa_rsn_ie_fixed_t *)wpaie;
215 if (rsnie->length < WPA_RSN_IE_TAG_FIXED_LEN) {
216 EAPD_ERROR("invalid RSN IE header\n");
217 return -1;
219 if (ltoh16_ua((uint8 *)&rsnie->version) != WPA2_VERSION) {
220 EAPD_ERROR("unsupported RSN IE version\n");
221 return -1;
223 mcast = (wpa_suite_mcast_t *)(rsnie + 1);
224 len = ie_len - WPA_RSN_IE_FIXED_LEN;
225 oui = (uint8*)WPA2_OUI;
226 akm2auth = nas_app_wpa2_akm2auth;
227 break;
229 case DOT11_MNG_WPA_ID: {
230 if (wpaie->length < WPA_IE_TAG_FIXED_LEN ||
231 bcmp(wpaie->oui, WPA_OUI "\x01", WPA_IE_OUITYPE_LEN)) {
232 EAPD_ERROR("invalid WPA IE header\n");
233 return -1;
235 if (ltoh16_ua((uint8 *)&wpaie->version) != WPA_VERSION) {
236 EAPD_ERROR("unsupported WPA IE version\n");
237 return -1;
239 mcast = (wpa_suite_mcast_t *)(wpaie + 1);
240 len = ie_len - WPA_IE_FIXED_LEN;
241 oui = (uint8*)WPA_OUI;
242 akm2auth = nas_app_wpa_akm2auth;
243 break;
245 default:
246 EAPD_ERROR("unsupported IE type\n");
247 return -1;
251 /* init return values - no mcast cipher and no ucast cipher */
252 if (wsec)
253 *wsec = 0;
254 if (mode)
255 *mode = 0;
257 /* Check for multicast suite */
258 if (len >= WPA_SUITE_LEN) {
259 if (!bcmp(mcast->oui, oui, DOT11_OUI_LEN)) {
260 if (wsec)
261 *wsec |= NAS_APP_WPA_CIPHER2WSEC(mcast->type);
263 len -= WPA_SUITE_LEN;
265 /* Check for unicast suite(s) */
266 if (len >= WPA_IE_SUITE_COUNT_LEN) {
267 ucast = (wpa_suite_ucast_t *)&mcast[1];
268 count = ltoh16_ua((uint8 *)&ucast->count);
269 len -= WPA_IE_SUITE_COUNT_LEN;
270 if (count != 1) {
271 EAPD_ERROR("# of unicast cipher suites %d\n", count);
272 return -1;
274 if (!bcmp(ucast->list[0].oui, oui, DOT11_OUI_LEN)) {
275 if (wsec)
276 *wsec |= NAS_APP_WPA_CIPHER2WSEC(ucast->list[0].type);
278 len -= WPA_SUITE_LEN;
280 /* Check for auth key management suite(s) */
281 if (len >= WPA_IE_SUITE_COUNT_LEN) {
282 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[1];
283 count = ltoh16_ua((uint8 *)&mgmt->count);
284 len -= WPA_IE_SUITE_COUNT_LEN;
285 if (count != 1) {
286 EAPD_ERROR("# of AKM suites %d\n", count);
287 return -1;
289 if (!bcmp(mgmt->list[0].oui, oui, DOT11_OUI_LEN)) {
290 m = nas_app_wpa_auth2mode(akm2auth(mgmt->list[0].type));
291 if (mode)
292 *mode = m;
294 len -= WPA_SUITE_LEN;
296 EAPD_INFO("wsec 0x%x mode 0x%x\n", *wsec, *mode);
298 return 0;
301 /* Receive eapol, preauth message from nas module
303 void
304 nas_app_recv_handler(eapd_wksp_t *nwksp, char *wlifname, eapd_cb_t *from, uint8 *pData,
305 int *pLen)
307 eapol_header_t *eapol = (eapol_header_t*) pData;
308 eap_header_t *eap;
309 struct ether_addr *sta_ea;
310 eapd_sta_t *sta;
311 struct eapd_socket *Socket = NULL;
313 if (!nwksp || !wlifname || !from || !pData) {
314 EAPD_ERROR("Wrong argument...\n");
315 return;
318 if (*pLen < EAPOL_HEADER_LEN)
319 return; /* message too short */
321 /* dispatch message to eapol, preauth and brcmevent */
322 switch (ntohs(eapol->eth.ether_type)) {
323 case ETHER_TYPE_802_1X: /* eapol */
324 case ETHER_TYPE_BRCM: /* brcmevent */
325 Socket = from->brcmSocket;
326 break;
327 case ETHER_TYPE_802_1X_PREAUTH: /* preauth */
328 Socket = &from->preauthSocket;
329 break;
332 /* send message data out. */
333 sta_ea = (struct ether_addr*) eapol->eth.ether_dhost;
334 sta = sta_lookup(nwksp, sta_ea, NULL, wlifname, EAPD_SEARCH_ONLY);
336 /* monitor eapol packet */
337 eap = (eap_header_t *) eapol->body;
338 if ((sta) && (eapol->type == EAP_PACKET) &&
339 (eap->code == EAP_FAILURE || eap->code == EAP_SUCCESS)) {
340 sta_remove(nwksp, sta);
343 if (Socket != NULL) {
344 eapd_message_send(nwksp, Socket, pData, *pLen);
346 else {
347 EAPD_ERROR("Socket is not exist!\n");
349 return;
352 void
353 nas_app_set_eventmask(eapd_app_t *app)
355 memset(app->bitvec, 0, sizeof(app->bitvec));
357 setbit(app->bitvec, WLC_E_EAPOL_MSG);
358 setbit(app->bitvec, WLC_E_LINK);
359 setbit(app->bitvec, WLC_E_ASSOC_IND);
360 setbit(app->bitvec, WLC_E_REASSOC_IND);
361 setbit(app->bitvec, WLC_E_DISASSOC_IND);
362 setbit(app->bitvec, WLC_E_DEAUTH_IND);
363 setbit(app->bitvec, WLC_E_MIC_ERROR);
364 #ifdef WLWNM
365 setbit(app->bitvec, WLC_E_WNM_STA_SLEEP);
366 #endif /* WLWNM */
367 return;
371 nas_open_dif_sockets(eapd_wksp_t *nwksp, eapd_cb_t *cb)
373 #ifdef BCMWPA2
374 eapd_preauth_socket_t *preauthSocket;
375 #endif
377 EAPD_INFO("nas: init brcm interface %s \n", cb->ifname);
378 cb->brcmSocket = eapd_add_brcm(nwksp, cb->ifname);
379 if (!cb->brcmSocket)
380 return -1;
381 /* set this brcmSocket have NAS capability */
382 cb->brcmSocket->flag |= EAPD_CAP_NAS;
384 #ifdef BCMWPA2
385 /* open preauth socket */
386 preauthSocket = &cb->preauthSocket;
387 memset(preauthSocket, 0, sizeof(eapd_preauth_socket_t));
388 strcpy(preauthSocket->ifname, cb->ifname);
389 EAPD_INFO("nas: init preauth interface %s \n", cb->ifname);
390 if (eapd_preauth_open(nwksp, preauthSocket) < 0) {
391 EAPD_ERROR("open preauth socket on %s error!!\n", preauthSocket->ifname);
392 preauthSocket->drvSocket = -1;
394 #endif
396 return 0;
399 void
400 nas_close_dif_sockets(eapd_wksp_t *nwksp, eapd_cb_t *cb)
402 #ifdef BCMWPA2
403 eapd_preauth_socket_t *preauthSocket;
404 #endif
406 /* close brcm drvSocket */
407 if (cb->brcmSocket) {
408 EAPD_INFO("close nas brcmSocket %d\n", cb->brcmSocket->drvSocket);
409 eapd_del_brcm(nwksp, cb->brcmSocket);
412 #ifdef BCMWPA2
413 /* close preauth drvSocket */
414 preauthSocket = &cb->preauthSocket;
415 if (preauthSocket->drvSocket >= 0) {
416 EAPD_INFO("close nas preauthSocket %d\n", preauthSocket->drvSocket);
417 eapd_preauth_close(preauthSocket->drvSocket);
418 preauthSocket->drvSocket = -1;
420 #endif
424 nas_app_init(eapd_wksp_t *nwksp)
426 int reuse = 1;
427 eapd_nas_t *nas;
428 eapd_cb_t *cb;
429 eapd_preauth_socket_t *preauthSocket;
430 struct sockaddr_in addr;
433 if (nwksp == NULL)
434 return -1;
436 nas = &nwksp->nas;
437 nas->appSocket = -1;
439 cb = nas->cb;
440 if (cb == NULL) {
441 EAPD_INFO("No any NAS application need to run.\n");
442 return 0;
445 while (cb) {
446 EAPD_INFO("nas: init brcm interface %s \n", cb->ifname);
447 cb->brcmSocket = eapd_add_brcm(nwksp, cb->ifname);
448 if (!cb->brcmSocket)
449 return -1;
450 /* set this brcmSocket have NAS capability */
451 cb->brcmSocket->flag |= EAPD_CAP_NAS;
453 /* open preauth socket */
454 preauthSocket = &cb->preauthSocket;
455 memset(preauthSocket, 0, sizeof(eapd_preauth_socket_t));
456 strcpy(preauthSocket->ifname, cb->ifname);
457 EAPD_INFO("nas: init preauth interface %s \n", cb->ifname);
458 if (eapd_preauth_open(nwksp, preauthSocket) < 0) {
459 EAPD_ERROR("open preauth socket on %s error!!\n", preauthSocket->ifname);
460 preauthSocket->drvSocket = -1;
462 cb = cb->next;
465 /* appSocket for nas */
466 nas->appSocket = socket(AF_INET, SOCK_DGRAM, 0);
467 if (nas->appSocket < 0) {
468 EAPD_ERROR("UDP Open failed.\n");
469 return -1;
471 #if defined(__ECOS)
472 if (setsockopt(nas->appSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&reuse,
473 sizeof(reuse)) < 0) {
474 EAPD_ERROR("UDP setsockopt failed.\n");
475 close(nas->appSocket);
476 nas->appSocket = -1;
477 return -1;
479 #else
480 if (setsockopt(nas->appSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse,
481 sizeof(reuse)) < 0) {
482 EAPD_ERROR("UDP setsockopt failed.\n");
483 close(nas->appSocket);
484 nas->appSocket = -1;
485 return -1;
487 #endif
489 memset(&addr, 0, sizeof(struct sockaddr_in));
490 addr.sin_family = AF_INET;
491 addr.sin_addr.s_addr = INADDR_ANY;
492 addr.sin_port = htons(EAPD_WKSP_NAS_UDP_RPORT);
493 if (bind(nas->appSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
494 EAPD_ERROR("UDP Bind failed, close nas appSocket %d\n", nas->appSocket);
495 close(nas->appSocket);
496 nas->appSocket = -1;
497 return -1;
499 EAPD_INFO("NAS appSocket %d opened\n", nas->appSocket);
501 return 0;
505 nas_app_deinit(eapd_wksp_t *nwksp)
507 eapd_nas_t *nas;
508 eapd_cb_t *cb, *tmp_cb;
509 eapd_preauth_socket_t *preauthSocket;
511 if (nwksp == NULL) {
512 EAPD_ERROR("Wrong argument...\n");
513 return -1;
516 nas = &nwksp->nas;
517 cb = nas->cb;
518 while (cb) {
519 /* close brcm drvSocket */
520 if (cb->brcmSocket) {
521 EAPD_INFO("close nas brcmSocket %d\n", cb->brcmSocket->drvSocket);
522 eapd_del_brcm(nwksp, cb->brcmSocket);
525 /* close preauth drvSocket */
526 preauthSocket = &cb->preauthSocket;
527 if (preauthSocket->drvSocket >= 0) {
528 EAPD_INFO("close nas preauthSocket %d\n", preauthSocket->drvSocket);
529 eapd_preauth_close(preauthSocket->drvSocket);
530 preauthSocket->drvSocket = -1;
532 tmp_cb = cb;
533 cb = cb->next;
534 free(tmp_cb);
537 /* close appSocke */
538 if (nas->appSocket >= 0) {
539 EAPD_INFO("close nas appSocket %d\n", nas->appSocket);
540 close(nas->appSocket);
541 nas->appSocket = -1;
544 return 0;
547 /* nas_sendup will send eapol, brcm and preauth packet */
549 nas_app_sendup(eapd_wksp_t *nwksp, uint8 *pData, int pLen, char *from)
551 eapd_nas_t *nas;
553 if (nwksp == NULL) {
554 EAPD_ERROR("Wrong argument...\n");
555 return -1;
558 nas = &nwksp->nas;
559 if (nas->appSocket >= 0) {
560 /* send to nas */
561 int sentBytes = 0;
562 struct sockaddr_in to;
564 to.sin_addr.s_addr = inet_addr(EAPD_WKSP_UDP_ADDR);
565 to.sin_family = AF_INET;
566 to.sin_port = htons(EAPD_WKSP_NAS_UDP_SPORT);
568 sentBytes = sendto(nas->appSocket, (char *)pData, pLen, 0,
569 (struct sockaddr *)&to, sizeof(struct sockaddr_in));
571 if (sentBytes != pLen) {
572 EAPD_ERROR("UDP send failed; sentBytes = %d\n", sentBytes);
574 else {
575 /* EAPD_ERROR("Send %d bytes to nas\n", sentBytes); */
578 else {
579 EAPD_ERROR("nas appSocket not created\n");
581 return 0;
584 #if EAPD_WKSP_AUTO_CONFIG
586 nas_app_enabled(char *name)
588 char value[128], comb[32], akm[16], prefix[8];
589 char akms[128], auth[32], wep[32], crypto[32], os_name[IFNAMSIZ];
590 char *akmnext;
591 uint wsec, nasm;
592 int unit;
594 memset(os_name, 0, sizeof(os_name));
596 if (nvifname_to_osifname(name, os_name, sizeof(os_name)))
597 return 0;
598 if (wl_probe(os_name) ||
599 wl_ioctl(os_name, WLC_GET_INSTANCE, &unit, sizeof(unit)))
600 return 0;
601 if (osifname_to_nvifname(name, prefix, sizeof(prefix)))
602 return 0;
604 strcat(prefix, "_");
605 /* ignore if disabled */
606 eapd_safe_get_conf(value, sizeof(value), strcat_r(prefix, "radio", comb));
607 if (atoi(value) == 0) {
608 EAPD_INFO("NAS:ignored interface %s. radio disabled\n", os_name);
609 return 0;
611 /* ignore shared */
612 eapd_safe_get_conf(value, sizeof(value), strcat_r(prefix, "auth", comb));
613 if (atoi(value) == 1) {
614 EAPD_INFO("NAS: ignored interface %s. Shared 802.11 auth\n", os_name);
615 return 0;
617 /* ignore if BSS is disabled */
618 eapd_safe_get_conf(value, sizeof(value), strcat_r(prefix, "bss_enabled", comb));
619 if (atoi(value) == 0) {
620 EAPD_INFO("NAS: ignored interface %s, %s is disabled \n", os_name, comb);
621 return 0;
623 /* nas mode */
624 eapd_safe_get_conf(auth, sizeof(auth), strcat_r(prefix, "auth_mode", comb));
625 nasm = !strcmp(auth, "radius") ? RADIUS : 0;
626 eapd_safe_get_conf(akms, sizeof(akms), strcat_r(prefix, "akm", comb));
627 foreach(akm, akms, akmnext) {
628 if (!strcmp(akm, "wpa"))
629 nasm |= WPA;
630 if (!strcmp(akm, "psk"))
631 nasm |= WPA_PSK;
632 if (!strcmp(akm, "wpa2"))
633 nasm |= WPA2;
634 if (!strcmp(akm, "psk2"))
635 nasm |= WPA2_PSK;
637 if (!nasm) {
638 EAPD_INFO("NAS:ignored interface %s. Invalid NAS mode\n", os_name);
639 return 0;
641 /* wsec */
642 eapd_safe_get_conf(wep, sizeof(wep), strcat_r(prefix, "wep", comb));
643 wsec = !strcmp(wep, "enabled") ? WEP_ENABLED : 0;
644 if (CHECK_NAS(nasm)) {
645 eapd_safe_get_conf(crypto, sizeof(crypto), strcat_r(prefix, "crypto", comb));
646 if (!strcmp(crypto, "tkip"))
647 wsec |= TKIP_ENABLED;
648 else if (!strcmp(crypto, "aes"))
649 wsec |= AES_ENABLED;
650 else if (!strcmp(crypto, "tkip+aes"))
651 wsec |= TKIP_ENABLED|AES_ENABLED;
653 if (!wsec) {
654 EAPD_INFO("%s: Ignored interface. Invalid WSEC\n", os_name);
655 return 0;
658 /* if come to here return enabled */
659 return 1;
661 #endif /* EAPD_WKSP_AUTO_CONFIG */
664 nas_app_handle_event(eapd_wksp_t *nwksp, uint8 *pData, int Len, char *from)
666 int type;
667 eapd_nas_t *nas;
668 eapd_cb_t *cb;
669 bcm_event_t *dpkt = (bcm_event_t *) pData;
670 wl_event_msg_t *event = &(dpkt->event);
671 uint8 *addr = (uint8 *)&(event->addr);
672 uint8 *data = (uint8 *)(event + 1);
673 uint16 len = ntoh32(event->datalen);
674 uint32 mode, wsec;
675 eapd_sta_t *sta;
678 type = ntohl(event->event_type);
680 nas = &nwksp->nas;
681 cb = nas->cb;
682 while (cb) {
683 if (isset(nas->bitvec, type) && !strcmp(cb->ifname, from)) {
684 /* We need to know is client in PSK mode */
685 if (type == WLC_E_ASSOC_IND || type == WLC_E_REASSOC_IND ||
686 type == WLC_E_DISASSOC_IND || type == WLC_E_DEAUTH_IND) {
687 sta = sta_lookup(nwksp, (struct ether_addr *)addr,
688 (struct ether_addr *) dpkt->eth.ether_dhost,
689 event->ifname, EAPD_SEARCH_ENTER);
690 if (!sta) {
691 EAPD_ERROR("no STA struct available\n");
692 return -1;
695 if (type == WLC_E_DISASSOC_IND || type == WLC_E_DEAUTH_IND) {
696 /* Reset the sta mode */
697 sta->mode = EAPD_STA_MODE_UNKNOW;
699 else if (nas_app_find_wpsie(data, (uint)len)) {
700 sta->mode = EAPD_STA_MODE_UNKNOW;
702 /* Don't send those Indication to NAS, otherwise NAS may
703 * initial a 4-ways handshake with Ralink STA
705 break;
707 else if (!nas_app_parse_ie(data, len, &wsec, &mode) &&
708 CHECK_PSK(mode)) {
709 /* set cient in PSK mode */
710 sta->mode = EAPD_STA_MODE_NAS_PSK;
714 /* prepend ifname, we reserved IFNAMSIZ length already */
715 pData -= IFNAMSIZ;
716 Len += IFNAMSIZ;
717 memcpy(pData, event->ifname, IFNAMSIZ);
719 EAPD_INFO("%s: send event %d to nas %s\n",
720 event->ifname, type, cb->ifname);
722 /* send to nas use cb->ifname */
723 nas_app_sendup(nwksp, pData, Len, cb->ifname);
724 break;
726 cb = cb->next;
729 return 0;