2 * NAS WorKSPace - NAS application common code
4 * Copyright (C) 2010, Broadcom Corporation
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: nas_wksp.c 245219 2011-03-09 02:06:06Z kenlo $
15 #include <bcmcrypto/passhash.h>
16 #include <bcmcrypto/sha1.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
39 #include <proto/eap.h>
43 #include <nas_radius.h>
44 #include <nas_wksp_radius.h>
48 #include <security_ipc.h>
52 #ifndef NAS_WKSP_DEBUG
53 #define NAS_WKSP_DEBUG 0
55 int debug_nwksp
= NAS_WKSP_DEBUG
;
56 #endif /* #if BCMDBG */
59 * Locally used globals
61 static char NAS_OPT_LIST
[] = "B:g:h:i:I:k:r:K:l:m:N:p:s:t:v:w:d:ADS";
62 static int nas_wksp_inited
= 0;
65 * Build command line in argc/argv form for NAS configuration.
66 * This is a template provided for convenience. Program who
67 * needs the functionality can make a copy of this template
68 * into its own code space.
75 * Parse command line and populate nas_wksp_t structure which consists of
76 * nas_t wpa_t and all the auxiliary stuff that needed for all NAS instances.
79 /* interface to option facilities */
80 extern int getopt(int argc
, char **argv
, char *ostr
);
81 extern void initopt(void);
85 /* print NAS command line usage */
87 nas_wksp_display_usage(void)
90 printf("\nUsage: nas [options]\n\n");
91 printf("\t-i <interface> Wireless interface name\n");
92 #if defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL)
93 printf("\t-A Authenticator\n");
94 printf("\t-S Supplicant\n");
95 #endif /* #if defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL) */
96 #ifdef NAS_WKSP_BUILD_NAS_AUTH
97 printf("\t-g <interval> WPA GTK rotation interval (ms)\n");
98 printf("\t-h <address> RADIUS server IP address\n");
99 printf("\t-p <port> RADIUS server UDP port\n");
100 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */
101 printf("\t-k <secret> WPA pre-shared key\n");
102 printf("\t-r <secret> RADIUS server secret\n");
103 printf("\t-m <authentication> Authentication protocol - %d:WPA | %d:WPA-PSK | %d:802.1x\n",
104 WPA
, WPA_PSK
, RADIUS
);
106 printf("\t %d:WPA2 | %d:WPA2-PSK\n",
109 printf("\t-s <SSID> Service Set Identity\n");
110 printf("\t-w <encryption> Crypto algorithm - %d:WEP | %d:TKIP | %d:AES\n",
111 WEP_ENABLED
, TKIP_ENABLED
, AES_ENABLED
);
112 printf("\t-I <index> WEP key index - 2 | 3\n");
113 printf("\t-K <key> WEP key\n");
114 printf("\t-t <duration> Radius Session timeout/PMK Caching duration (ms)\n");
115 printf("\t-N <NasID> NAS id\n");
117 printf("\t-v <debug> Verbose mode - 0:off | 1:console\n");
118 #endif /* #ifdef BCMDBG */
119 printf("\nThe -i <interface> option must be present before any other per interface options "
120 "to specify the wireless interface\n");
122 #endif /* #ifdef BCMDBG */
126 * Parse command line and populate nas_wksp_t structure.
127 * It takes short form options only as described in function usage().
128 * Field 'nwcbs' in 'nwksp' indicates the number of elements populated
132 nas_wksp_parse_cmd(int argc
, char *argv
[], nas_wksp_t
*nwksp
)
134 nas_wpa_cb_t
*nwcb
= NULL
; /* pointer to current nas_wpa_cb_t */
135 int i
= -1; /* index of current interface */
143 /* parse command line parameters */
144 while ((opt
= getopt(argc
, argv
, NAS_OPT_LIST
)) != EOF
) {
147 if (i
+ 1 >= NAS_WKSP_MAX_NUM_INTERFACES
) {
148 NASDBG("too many interfaces specified\n");
158 NASDBG("no I/F specified\n");
164 /* save parameters in user-provided structure */
166 /* i/f dependant parameters */
168 /* check if i/f exists and retrieve the i/f index */
169 if (wl_probe(optarg
) ||
170 wl_ioctl(optarg
, WLC_GET_INSTANCE
, &unit
, sizeof(unit
))) {
171 NASDBG("%s: not a wireless interface\n", optarg
);
174 /* ignore errorous interface and reuse nas_wpa_cb_t */
175 if (i
>= 0 && (nwcb
->flags
& NAS_WPA_CB_FLAG_ERROR
))
176 NASMSG("%s: error parsing options, ignored\n", nwcb
->nas
.interface
);
177 /* advance nas_wpa_cb_t index & alloc new nas_wpa_cb_t */
178 else if ((++ i
) < NAS_WKSP_MAX_NUM_INTERFACES
) {
179 nwcb
= (nas_wpa_cb_t
*)malloc(sizeof(nas_wpa_cb_t
));
182 /* init nas_wpa_cb_t */
183 memset(nwcb
, 0, sizeof(nwcb
[0]));
186 #if !defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL)
187 nwcb
->flags
|= NAS_WPA_CB_FLAG_SUPPL
;
188 nwcb
->nas
.flags
|= NAS_FLAG_SUPPLICANT
;
189 #endif /* #if !defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL) */
190 #if defined(NAS_WKSP_BUILD_NAS_AUTH) && !defined(NAS_WKSP_BUILD_NAS_SUPPL)
191 nwcb
->flags
|= NAS_WPA_CB_FLAG_AUTH
;
192 nwcb
->nas
.flags
|= NAS_FLAG_AUTHENTICATOR
;
193 #endif /* #if defined(NAS_WKSP_BUILD_NAS_AUTH) && !defined(NAS_WKSP_BUILD_NAS_SUPPL) */
194 nwcb
->nas
.wan
= NAS_WKSP_UNK_FILE_DESC
;
195 nwcb
->nas
.server
.sin_port
= htons(RADIUS_PORT
);
196 nwcb
->nas
.wsec
= TKIP_ENABLED
|AES_ENABLED
;
197 nwcb
->nas
.wpa
= &nwcb
->wpa
;
198 nwcb
->nas
.appl
= nwcb
;
203 nwcb
->nas
.disable_preauth
= 0;
205 nwcb
->nas
.ssn_to
= 36000; /* 10hrs */
206 nwcb
->wpa
.nas
= &nwcb
->nas
;
207 strncpy(nwcb
->nas
.interface
, optarg
, IFNAMSIZ
);
208 NASDBG("nas[%d].interface %s\n", i
, optarg
);
209 /* Get interface address */
210 if (wl_hwaddr(nwcb
->nas
.interface
, nwcb
->nas
.ea
.octet
)) {
211 NASDBG("%s: failed to get hwaddr\n", nwcb
->nas
.interface
);
212 nwcb
->flags
|= NAS_WPA_CB_FLAG_ERROR
;
215 NASDBG("nas[%d].hwaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
217 nwcb
->nas
.ea
.octet
[0], nwcb
->nas
.ea
.octet
[1],
218 nwcb
->nas
.ea
.octet
[2], nwcb
->nas
.ea
.octet
[3],
219 nwcb
->nas
.ea
.octet
[4], nwcb
->nas
.ea
.octet
[5]);
220 nwksp
->nwcb
[i
] = nwcb
;
223 /* Save key parameter. What contraints to apply
224 * are unknown until mode is also known.
226 strncpy((char *)nwcb
->psk
, optarg
, NAS_WKSP_MAX_USER_KEY_LEN
);
227 nwcb
->psk
[NAS_WKSP_MAX_USER_KEY_LEN
] = 0;
228 NASDBG("nas[%d].psk %s\n", i
, optarg
);
231 /* Save key parameter. What contraints to apply
232 * are unknown until mode is also known.
234 strncpy((char *)nwcb
->secret
, optarg
, NAS_WKSP_MAX_USER_KEY_LEN
);
235 nwcb
->secret
[NAS_WKSP_MAX_USER_KEY_LEN
] = 0;
236 NASDBG("nas[%d].secret %s\n", i
, optarg
);
239 /* update auth mode */
240 nwcb
->nas
.mode
= (int)strtoul(optarg
, NULL
, 0);
241 NASDBG("nas[%d].mode %s\n", i
, optarg
);
243 #if defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL)
245 /* nas as authenticator */
246 nwcb
->flags
|= NAS_WPA_CB_FLAG_AUTH
;
247 nwcb
->nas
.flags
|= NAS_FLAG_AUTHENTICATOR
;
248 NASDBG("nas[%d].role authenticator\n", i
);
251 /* nas as supplicant */
252 nwcb
->flags
|= NAS_WPA_CB_FLAG_SUPPL
;
253 nwcb
->nas
.flags
|= NAS_FLAG_SUPPLICANT
;
254 NASDBG("nas[%d].role supplicant\n", i
);
256 #endif /* #if defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL) */
257 #ifdef NAS_WKSP_BUILD_NAS_AUTH
259 /* update group key rekey interval */
260 nwcb
->wpa
.gtk_rekey_secs
= (int)strtoul(optarg
, NULL
, 0);
261 NASDBG("nas[%d].gtk.rekey %s\n", i
, optarg
);
265 /* update radius server address */
266 nwcb
->nas
.server
.sin_family
= AF_INET
;
267 nwcb
->nas
.server
.sin_addr
.s_addr
= inet_addr(optarg
);
268 NASDBG("nas[%d].server.address %s\n", i
, optarg
);
269 #endif /* #ifdef NAS_RADIUS */
272 /* update radius server port number */
273 nwcb
->nas
.server
.sin_port
= htons((int)strtoul(optarg
, NULL
, 0));
274 NASDBG("nas[%d].server.port %s\n", i
, optarg
);
276 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */
278 /* update ssid info */
279 strncpy(nwcb
->nas
.ssid
, optarg
, DOT11_MAX_SSID_LEN
);
280 NASDBG("nas[%d].ssid %s\n", i
, optarg
);
283 /* update wsec value */
284 nwcb
->nas
.wsec
= (int)strtoul(optarg
, NULL
, 0);
285 NASDBG("nas[%d].wsec %s\n", i
, optarg
);
288 /* nas in WDS mode */
289 nwcb
->flags
|= NAS_WPA_CB_FLAG_WDS
;
290 nwcb
->nas
.flags
|= NAS_FLAG_WDS
;
291 NASDBG("nas[%d].flags %08x\n", i
, nwcb
->nas
.flags
);
293 if (wl_ioctl(nwcb
->nas
.interface
, WLC_WDS_GET_REMOTE_HWADDR
,
294 nwcb
->nas
.remote
, sizeof(nwcb
->nas
.remote
))) {
295 NASDBG("%s: failed to get remote hwaddr\n", nwcb
->nas
.interface
);
296 nwcb
->flags
|= NAS_WPA_CB_FLAG_ERROR
;
299 NASDBG("nas[%d].remote %02x:%02x:%02x:%02x:%02x:%02x\n",
301 nwcb
->nas
.remote
[0], nwcb
->nas
.remote
[1],
302 nwcb
->nas
.remote
[2], nwcb
->nas
.remote
[3],
303 nwcb
->nas
.remote
[4], nwcb
->nas
.remote
[5]);
307 /* verbose - 0:no | others:yes */
310 debug_nwksp
= (int)strtoul(optarg
, NULL
, 0);
314 nwcb
->nas
.debug
= (bool)strtoul(optarg
, NULL
, 0);
320 nwcb
->index
= (int)strtoul(optarg
, NULL
, 0);
321 NASDBG("nas[%d].wep.index %s\n", i
, optarg
);
326 strncpy((char *)nwcb
->wep
, optarg
, NAS_WKSP_MAX_USER_KEY_LEN
);
327 nwcb
->wep
[NAS_WKSP_MAX_USER_KEY_LEN
] = 0;
328 NASDBG("nas[%d].wep %s\n", i
, optarg
);
331 nwcb
->nas
.ssn_to
= (int)strtoul(optarg
, NULL
, 0);
332 NASDBG("nas[%d].ssn.timeout %s\n", i
, optarg
);
336 nwcb
->nas
.disable_preauth
= strtoul(optarg
, NULL
, 0) == 0;
337 NASDBG("nas[%d].disable_preauth %d\n", i
, nwcb
->nas
.disable_preauth
);
341 strncpy(nwcb
->nas
.nas_id
, optarg
, MAX_NAS_ID_LEN
);
342 NASDBG("nas[%d].nas_id %s\n", i
, optarg
);
345 /* display wrong option and quit */
346 NASDBG("unknown option -%c, ignored\n", opt
);
351 /* return to caller # of i/f */
352 nwksp
->nwcbs
= i
+ 1;
357 /* listen to sockets and call handlers to process packets */
359 nas_wksp_main_loop(nas_wksp_t
*nwksp
)
364 ret
= nas_wksp_init(nwksp
);
366 /* nas wksp initialization finished */
369 NASMSG("Unable to initialize NAS. Quitting...\n");
370 nas_wksp_free_workspace(nwksp
);
374 #if !defined(DEBUG) && !defined(__ECOS)
376 if (daemon(1, 1) == -1) {
377 /* clean up nas workspace */
378 nas_wksp_cleanup(nwksp
);
379 /* free workspace context */
380 nas_wksp_free_workspace(nwksp
);
381 perror("nas_wksp_main_loop: daemon\n");
387 /* check user command for shutdown */
388 if (nwksp
->flags
& NAS_WKSP_FLAG_SHUTDOWN
) {
389 /* clean up nas workspace */
390 nas_wksp_cleanup(nwksp
);
392 /* free workspace context */
393 nas_wksp_free_workspace(nwksp
);
395 NASDBG("NAS shutdown...\n");
399 /* do packets dispatch */
400 nas_wksp_dispatch_packet(nwksp
);
404 /* listen to sockets and call handlers to process packets */
406 nas_wksp_dispatch_packet(nas_wksp_t
*nwksp
)
409 int i
, len
, width
, status
, bytes
;
410 nas_wpa_cb_t
*nwcb
= NULL
;
412 bcm_event_t
*pvt_data
;
415 /* init file descriptor set */
416 FD_ZERO(&nwksp
->fdset
);
419 /* build file descriptor set now to save time later */
420 if (nwksp
->eapd
!= NAS_WKSP_UNK_FILE_DESC
) {
421 FD_SET(nwksp
->eapd
, &nwksp
->fdset
);
422 if (nwksp
->eapd
> nwksp
->fdmax
)
423 nwksp
->fdmax
= nwksp
->eapd
;
425 for (i
= 0; i
< nwksp
->nwcbs
; i
++) {
426 nwcb
= nwksp
->nwcb
[i
];
428 /* ignore the interface if there was any error */
429 if (nwcb
->flags
& NAS_WPA_CB_FLAG_ERROR
) {
430 /* NASMSG("%s: ignore i/f due to error(s)\n", nwcb->nas.interface); */
433 #ifdef NAS_WKSP_BUILD_NAS_AUTH
434 if (nwcb
->nas
.wan
!= NAS_WKSP_UNK_FILE_DESC
) {
435 FD_SET(nwcb
->nas
.wan
, &nwksp
->fdset
);
436 if (nwcb
->nas
.wan
> nwksp
->fdmax
)
437 nwksp
->fdmax
= nwcb
->nas
.wan
;
439 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */
441 /* check if there is any sockets in the fd set */
442 if (nwksp
->fdmax
== -1) {
443 /* do shutdown procedure */
444 nwksp
->flags
= NAS_WKSP_FLAG_SHUTDOWN
;
445 NASMSG("Threr is no any sockets in the fd set, shutdown...\n");
450 len
= sizeof(nwksp
->packet
);
451 width
= nwksp
->fdmax
+ 1;
452 fdset
= nwksp
->fdset
;
453 /* set timeout value */
457 /* enable timer handling */
458 bcm_timer_module_enable(nwksp
->timer
, 1);
460 /* listen to data availible on all sockets */
461 status
= select(width
, &fdset
, NULL
, NULL
, &tv
);
463 /* disable timer handling */
464 bcm_timer_module_enable(nwksp
->timer
, 0);
468 /* the data is driver indication message or encapsulated 802.1x frame */
469 if (nwksp
->eapd
!= NAS_WKSP_UNK_FILE_DESC
&& FD_ISSET(nwksp
->eapd
, &fdset
)) {
470 char *ifname
= (char *)pkt
;
471 eapol_header_t
*eapol
= (eapol_header_t
*)(ifname
+ IFNAMSIZ
);
473 if ((bytes
= recv(nwksp
->eapd
, pkt
, len
, 0)) > 0) {
474 /* strip prepend ifname */
477 /* dispatch message to eapol, preauth, brcmevent */
478 switch (ntohs(eapol
->eth
.ether_type
)) {
479 case ETHER_TYPE_802_1X
: /* eapol */
480 NASDBG("recv eapol packet from socket %d\n", nwksp
->eapd
);
482 nwcb
= nas_wksp_find_nwcb(nwksp
, eapol
->eth
.ether_dhost
,
483 ifname
, NAS_WKSP_NWCB_AUTO
);
487 /* dispatch eapol for auth or suppl */
488 nas_eapol_message_dispatch(nwcb
, (void *)eapol
, bytes
);
491 case ETHER_TYPE_802_1X_PREAUTH
: /* preauth */
492 NASDBG("recv preauth packet from socket %d\n",
495 nwcb
= nas_wksp_find_nwcb(nwksp
, eapol
->eth
.ether_dhost
,
496 NULL
, NAS_WKSP_NWCB_AUTO
);
500 preauth_dispatch(&nwcb
->nas
, eapol
);
503 case ETHER_TYPE_BRCM
: /* brcmevent */
504 NASDBG("recv brcmevent packet from eapd Socket"
505 "%d\n", nwksp
->eapd
);
507 /* make sure to interpret only messages destined to NAS */
508 if (nas_validate_wlpvt_message(bytes
, (uint8
*)eapol
))
511 pvt_data
= (bcm_event_t
*)(ifname
+ IFNAMSIZ
);
512 nwcb
= nas_wksp_find_nwcb(nwksp
,
513 pvt_data
->eth
.ether_dhost
,
514 pvt_data
->event
.ifname
,
520 /* do not process eapol message in brcmevent */
521 nas_handle_wlpvt_messages(nwcb
, (void *)pvt_data
, bytes
);
523 } /* switch(ntohs(eapol->eth.ether_type)) */
524 } /* if ((bytes = recv(nwksp->eapd, pkt, len, 0)) > 0) */
525 } /* FD_ISSET(nwksp->eapd, &fdset) */
527 #ifdef NAS_WKSP_BUILD_NAS_AUTH
528 /* process radius data from individual interfaces */
529 for (i
= 0; i
< nwksp
->nwcbs
; i
++) {
530 nwcb
= nwksp
->nwcb
[i
];
531 /* the data is radius message */
532 if ((nwcb
->nas
.wan
!= NAS_WKSP_UNK_FILE_DESC
) &&
533 FD_ISSET(nwcb
->nas
.wan
, &fdset
)) {
534 if (recv(nwcb
->nas
.wan
, pkt
, len
, 0) <= 0) {
535 NASMSG("%s: recv radius error %d from socket %d\n",
536 nwcb
->nas
.interface
, errno
, nwcb
->nas
.wan
);
537 /* Reopen the socket to the radius server if possible */
538 if (NAS_RADIUS_OPEN(nwksp
, nwcb
) != 0) {
539 NASMSG("%s: open radius connection failed\n",
540 nwcb
->nas
.interface
);
542 continue; /* Skip this attempt */
545 NASDBG("%s: recv radius packet from socket %d\n",
546 nwcb
->nas
.interface
, nwcb
->nas
.wan
);
547 RADIUS_DISPATCH(&nwcb
->nas
, (void *)pkt
);
550 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */
557 /* establish connection to EAPD to
558 * receive wpa, eapol and preauth.
561 nas_wksp_open_eapd(nas_wksp_t
*nwksp
)
564 struct sockaddr_in sockaddr
;
566 /* open loopback socket to communicate with EAPD */
567 memset(&sockaddr
, 0, sizeof(sockaddr
));
568 sockaddr
.sin_family
= AF_INET
;
569 sockaddr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
570 sockaddr
.sin_port
= htons(EAPD_WKSP_NAS_UDP_SPORT
);
571 if ((nwksp
->eapd
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0) {
572 NASDBG("eapd: Unable to create loopback socket\n");
576 if (setsockopt(nwksp
->eapd
, SOL_SOCKET
, SO_REUSEPORT
, (char*)&reuse
, sizeof(reuse
)) < 0) {
577 NASDBG("eapd: Unable to setsockopt to loopback socket %d.\n", nwksp
->eapd
);
581 if (setsockopt(nwksp
->eapd
, SOL_SOCKET
, SO_REUSEADDR
, (char*)&reuse
, sizeof(reuse
)) < 0) {
582 NASDBG("eapd: Unable to setsockopt to loopback socket %d.\n", nwksp
->eapd
);
586 if (bind(nwksp
->eapd
, (struct sockaddr
*)&sockaddr
, sizeof(sockaddr
)) < 0) {
587 NASDBG("eapd: Unable to bind to loopback socket %d\n", nwksp
->eapd
);
590 NASDBG("eapd: opened loopback socket %d\n", nwksp
->eapd
);
598 nwksp
->eapd
= NAS_WKSP_UNK_FILE_DESC
;
599 NASDBG("eapd: failed to open loopback socket\n");
604 nas_wksp_close_eapd(nas_wksp_t
*nwksp
)
606 /* clsoe eapd socket */
607 if (nwksp
->eapd
!= NAS_WKSP_UNK_FILE_DESC
) {
608 NASDBG("eapd: close loopback socket %d\n", nwksp
->eapd
);
610 nwksp
->eapd
= NAS_WKSP_UNK_FILE_DESC
;
615 /* transmit eapol message thru the socket */
617 nas_wksp_eapd_send_packet(nas_t
*nas
, struct iovec
*frags
, int nfrags
)
619 nas_wpa_cb_t
*nwcb
= (nas_wpa_cb_t
*)nas
->appl
;
620 nas_wksp_t
*nwksp
= nwcb
->nwksp
;
621 struct ether_header
*eth
;
623 struct sockaddr_in to
;
627 if (!nfrags
|| !nfrags
)
630 if (frags
->iov_len
< sizeof(struct ether_header
))
633 /* allocate iov buffer */
634 iov
= malloc(sizeof(struct iovec
) * (nfrags
+ 1));
638 eth
= (struct ether_header
*) frags
->iov_base
;
640 to
.sin_addr
.s_addr
= inet_addr(EAPD_WKSP_UDP_ADDR
);
641 to
.sin_family
= AF_INET
;
642 to
.sin_port
= htons(EAPD_WKSP_NAS_UDP_RPORT
);
644 /* Save incoming interface name */
645 iov
[0].iov_base
= (void *)&nas
->interface
;
646 iov
[0].iov_len
= IFNAMSIZ
;
648 for (i
= 1; i
<= nfrags
; i
++) {
649 iov
[i
].iov_base
= frags
[i
-1].iov_base
;
650 iov
[i
].iov_len
= frags
[i
-1].iov_len
;
653 memset(&mh
, 0, sizeof(mh
));
654 mh
.msg_name
= (void *)&to
;
655 mh
.msg_namelen
= sizeof(to
);
657 mh
.msg_iovlen
= nfrags
+ 1;
659 if (sendmsg(nwksp
->eapd
, &mh
, 0) < 0)
666 /* transmit eapol message thru the socket */
668 nas_eapol_send_packet(nas_t
*nas
, struct iovec
*frags
, int nfrags
)
670 return (nas_wksp_eapd_send_packet(nas
, frags
, nfrags
));
674 /* transmit preauth message thru the socket */
675 int nas_preauth_send_packet(nas_t
*nas
, struct iovec
*frags
, int nfrags
)
677 return (nas_wksp_eapd_send_packet(nas
, frags
, nfrags
));
681 /* allocate NAS workspace for <nifs> interfaces/instances */
683 nas_wksp_alloc_workspace(void)
685 nas_wksp_t
*nwksp
= (nas_wksp_t
*)malloc(sizeof(nas_wksp_t
));
689 memset(nwksp
, 0, sizeof(nas_wksp_t
));
692 NASDBG("allocated NAS workspace %d bytes\n", sizeof(nas_wksp_t
));
696 /* free memory taken by NAS workspace */
698 nas_wksp_free_workspace(nas_wksp_t
*nwksp
)
701 NASDBG("free NAS workspace %08x\n", (int)nwksp
);
702 for (i
= 0; i
< nwksp
->nwcbs
; i
++)
704 free(nwksp
->nwcb
[i
]);
708 #define NAS_WKSP_MODULE_TIMER 0
710 * Init the timer event queue (used only by WPA stuff,
711 * up to one per supplicant plus:
712 * the group rekey timer
713 * MIC failure throttling timer
714 * 4-way handshake initiator for wds
717 #define NAS_WKSP_MAX_NUM_TIMER (MAX_SUPPLICANTS + 4)
719 /* init one nas instance */
721 nas_init_nas(nas_wksp_t
*nwksp
, nas_wpa_cb_t
*nwcb
)
726 #if !NAS_WKSP_MODULE_TIMER
727 nwcb
->nas
.timer
= nwksp
->timer
;
729 bcm_timer_module_init(NAS_WKSP_MAX_NUM_TIMER
, &nwcb
->nas
.timer
);
730 #endif /* #if NAS_WKSP_MODULE_TIMER */
732 /* check if mode is supported */
733 if (!(CHECK_AUTH(nwcb
->nas
.mode
))) {
734 NASDBG("%s: auth mode %d is not supported\n", nwcb
->nas
.interface
, nwcb
->nas
.mode
);
735 nwcb
->flags
|= NAS_WPA_CB_FLAG_ERROR
;
739 /* check if wsec is supported */
740 if (!nwcb
->nas
.wsec
||
741 (nwcb
->nas
.wsec
& (AES_ENABLED
| TKIP_ENABLED
| WEP_ENABLED
)) != nwcb
->nas
.wsec
) {
742 NASDBG("%s: wsec 0x%x is not supported\n", nwcb
->nas
.interface
, nwcb
->nas
.wsec
);
743 nwcb
->flags
|= NAS_WPA_CB_FLAG_ERROR
;
747 /* validate gtk rotation and gtk index */
748 if (nwcb
->flags
& NAS_WPA_CB_FLAG_AUTH
) {
749 if ((CHECK_NAS(nwcb
->nas
.mode
)) &&
750 WSEC_WEP_ENABLED(nwcb
->nas
.wsec
)) {
751 if (nwcb
->wpa
.gtk_rekey_secs
) {
752 NASDBG("%s: GTK rotation is not allowed when WEP is enabled,"
754 nwcb
->nas
.interface
);
755 nwcb
->wpa
.gtk_rekey_secs
= 0;
757 if (nwcb
->index
!= (GTK_INDEX_1
+ 1) && nwcb
->index
!= (GTK_INDEX_2
+ 1)) {
758 NASDBG("%s: GTK index %d is invalid when WEP is enabled, using %d"
760 nwcb
->nas
.interface
, nwcb
->index
, GTK_INDEX_1
+ 1);
761 nwcb
->index
= GTK_INDEX_1
+ 1;
764 else if (nwcb
->index
&&
765 nwcb
->index
!= (GTK_INDEX_1
+ 1) && nwcb
->index
!= (GTK_INDEX_2
+ 1)) {
766 NASDBG("%s: GTK index %d is invalid when used with mode %d, using %d"
768 nwcb
->nas
.interface
, nwcb
->index
, nwcb
->nas
.mode
, GTK_INDEX_1
+ 1);
769 nwcb
->index
= GTK_INDEX_1
+ 1;
773 /* nas type is Wireless IEEE 802.11 */
774 nwcb
->nas
.type
= NAS_PORT_TYPE_WIRELESS_IEEE80211
;
776 /* default key index and size */
777 nwcb
->wpa
.gtk_index
= GTK_INDEX_1
;
779 nwcb
->wpa
.igtk
.id
= IGTK_INDEX_1
;
782 if (nwcb
->nas
.mode
& RADIUS
)
783 nwcb
->wpa
.gtk_len
= WEP128_KEY_SIZE
;
785 /* apply key constraints according to the mode */
786 /* PSK pre-shared key */
787 if (CHECK_PSK(nwcb
->nas
.mode
)) {
790 len
= strlen((char *)key
);
791 nwcb
->nas
.key
.data
= data
= nwcb
->wpa
.pmk
;
792 /* numeric key must be 256-bit. */
793 if (len
== NAS_WKSP_PSK_LEN
)
795 /* allow leading hex radix for a proper size number */
796 else if ((len
== NAS_WKSP_PSK_LEN
+ 2) &&
797 (!strncmp((char *)key
, "0x", 2) || !strncmp((char *)key
, "0X", 2)))
805 if (!isxdigit((int)hex
[0]) ||
806 !isxdigit((int)hex
[1])) {
807 NASDBG("%s: numeric PSK %s not 256-bit hex number\n",
808 nwcb
->nas
.interface
, key
);
809 nwcb
->flags
|= NAS_WPA_CB_FLAG_ERROR
;
812 *data
++ = (uint8
)strtoul(hex
, NULL
, 16);
813 } while (++j
< NAS_WKSP_PSK_LEN
/2);
814 nwcb
->nas
.key
.length
= NAS_WKSP_PSK_LEN
/2;
816 unsigned char output
[2*SHA1HashSize
];
817 if ((len
< NAS_WKSP_PASSPHRASE_MIN
) ||
818 (len
> NAS_WKSP_PASSPHRASE_MAX
)) {
819 NASDBG("%s: %s length illegal\n", nwcb
->nas
.interface
, key
);
820 nwcb
->flags
|= NAS_WPA_CB_FLAG_ERROR
;
824 /* perform password to hash conversion */
825 if (passhash((char *)key
, len
, (uchar
*)nwcb
->nas
.ssid
,
826 strlen(nwcb
->nas
.ssid
), output
)) {
827 NASDBG("%s: PSK password hash failed\n", nwcb
->nas
.interface
);
828 nwcb
->flags
|= NAS_WPA_CB_FLAG_ERROR
;
831 memcpy(data
, output
, PMK_LEN
);
832 nwcb
->nas
.key
.length
= PMK_LEN
;
834 nwcb
->wpa
.pmk_len
= nwcb
->nas
.key
.length
;
838 if (CHECK_RADIUS(nwcb
->nas
.mode
)) {
840 len
= strlen((char *)key
);
841 if (len
> NAS_WKSP_MAX_USER_KEY_LEN
) {
842 NASDBG("%s: %s too long, truncated\n", nwcb
->nas
.interface
, key
);
843 len
= NAS_WKSP_MAX_USER_KEY_LEN
;
845 nwcb
->nas
.secret
.data
= key
;
846 nwcb
->nas
.secret
.length
= len
;
849 /* init mode-specific keys */
850 if (CHECK_NAS(nwcb
->nas
.mode
)) {
851 /* generate the initial global_key_counter and gmk */
852 initialize_global_key_counter(&nwcb
->wpa
);
853 initialize_gmk(&nwcb
->wpa
);
856 /* get default key size, key index */
857 if (!nwcb
->wpa
.gtk_rekey_secs
) {
859 * Honor statically configured WEP key. Key index
860 * should be either 2 or 3.
862 if (WSEC_WEP_ENABLED(nwcb
->nas
.wsec
) &&
863 nwcb
->index
&& strlen((char *)nwcb
->wep
)) {
865 uint8 wep
[NAS_WKSP_MAX_USER_KEY_LEN
+ 1];
870 switch (strlen((char *)key
)) {
872 case WEP128_KEY_SIZE
:
873 len
= strlen((char *)key
);
874 strcpy((char *)wep
, (char *) key
);
876 case WEP1_KEY_HEX_SIZE
:
877 case WEP128_KEY_HEX_SIZE
:
878 len
= strlen((char *)key
) / 2;
880 strncpy(hex
, (char *) key
, 2);
881 *data
++ = (uint8
)strtoul(hex
, NULL
, 16);
890 /* wlconf will apply wep first */
892 bcopy(wep
, nwcb
->wpa
.gtk
, len
);
893 nwcb
->wpa
.gtk_index
= nwcb
->index
- 1;
894 nwcb
->wpa
.gtk_len
= len
;
895 nwcb
->nas
.flags
|= NAS_FLAG_GTK_PLUMBED
;
898 NASDBG("%s: unable to plumb WEP key!\n",
899 nwcb
->nas
.interface
);
900 nwcb
->flags
|= NAS_WPA_CB_FLAG_ERROR
;
905 * When doing WPA (WEP is not enabled) or doing
906 * 802.1x without static WEP key, honor the key index.
908 else if (nwcb
->index
)
909 nwcb
->wpa
.gtk_index
= nwcb
->index
- 1;
912 /* AP specific setup */
913 if (nwcb
->flags
& NAS_WPA_CB_FLAG_AUTH
) {
914 /* grab WPA capabilities, used in IE contruction */
915 nas_get_wpacap(&nwcb
->nas
, nwcb
->wpa
.cap
);
919 /* tell nas to start */
920 if (nwcb
->flags
& NAS_WPA_CB_FLAG_ERROR
) {
921 NASDBG("%s: unable to start NAS due to early error",
922 nwcb
->nas
.interface
);
926 nas_start(&nwcb
->nas
);
931 /* init all NAS instances */
933 nas_wksp_init_nas(nas_wksp_t
*nwksp
)
938 for (i
= 0; i
< nwksp
->nwcbs
; i
++) {
939 nwcb
= nwksp
->nwcb
[i
];
942 nas_init_nas(nwksp
, nwcb
);
948 /* cleanup one nas instance */
950 nas_cleanup_nas(nas_wksp_t
*nwksp
, nas_wpa_cb_t
*nwcb
)
952 wpa_reset_countermeasures(nwcb
->nas
.wpa
);
954 #if !NAS_WKSP_MODULE_TIMER
957 bcm_timer_module_cleanup(nwcb
->nas
.timer
);
963 /* cleanup all nas instances */
965 nas_wksp_cleanup_nas(nas_wksp_t
*nwksp
)
970 /* init each instance */
971 for (i
= 0; i
< nwksp
->nwcbs
; i
++) {
972 nwcb
= nwksp
->nwcb
[i
];
975 nas_cleanup_nas(nwksp
, nwcb
);
980 * Common NAS application level routines that can be used under different
981 * OSs. These functions need to be re-implemented only when the application
982 * needs a different low level control over how NAS behaves than this
985 /* init NAS workspace */
987 nas_wksp_init(nas_wksp_t
*nwksp
)
989 #if !NAS_WKSP_MODULE_TIMER
990 if (bcm_timer_module_init(NAS_WKSP_MAX_NUM_TIMER
*NAS_WKSP_MAX_NUM_INTERFACES
,
992 NASMSG("bcm_timer_module_init failed\n");
994 #endif /* #if !NAS_WKSP_MODULE_TIMER */
996 /* open connection to receive eapd messages */
997 nas_wksp_open_eapd(nwksp
);
999 #ifdef NAS_WKSP_BUILD_NAS_AUTH
1000 /* open connection to receive radius messages */
1001 (void)NAS_WKSP_OPEN_RADIUS(nwksp
);
1002 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */
1004 /* init each instance */
1005 nas_wksp_init_nas(nwksp
);
1010 /* cleanup NAS workspace */
1012 nas_wksp_cleanup(nas_wksp_t
*nwksp
)
1014 /* stop running nas */
1015 nas_wksp_cleanup_nas(nwksp
);
1017 #ifdef NAS_WKSP_BUILD_NAS_AUTH
1018 /* disconnect from radius server */
1019 NAS_WKSP_CLOSE_RADIUS(nwksp
);
1020 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */
1022 #if !NAS_WKSP_MODULE_TIMER
1023 bcm_timer_module_cleanup(nwksp
->timer
);
1024 #endif /* #if !NAS_WKSP_MODULE_TIMER */
1026 nas_wksp_close_eapd(nwksp
);
1029 #ifdef NAS_WKSP_ON_DEMAND
1030 static nas_wpa_cb_t
*
1031 nas_get_wsec(nas_wksp_t
*nwksp
, uint8
*mac
, char *osifname
)
1035 nas_wpa_cb_t
*nwcb
= NULL
;
1037 if ((ret
= get_wsec(&info
, (char *) mac
, osifname
)) != WLIFU_WSEC_SUCCESS
) {
1038 if (ret
!= WLIFU_ERR_NOT_SUPPORT_MODE
)
1039 NASDBG("Get wireless security settings failed,"
1040 "mac=0x%02x:%02x:%02x:%02x:%02x:%02x osifname = %s err %d\n",
1041 mac
[0], mac
[1], mac
[2], mac
[3], mac
[4], mac
[5],
1042 osifname
? : "NULL", ret
);
1046 nwcb
= (nas_wpa_cb_t
*)malloc(sizeof(nas_wpa_cb_t
));
1048 NASMSG("Memory allocate failed for adding new nwcb\n");
1051 memset(nwcb
, 0, sizeof(nas_wpa_cb_t
));
1053 /* Set default values */
1054 nwcb
->nwksp
= nwksp
;
1055 #if !defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL)
1056 nwcb
->flags
|= NAS_WPA_CB_FLAG_SUPPL
;
1057 nwcb
->nas
.flags
|= NAS_FLAG_SUPPLICANT
;
1058 #endif /* #if !defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL) */
1059 #if defined(NAS_WKSP_BUILD_NAS_AUTH) && !defined(NAS_WKSP_BUILD_NAS_SUPPL)
1060 nwcb
->flags
|= NAS_WPA_CB_FLAG_AUTH
;
1061 nwcb
->nas
.flags
|= NAS_FLAG_AUTHENTICATOR
;
1062 #endif /* #if defined(NAS_WKSP_BUILD_NAS_AUTH) && !defined(NAS_WKSP_BUILD_NAS_SUPPL) */
1063 nwcb
->nas
.wan
= NAS_WKSP_UNK_FILE_DESC
;
1064 nwcb
->nas
.server
.sin_port
= htons(RADIUS_PORT
);
1065 nwcb
->nas
.wsec
= TKIP_ENABLED
|AES_ENABLED
;
1066 nwcb
->nas
.wpa
= &nwcb
->wpa
;
1067 nwcb
->nas
.appl
= nwcb
;
1069 nwcb
->nas
.debug
= 1;
1072 nwcb
->nas
.disable_preauth
= 0;
1074 nwcb
->nas
.ssn_to
= 36000; /* 10hrs */
1075 nwcb
->wpa
.nas
= &nwcb
->nas
;
1077 /* interface unit */
1078 nwcb
->unit
= info
.unit
;
1079 NASDBG("new nwcb's unit %d\n", nwcb
->unit
);
1080 /* interface name */
1081 strncpy(nwcb
->nas
.interface
, info
.osifname
, IFNAMSIZ
);
1082 NASDBG("new nwcb's nas interface %s\n", nwcb
->nas
.interface
);
1083 /* interface address */
1084 memcpy(nwcb
->nas
.ea
.octet
, info
.ea
, ETHER_ADDR_LEN
);
1085 NASDBG("new nwcb's nas hwaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
1086 nwcb
->nas
.ea
.octet
[0], nwcb
->nas
.ea
.octet
[1],
1087 nwcb
->nas
.ea
.octet
[2], nwcb
->nas
.ea
.octet
[3],
1088 nwcb
->nas
.ea
.octet
[4], nwcb
->nas
.ea
.octet
[5]);
1090 strncpy(nwcb
->nas
.ssid
, info
.ssid
, DOT11_MAX_SSID_LEN
);
1091 NASDBG("new nwcb's nas ssid %s\n", nwcb
->nas
.ssid
);
1093 nwcb
->nas
.mode
= info
.akm
;
1094 NASDBG("new nwcb's nas auth mode %d\n", nwcb
->nas
.mode
);
1095 if (!nwcb
->nas
.mode
) {
1096 NASDBG("%s: Ignored interface. Invalid NAS mode\n", info
.osifname
);
1100 /* wsec encryption */
1101 nwcb
->nas
.wsec
= info
.wsec
;
1102 NASDBG("new nwcb's nas wsec encryption mode %d\n", nwcb
->nas
.wsec
);
1103 if (!nwcb
->nas
.wsec
) {
1104 NASDBG("%s: Ignored interface. Invalid WSEC\n", info
.osifname
);
1109 /* nas role setting */
1110 #if defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL)
1111 nwcb
->flags
= info
.flags
;
1112 nwcb
->nas
.flags
= info
.flags
;
1113 #endif /* #if defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL) */
1114 if (info
.flags
& NAS_WPA_CB_FLAG_WDS
) {
1115 nwcb
->flags
= info
.flags
;
1116 nwcb
->nas
.flags
= info
.flags
;
1118 NASDBG("new nwcb's nas flags %d\n", nwcb
->nas
.flags
);
1120 /* remote address */
1121 memcpy(nwcb
->nas
.remote
, info
.remote
, ETHER_ADDR_LEN
);
1122 NASDBG("new nwcb's nas remote %02x:%02x:%02x:%02x:%02x:%02x\n",
1123 nwcb
->nas
.remote
[0], nwcb
->nas
.remote
[1],
1124 nwcb
->nas
.remote
[2], nwcb
->nas
.remote
[3],
1125 nwcb
->nas
.remote
[4], nwcb
->nas
.remote
[5]);
1126 /* user-supplied psk passphrase */
1128 strncpy((char *)nwcb
->psk
, info
.psk
, NAS_WKSP_MAX_USER_KEY_LEN
);
1129 nwcb
->psk
[NAS_WKSP_MAX_USER_KEY_LEN
] = 0;
1130 NASDBG("new nwcb's psk %s\n", nwcb
->psk
);
1132 /* user-supplied radius server secret */
1134 strncpy((char *)nwcb
->secret
, info
.secret
, NAS_WKSP_MAX_USER_KEY_LEN
);
1135 nwcb
->secret
[NAS_WKSP_MAX_USER_KEY_LEN
] = 0;
1136 NASDBG("new nwcb's secret %s\n", nwcb
->secret
);
1138 #ifdef NAS_WKSP_BUILD_NAS_AUTH
1139 nwcb
->wpa
.gtk_rekey_secs
= info
.gtk_rekey_secs
;
1140 NASDBG("new nwcb's wpa gtk_rekey_sec %d\n", nwcb
->wpa
.gtk_rekey_secs
);
1142 nwcb
->index
= info
.wep_index
;
1143 NASDBG("new nwcb's wep index %d\n", nwcb
->index
);
1146 strncpy((char *)nwcb
->wep
, info
.wep_key
, NAS_WKSP_MAX_USER_KEY_LEN
);
1147 nwcb
->wep
[NAS_WKSP_MAX_USER_KEY_LEN
] = 0;
1148 NASDBG("new nwcb's wep %s\n", nwcb
->wep
);
1150 /* radius server host/port */
1152 /* update radius server address */
1153 if (info
.radius_addr
) {
1154 nwcb
->nas
.server
.sin_family
= AF_INET
;
1155 nwcb
->nas
.server
.sin_addr
.s_addr
= inet_addr(info
.radius_addr
);
1156 /* update radius server port number */
1157 nwcb
->nas
.server
.sin_port
= info
.radius_port
;
1158 NASDBG("new nwcb's nas radius server address %s, port %d\n",
1159 info
.radius_addr
, nwcb
->nas
.server
.sin_port
);
1161 #endif /* NAS_RADIUS */
1162 /* 802.1x session timeout/pmk cache duration */
1163 nwcb
->nas
.ssn_to
= info
.ssn_to
;
1164 NASDBG("new nwcb's nas ssn timeout %d\n", nwcb
->nas
.ssn_to
);
1165 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */
1168 /* verbose - 0:no | others:yes */
1169 nwcb
->nas
.debug
= info
.debug
;
1170 NASDBG("new nwcb's nas debug %d\n", nwcb
->nas
.debug
);
1174 nwcb
->nas
.disable_preauth
= (info
.preauth
== 0) ? 1 : 0;
1175 NASDBG("new nwcb's nas disable_preauth %d\n", nwcb
->nas
.disable_preauth
);
1181 strncpy(nwcb
->nas
.nas_id
, info
.nas_id
, MAX_NAS_ID_LEN
);
1182 NASDBG("new nwcb's nas nas_id %s\n", nwcb
->nas
.nas_id
);
1187 nwksp
->nwcb
[nwksp
->nwcbs
++] = nwcb
;
1192 /* add new NAS instance */
1194 nas_wksp_add_nwcb(nas_wksp_t
*nwksp
, uint8
*mac
, char *osifname
)
1196 nas_wpa_cb_t
*nwcb
= NULL
;
1198 /* retrieve wireless security infomation for this interface */
1199 if (nwksp
->nwcbs
< NAS_WKSP_MAX_NUM_INTERFACES
) {
1200 if (!(nwcb
= nas_get_wsec(nwksp
, mac
, osifname
))) {
1204 #ifdef NAS_WKSP_BUILD_NAS_AUTH
1205 /* open connection to receive radius messages */
1206 if (CHECK_RADIUS(nwcb
->nas
.mode
)) {
1207 /* open connection to radius server */
1208 if (NAS_RADIUS_OPEN(nwksp
, nwcb
) != 0)
1209 NASMSG("%s: open radius connection failed\n", nwcb
->nas
.interface
);
1211 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */
1213 /* init new instance */
1214 nas_init_nas(nwksp
, nwcb
);
1219 #endif /* #ifdef NAS_WKSP_ON_DEMAND */
1221 /* find NAS instance based on MAC address and i/f name */
1223 nas_wksp_find_nwcb(nas_wksp_t
*nwksp
, uint8
*mac
, char *osifname
, int mode
)
1226 char eabuf
[ETHER_ADDR_STR_LEN
];
1228 nas_wpa_cb_t
*nwcb
= NULL
;
1231 for (i
= 0; i
< nwksp
->nwcbs
; i
++) {
1232 nwcb
= nwksp
->nwcb
[i
];
1235 if (!bcmp(mac
, nwcb
->nas
.ea
.octet
, ETHER_ADDR_LEN
)) {
1237 NASDBG("%s *: found %08x\n",
1238 ether_etoa((uchar
*)mac
, eabuf
), (uint
)nwcb
);
1241 else if (!strncmp(nwcb
->nas
.interface
, osifname
, BCM_MSG_IFNAME_MAX
)) {
1242 NASDBG("%s %s: found %08x\n",
1243 ether_etoa((uchar
*)mac
, eabuf
), osifname
, (uint
)nwcb
);
1249 if (mode
== NAS_WKSP_NWCB_SEARCH_ENTER
)
1250 nwcb
= NAS_WKSP_ADD_NWCB(nwksp
, mac
, osifname
);
1253 NASDBG("%s %s: find error\n", ether_etoa((uchar
*)mac
, eabuf
), osifname
? : "*");
1259 ** Return values are really improtant here please make sure you look
1260 ** thr'u the code before changing it. vx code depends on the return values.
1262 ** 0,our packet otherwise not our packet
1265 nas_validate_wlpvt_message(int bytes
, uint8
*dpkt
)
1267 bcm_event_t
*pvt_data
;
1269 /* the message should be at least the header to even look at it */
1270 if (bytes
< sizeof(bcm_event_t
) + 2) {
1271 NASDBG("nas_validate_wlpvt_message: invalid length of message\n");
1274 pvt_data
= (bcm_event_t
*)dpkt
;
1275 if (ntohs(pvt_data
->bcm_hdr
.subtype
) != BCMILCP_SUBTYPE_VENDOR_LONG
) {
1276 NASDBG("%s: nas_validate_wlpvt_message: not vendor specifictype\n",
1277 pvt_data
->event
.ifname
);
1280 if (pvt_data
->bcm_hdr
.version
!= BCMILCP_BCM_SUBTYPEHDR_VERSION
) {
1281 NASDBG("%s: nas_validate_wlpvt_message: subtype header version mismatch\n",
1282 pvt_data
->event
.ifname
);
1285 if (ntohs(pvt_data
->bcm_hdr
.length
) < BCMILCP_BCM_SUBTYPEHDR_MINLENGTH
) {
1286 NASDBG("%s: nas_validate_wlpvt_message: subtype hdr length not even minimum\n",
1287 pvt_data
->event
.ifname
);
1290 if (bcmp(&pvt_data
->bcm_hdr
.oui
[0], BRCM_OUI
, DOT11_OUI_LEN
) != 0) {
1291 NASDBG("%s: nas_validate_wlpvt_message: not BRCM OUI\n", pvt_data
->event
.ifname
);
1294 /* check for wl nas message types */
1295 switch (ntohs(pvt_data
->bcm_hdr
.usr_subtype
)) {
1296 case BCMILCP_BCM_SUBTYPE_EVENT
:
1297 /* wl nas message */
1298 /* if (pvt_data->version != BCM_MSG_VERSION) {
1299 * atleast a debug message
1307 return 0; /* good packet may be this is destined to us */
1313 nas_eapol_message_dispatch(nas_wpa_cb_t
*nwcb
, void *eapol
, int bytes
)
1315 nas_t
*nas
= &nwcb
->nas
;
1317 #if defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL)
1318 if (nwcb
->flags
& NAS_WPA_CB_FLAG_AUTH
)
1319 eapol_dispatch(nas
, eapol
);
1321 eapol_sup_dispatch(nas
, eapol
);
1322 #elif defined(NAS_WKSP_BUILD_NAS_AUTH) /* Only support authenticator */
1323 eapol_dispatch(nas
, eapol
);
1324 #else /* Only support supplicant */
1325 eapol_sup_dispatch(nas
, eapol
);
1326 #endif /* #if defined(NAS_WKSP_BUILD_NAS_AUTH) && defined(NAS_WKSP_BUILD_NAS_SUPPL) */
1332 nas_handle_wlpvt_messages(nas_wpa_cb_t
*nwcb
, void *pkt
, int bytes
)
1336 dpkt
= (bcm_event_t
*)pkt
;
1337 NASDBG("received event of type : %d\n", ntohs(dpkt
->event
.event_type
));
1338 switch (ntohs(dpkt
->bcm_hdr
.usr_subtype
)) {
1339 case BCMILCP_BCM_SUBTYPE_EVENT
:
1340 /* ingore EAPOL message encapsulated ini bcmevent packet */
1341 if ((ntohl(dpkt
->event
.event_type
) != WLC_E_EAPOL_MSG
)) {
1342 NASDBG("%s: recved wl wpa packet interface bytes: %d\n",
1343 dpkt
->event
.ifname
, bytes
);
1344 driver_message_dispatch(&nwcb
->nas
, dpkt
);
1348 default: /* not a NAS supported message so return an error */
1349 NASDBG("%s: ERROR: recved unknown packet interface subtype "
1350 "0x%x bytes: %d\n", dpkt
->event
.ifname
,
1351 ntohs(dpkt
->bcm_hdr
.usr_subtype
), bytes
);
1359 nas_wksp_clear_inited()
1361 nas_wksp_inited
= 0;
1364 int nas_wksp_is_inited()
1366 return nas_wksp_inited
;