2 * vxWorks-specific portion of EAPD
5 * Copyright (C) 2010, Broadcom Corporation
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: eapd_vx.c 241391 2011-02-18 03:35:48Z stakita $
36 #include <proto/ethernet.h>
37 #include <proto/eapol.h>
38 #include <proto/eap.h>
43 #include <wlif_utils.h>
45 #include <security_ipc.h>
47 extern int sysClkRateGet(void);
49 static eapd_wksp_t
*eapd_nwksp
= NULL
;
51 #define VX_MUX_MAX_OBJS EAPD_WKSP_MAX_NO_BRCM + EAPD_WKSP_MAX_NO_BRIDGE
52 typedef struct vx_mux_obj
{
58 static vx_mux_obj_t muxobjs
[VX_MUX_MAX_OBJS
];
60 typedef struct pif2index
{
61 char ifname
[IFNAMSIZ
];
65 static pif2index_t if2index
[] = {
73 #define CHECK_ETHER_TYPE(type) (((type) == ETHER_TYPE_BRCM) || \
74 ((type) == ETHER_TYPE_802_1X_PREAUTH))
76 #define CHECK_ETHER_TYPE(type) ((type) == ETHER_TYPE_BRCM)
80 eapd_hup_hdlr(int sig
)
83 eapd_nwksp
->flags
|= EAPD_WKSP_FLAG_SHUTDOWN
;
90 eapd_dump_hdlr(int sig
)
93 eapd_nwksp
->flags
|= EAPD_WKSP_FLAG_DUMP
;
99 /* parse interface name and retrieve device name and unit number */
101 _ifunit_(char *ifname
, char *dev
, int *unit
)
103 /* Parse unit number */
104 for (*dev
= *ifname
; *dev
!= EOS
&& !isdigit((int)*dev
); *dev
= *ifname
) {
110 *unit
= atoi(ifname
);
118 _get_lbport_(char *dev
, int unit
, int type
)
120 /* wl, et, vl, mirror */
121 int i
, base
, if2indexsz
;
123 if2indexsz
= sizeof(if2index
) / sizeof(pif2index_t
);
124 base
= EAPD_WKSP_NAS_UDP_SPORT
+ EAPD_WKSP_VX_PORT_OFFSET
;
126 if (!CHECK_ETHER_TYPE(type
))
129 for (i
= 0; i
< if2indexsz
; i
++) {
130 if (!strcmp(if2index
[i
].ifname
, dev
))
136 base
+= if2index
[i
].idx
;
138 base
+= (type
& 0xff);
148 memset(muxobjs
, 0, sizeof(muxobjs
));
149 for (i
= 0; i
< VX_MUX_MAX_OBJS
; i
++)
150 muxobjs
[i
].lbSocket
= -1;
153 static vx_mux_obj_t
*
154 muxobj_find(int lbSocket
)
161 for (i
= 0; i
< VX_MUX_MAX_OBJS
; i
++) {
162 if ((lbSocket
== muxobjs
[i
].lbSocket
) &&
164 return (&muxobjs
[i
]);
170 static vx_mux_obj_t
*
175 for (i
= 0; i
< VX_MUX_MAX_OBJS
; i
++) {
176 if (muxobjs
[i
].used
== 0) {
178 return (&muxobjs
[i
]);
186 muxobj_free(vx_mux_obj_t
*muxobj
)
189 memset(muxobj
, 0, sizeof(vx_mux_obj_t
));
190 muxobj
->lbSocket
= -1;
198 * A network service that receives and processes the messages
199 * sent from wireless END driver (assoc/disassoc) thru MUX.
201 /* service - shutdown routine - END */
203 stop_brcm_svc(void *param
, void *spare
)
208 /* send it to loopback socket, eapd receive it in vxWorks platform */
210 recv_brcm_msg(void *param
, long type
,
211 M_BLK_ID mbuf
, LL_HDR_INFO
*llhdr
, void *spare
)
213 uint8
*pkt
= mbuf
->mBlkHdr
.mData
;
214 int bytes
= mbuf
->mBlkHdr
.mLen
;
215 vx_mux_obj_t
*muxobj
= (vx_mux_obj_t
*)spare
;
217 /* send this date to lbSocket */
218 if (muxobj
->lbSocket
>= 0) {
220 struct sockaddr_in to
;
222 to
.sin_addr
.s_addr
= inet_addr(EAPD_WKSP_UDP_ADDR
);
223 to
.sin_family
= AF_INET
;
224 to
.sin_port
= htons(muxobj
->lbPort
);
226 sentBytes
= sendto(muxobj
->lbSocket
, pkt
, bytes
, 0,
227 (struct sockaddr
*)&to
, sizeof(struct sockaddr_in
));
229 if (sentBytes
!= bytes
) {
230 EAPD_ERROR("UDP send failed; sentBytes = %d\n", sentBytes
);
233 /* EAPD_ERROR("Send %d bytes to eapd\n", sentBytes); */
237 EAPD_ERROR("eapd vxWorks lbSocket not created\n");
241 netMblkClChainFree(mbuf
);
246 /* service - error notification - END */
248 notify_brcm_error(END_OBJ
*end
, END_ERR
*error
, void *spare
)
252 /* service - restart - END */
254 restart_brcm_svc(void *param
, void *spare
)
261 stop_preauth_svc(void *param
, void *spare
)
266 /* send it to loopback socket, eapd receive it in vxWorks platform */
268 recv_preauth_msg(void *param
, long type
, M_BLK_ID mbuf
,
269 LL_HDR_INFO
*llhdr
, void *spare
)
271 uint8
*pkt
= mbuf
->mBlkHdr
.mData
;
272 int bytes
= mbuf
->mBlkHdr
.mLen
;
273 vx_mux_obj_t
*muxobj
= (vx_mux_obj_t
*)spare
;
275 /* send this date to lbSocket */
276 if (muxobj
->lbSocket
>= 0) {
278 struct sockaddr_in to
;
280 to
.sin_addr
.s_addr
= inet_addr(EAPD_WKSP_UDP_ADDR
);
281 to
.sin_family
= AF_INET
;
282 to
.sin_port
= htons(muxobj
->lbPort
);
284 sentBytes
= sendto(muxobj
->lbSocket
, pkt
, bytes
, 0,
285 (struct sockaddr
*)&to
, sizeof(struct sockaddr_in
));
287 if (sentBytes
!= bytes
) {
288 EAPD_ERROR("UDP send failed; sentBytes = %d\n", sentBytes
);
291 /* EAPD_ERROR("Send %d bytes to eapd\n", sentBytes); */
295 EAPD_ERROR("eapd vxWorks lbSocket not created\n");
299 netMblkClChainFree(mbuf
);
304 /* service - error notification - END */
306 notify_preauth_error(END_OBJ
*end
, END_ERR
*error
, void *spare
)
310 /* service - restart - END */
312 restart_preauth_svc(void *param
, void *spare
)
318 #include <private/muxLibP.h>
319 static M_BLK_ID
_mblk_(vx_mux_obj_t
*muxobj
, uint8
*pkt
, int len
)
324 /* size requested should fit in our cluster buffer */
327 EAPD_ERROR("packet is too big %d on drvSocket %d\n", len
, muxobj
->lbSocket
);
331 /* muxobj->pCookie is a mux cookie */
332 end
= PCOOKIE_TO_ENDOBJ(muxobj
->pCookie
);
334 /* alloc packet from pool and copy data */
335 if ((m
= netTupleGet(end
->pNetPool
, len
, M_DONTWAIT
, MT_DATA
, FALSE
)))
337 /* reserve a few bytes */
338 m
->mBlkHdr
.mLen
= len
;
340 /* ensure the cookie field is cleared */
341 m
->mBlkPktHdr
.len
= 0;
343 /* copy packet content */
344 bcopy(pkt
, m
->mBlkHdr
.mData
, len
);
347 EAPD_ERROR("netTupleGet error 0x%x, end = 0x%x end->pNetPool = 0x%x, pCookie="
348 "0x%x\n", errno
, (int)end
, (int)end
->pNetPool
, (int)muxobj
->pCookie
);
355 eapd_send(eapd_wksp_t
*nwksp
, int drvSocket
, struct iovec
*frags
, int nfrags
)
361 vx_mux_obj_t
*muxobj
;
363 /* find muxobj from drvSocket */
364 if ((muxobj
= muxobj_find(drvSocket
)) == NULL
) {
365 EAPD_ERROR("can not find muxobj from drvSocket %d\n", drvSocket
);
369 /* Convert iov to mbuf chain */
371 for (i
= 0, count
= 0; i
< nfrags
; i
++)
372 count
+= frags
[i
].iov_len
;
373 if (!(buf
= malloc(count
))) {
374 EAPD_ERROR("malloc error on drvSocket %d\n", drvSocket
);
377 for (i
= 0, count
= 0; i
< nfrags
; i
++) {
378 memcpy(&buf
[count
], frags
[i
].iov_base
, frags
[i
].iov_len
);
379 count
+= frags
[i
].iov_len
;
381 mbuf
= _mblk_(muxobj
, (void *)buf
, count
);
384 else if (nfrags
== 1) {
385 mbuf
= _mblk_(muxobj
, (void *)frags
[0].iov_base
, frags
[0].iov_len
);
388 EAPD_ERROR("nfrags == 0 error on drvSocket %d\n", drvSocket
);
393 EAPD_ERROR("failed to allocate mblk on drvSocket %d\n", drvSocket
);
397 /* send packet to network thru the interface */
398 status
= muxSend(muxobj
->pCookie
, mbuf
);
399 if (status
== END_ERR_BLOCK
) {
400 EAPD_ERROR("send error %d to drvSocket %d\n", errno
, drvSocket
);
401 netMblkClChainFree(mbuf
);
406 /* Send a canned EAPOL packet */
408 eapd_eapol_canned_send(eapd_wksp_t
*nwksp
, struct eapd_socket
*Socket
, eapd_sta_t
*sta
,
409 unsigned char code
, unsigned char type
)
411 eapol_header_t eapol
;
413 struct iovec frags
[2];
415 memcpy(&eapol
.eth
.ether_dhost
, &sta
->ea
, ETHER_ADDR_LEN
);
416 memcpy(&eapol
.eth
.ether_shost
, &sta
->bssid
, ETHER_ADDR_LEN
);
418 eapol
.eth
.ether_type
= htons(ETHER_TYPE_802_1X
);
419 eapol
.version
= sta
->eapol_version
;
420 eapol
.type
= EAP_PACKET
;
421 eapol
.length
= htons(type
? (EAP_HEADER_LEN
+ 1) : EAP_HEADER_LEN
);
424 eap
.id
= sta
->pae_id
;
425 eap
.length
= eapol
.length
;
428 frags
[0].iov_base
= (caddr_t
) &eapol
;
429 frags
[0].iov_len
= EAPOL_HEADER_LEN
;
430 frags
[1].iov_base
= (caddr_t
) &eap
;
431 frags
[1].iov_len
= ntohs(eapol
.length
);
433 eapd_send(nwksp
, Socket
->drvSocket
, frags
, 2);
437 eapd_message_send(eapd_wksp_t
*nwksp
, struct eapd_socket
*Socket
, uint8
*pData
, int pLen
)
439 struct iovec frags
[1];
441 frags
[0].iov_base
= (caddr_t
) pData
;
442 frags
[0].iov_len
= pLen
;
444 eapd_send(nwksp
, Socket
->drvSocket
, frags
, 1);
448 eapd_brcm_open(eapd_wksp_t
*nwksp
, eapd_brcm_socket_t
*sock
)
450 int unit
, lbport
, reuse
= 1;
452 vx_mux_obj_t
*muxobj
;
453 struct sockaddr_in addr
;
456 if (nwksp
== NULL
|| sock
== NULL
) {
457 EAPD_ERROR("Wrong arguments...\n");
461 /* retrieve interface dev name and index */
462 _ifunit_(sock
->ifname
, dev
, &unit
);
464 lbport
= _get_lbport_(dev
, unit
, ETHER_TYPE_BRCM
);
466 EAPD_ERROR("%s: can not get a loopback bind port ...\n", sock
->ifname
);
470 /* check if the dev is an NPT/END complaint driver */
471 if (muxTkDrvCheck(dev
) != 0) {
472 EAPD_ERROR("%s: not an NTP/END complaint driver ...\n", dev
);
476 /* open a udp loopback for this ifname and type */
477 sock
->drvSocket
= socket(AF_INET
, SOCK_DGRAM
, 0);
478 if (sock
->drvSocket
< 0) {
479 EAPD_ERROR("UDP Open failed.\n");
482 if (setsockopt(sock
->drvSocket
, SOL_SOCKET
, SO_REUSEPORT
, (char*)&reuse
,
483 sizeof(reuse
)) < 0) {
484 EAPD_ERROR("UDP setsockopt failed.\n");
485 close(sock
->drvSocket
);
486 sock
->drvSocket
= -1;
490 memset(&addr
, 0, sizeof(struct sockaddr_in
));
491 addr
.sin_family
= AF_INET
;
492 addr
.sin_addr
.s_addr
= INADDR_ANY
;
493 addr
.sin_port
= htons(lbport
);
494 if (bind(sock
->drvSocket
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
495 EAPD_ERROR("UDP Bind failed, close brcm lbSocket %d\n", sock
->drvSocket
);
496 close(sock
->drvSocket
);
497 sock
->drvSocket
= -1;
500 EAPD_INFO("%s: BRCM socket %d opened\n", sock
->ifname
, sock
->drvSocket
);
502 if ((muxobj
= muxobj_get()) == NULL
) {
503 EAPD_ERROR("%s: can not get a local muxobj ...\n", sock
->ifname
);
504 close(sock
->drvSocket
);
505 sock
->drvSocket
= -1;
509 /* bind the service to the END driver */
510 if (!(muxobj
->pCookie
= muxBind(dev
, unit
,
511 recv_brcm_msg
, stop_brcm_svc
,
512 restart_brcm_svc
, notify_brcm_error
,
513 ETHER_TYPE_BRCM
, "BRCMEVT", muxobj
))) {
514 EAPD_ERROR("%s: failed to open brcm muxsocket (%x)\n", sock
->ifname
, errnoGet());
515 close(sock
->drvSocket
);
516 sock
->drvSocket
= -1;
521 /* at least one use it */
522 sock
->inuseCount
= 1;
523 muxobj
->lbSocket
= sock
->drvSocket
;
524 muxobj
->lbPort
= lbport
;
526 EAPD_INFO("%s: BRCM muxsocket %08x opened\n", sock
->ifname
, (int)muxobj
->pCookie
);
532 eapd_brcm_close(int drvSocket
)
535 vx_mux_obj_t
*muxobj
;
540 muxobj
= muxobj_find(drvSocket
);
542 ret
= muxUnbind((void *)muxobj
->pCookie
, ETHER_TYPE_BRCM
, recv_brcm_msg
);
544 EAPD_ERROR("brcm close failed 0x%x, drvSocket %d muxsocket %08x\n",
545 errno
, drvSocket
, (int)muxobj
->pCookie
);
550 EAPD_ERROR("muxobj not found drvSocket %d\n", drvSocket
);
561 eapd_preauth_open(eapd_wksp_t
*nwksp
, eapd_preauth_socket_t
*sock
)
563 int unit
, lbport
, reuse
= 1;
565 vx_mux_obj_t
*muxobj
;
566 struct sockaddr_in addr
;
569 if (nwksp
== NULL
|| sock
== NULL
) {
570 EAPD_ERROR("Wrong arguments...\n");
574 /* retrieve interface dev name and index */
575 _ifunit_(sock
->ifname
, dev
, &unit
);
577 lbport
= _get_lbport_(dev
, unit
, ETHER_TYPE_802_1X_PREAUTH
);
579 EAPD_ERROR("%s: can not get a loopback bind port ...\n", sock
->ifname
);
583 /* check if the dev is an NPT/END complaint driver */
584 if (muxTkDrvCheck(dev
) != 0) {
585 EAPD_ERROR("%s: not an NTP/END complaint driver ...\n", dev
);
589 /* open a udp loopback for this ifname and type */
590 sock
->drvSocket
= socket(AF_INET
, SOCK_DGRAM
, 0);
591 if (sock
->drvSocket
< 0) {
592 EAPD_ERROR("UDP Open failed.\n");
595 if (setsockopt(sock
->drvSocket
, SOL_SOCKET
, SO_REUSEPORT
, (char*)&reuse
,
596 sizeof(reuse
)) < 0) {
597 EAPD_ERROR("UDP setsockopt failed.\n");
598 close(sock
->drvSocket
);
599 sock
->drvSocket
= -1;
603 memset(&addr
, 0, sizeof(struct sockaddr_in
));
604 addr
.sin_family
= AF_INET
;
605 addr
.sin_addr
.s_addr
= INADDR_ANY
;
606 addr
.sin_port
= htons(lbport
);
607 if (bind(sock
->drvSocket
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
608 EAPD_ERROR("UDP Bind failed, close brcm lbSocket %d\n", sock
->drvSocket
);
609 close(sock
->drvSocket
);
610 sock
->drvSocket
= -1;
613 EAPD_INFO("%s: preauth socket %d opened\n", sock
->ifname
, sock
->drvSocket
);
615 if ((muxobj
= muxobj_get()) == NULL
) {
616 EAPD_ERROR("%s: can not get a local muxobj ...\n", sock
->ifname
);
617 close(sock
->drvSocket
);
618 sock
->drvSocket
= -1;
622 /* bind the service to the END driver */
623 if (!(muxobj
->pCookie
= muxBind(dev
, unit
,
624 recv_preauth_msg
, stop_preauth_svc
,
625 restart_preauth_svc
, notify_preauth_error
,
626 ETHER_TYPE_802_1X_PREAUTH
, "PREAUTH", muxobj
))) {
627 EAPD_ERROR("%s: failed to open preauth muxsocket (%x)\n", sock
->ifname
, errnoGet());
628 close(sock
->drvSocket
);
629 sock
->drvSocket
= -1;
634 /* at least one use it */
635 sock
->inuseCount
= 1;
636 muxobj
->lbSocket
= sock
->drvSocket
;
637 muxobj
->lbPort
= lbport
;
639 EAPD_INFO("%s: preauth muxsocket %08x opened\n", sock
->ifname
, (int)muxobj
->pCookie
);
645 eapd_preauth_close(int drvSocket
)
648 vx_mux_obj_t
*muxobj
;
653 muxobj
= muxobj_find(drvSocket
);
655 ret
= muxUnbind((void *)muxobj
->pCookie
, ETHER_TYPE_802_1X_PREAUTH
,
658 EAPD_ERROR("preauth close failed 0x%x, drvSocket %d muxsocket %08x\n",
659 errno
, drvSocket
, (int)muxobj
->pCookie
);
664 EAPD_ERROR("muxobj not found drvSocket %d\n", drvSocket
);
678 eapd_safe_get_conf(char *outval
, int outval_size
, char *name
)
682 if (name
== NULL
|| outval
== NULL
) {
684 memset(outval
, 0, outval_size
);
688 val
= nvram_safe_get(name
);
689 if (!strcmp(val
, ""))
690 memset(outval
, 0, outval_size
);
692 snprintf(outval
, outval_size
, "%s", val
);
696 int eapd_main(int argc
, char* argv
[])
703 /* get eapd_msg_level from nvram */
704 if ((dbg
= nvram_get("eapd_dbg"))) {
705 eapd_msg_level
= (uint
)strtoul(dbg
, NULL
, 0);
710 EAPD_INFO("EAP Dispatch Start...\n");
712 /* clear muxobjs array */
715 /* alloc eapd work space */
716 if (!(eapd_nwksp
= eapd_wksp_alloc_workspace())) {
717 EAPD_ERROR("Unable to allocate wksp memory. Quitting...\n");
721 if (eapd_wksp_auto_config(eapd_nwksp
)) {
722 EAPD_ERROR("Unable to auto config. Quitting...\n");
723 eapd_wksp_cleanup(eapd_nwksp
);
727 /* establish a handler to handle SIGTERM. */
728 signal(SIGTERM
, eapd_hup_hdlr
);
731 signal(SIGUSR1
, eapd_dump_hdlr
);
734 eapd_wksp_main_loop(eapd_nwksp
);
736 EAPD_INFO("EAP Dispatcher Stopped...\n");
745 int tid
= taskNameToId("EAPD");
749 /* clear eapd wksp initialization flag */
750 eapd_wksp_clear_inited();
753 60, /* priority of new task */
754 0, /* task option word */
755 30000, /* size (bytes) of stack needed plus name */
756 (FUNCPTR
)eapd_main
, /* entry point of new task */
759 0, 0, 0, 0, 0, 0, 0, 0);
760 printf("EAPD task started.\n");
762 /* wait until eapd initialization finished */
765 if (tickGet() - ticks
< 3 * sysClkRateGet())
766 taskDelay(sysClkRateGet());
768 printf("Unable to wait EAPD initialization finished!.\n");
771 } while (taskNameToId("EAPD") != ERROR
&& !eapd_wksp_is_inited());
774 printf("EAPD task is already running.\n");
780 int tid
= taskNameToId("EAPD");
787 /* wait till the task is dead */
790 if (tickGet() - ticks
< 3 * sysClkRateGet())
791 taskDelay(sysClkRateGet());
793 printf("Unable to kill EAPD task!.\n");
797 while (taskNameToId("EAPD") != ERROR
);
798 printf("EAPD task killed.\n");
801 printf("EAPD task is not running.\n");