allow coexistance of N build and AC build.
[tomato.git] / release / src-rt / wl / eapd / eapd_vx.c
blobac282a07c15f8fe154fe34a744209df56425f6c3
1 /*
2 * vxWorks-specific portion of EAPD
3 * (OS dependent file)
5 * Copyright (C) 2010, 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: eapd_vx.c 241391 2011-02-18 03:35:48Z stakita $
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <errno.h>
22 #include <signal.h>
23 #include <ctype.h>
25 #include <vxWorks.h>
26 #include <ioLib.h>
27 #include <ifLib.h>
28 #include <muxLib.h>
29 #include <muxTkLib.h>
30 #include <tickLib.h>
31 #include <taskLib.h>
32 #include <errnoLib.h>
34 #include <typedefs.h>
35 #include <bcmutils.h>
36 #include <proto/ethernet.h>
37 #include <proto/eapol.h>
38 #include <proto/eap.h>
39 #include <wlutils.h>
40 #include <bcmnvram.h>
41 #include <eapd.h>
42 #include <shutils.h>
43 #include <wlif_utils.h>
44 #include <UdpLib.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 {
53 void *pCookie;
54 int lbSocket;
55 short lbPort;
56 short used;
57 } vx_mux_obj_t;
58 static vx_mux_obj_t muxobjs[VX_MUX_MAX_OBJS];
60 typedef struct pif2index {
61 char ifname[IFNAMSIZ];
62 int idx;
63 } pif2index_t;
65 static pif2index_t if2index[] = {
66 {"wl", 1},
67 {"et", 2},
68 {"vl", 3},
69 {"mirror", 4}
72 #ifdef BCMWPA2
73 #define CHECK_ETHER_TYPE(type) (((type) == ETHER_TYPE_BRCM) || \
74 ((type) == ETHER_TYPE_802_1X_PREAUTH))
75 #else
76 #define CHECK_ETHER_TYPE(type) ((type) == ETHER_TYPE_BRCM)
77 #endif /* BCMWPA2 */
79 static void
80 eapd_hup_hdlr(int sig)
82 if (eapd_nwksp)
83 eapd_nwksp->flags |= EAPD_WKSP_FLAG_SHUTDOWN;
85 return;
88 #ifdef EAPDDUMP
89 static void
90 eapd_dump_hdlr(int sig)
92 if (eapd_nwksp)
93 eapd_nwksp->flags |= EAPD_WKSP_FLAG_DUMP;
95 return;
97 #endif
99 /* parse interface name and retrieve device name and unit number */
100 static int
101 _ifunit_(char *ifname, char *dev, int *unit)
103 /* Parse unit number */
104 for (*dev = *ifname; *dev != EOS && !isdigit((int)*dev); *dev = *ifname) {
105 dev++;
106 ifname++;
108 if (*dev != EOS) {
109 *dev = 0;
110 *unit = atoi(ifname);
111 return OK;
114 return ERROR;
117 static int
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))
127 return -1;
129 for (i = 0; i < if2indexsz; i++) {
130 if (!strcmp(if2index[i].ifname, dev))
131 break;
133 if (i == if2indexsz)
134 return -1;
136 base += if2index[i].idx;
137 base += unit;
138 base += (type & 0xff);
140 return base;
143 static void
144 muxobj_init()
146 int i;
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)
156 int i;
158 if (lbSocket < 0)
159 return NULL;
161 for (i = 0; i < VX_MUX_MAX_OBJS; i++) {
162 if ((lbSocket == muxobjs[i].lbSocket) &&
163 muxobjs[i].used)
164 return (&muxobjs[i]);
167 return NULL;
170 static vx_mux_obj_t *
171 muxobj_get()
173 int i;
175 for (i = 0; i < VX_MUX_MAX_OBJS; i++) {
176 if (muxobjs[i].used == 0) {
177 muxobjs[i].used = 1;
178 return (&muxobjs[i]);
182 return NULL;
185 static int
186 muxobj_free(vx_mux_obj_t *muxobj)
188 if (muxobj) {
189 memset(muxobj, 0, sizeof(vx_mux_obj_t));
190 muxobj->lbSocket = -1;
191 return 0;
194 return -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 */
202 static STATUS
203 stop_brcm_svc(void *param, void *spare)
205 return OK;
208 /* send it to loopback socket, eapd receive it in vxWorks platform */
209 static BOOL
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) {
219 int sentBytes = 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);
232 else {
233 /* EAPD_ERROR("Send %d bytes to eapd\n", sentBytes); */
236 else {
237 EAPD_ERROR("eapd vxWorks lbSocket not created\n");
240 /* Mesage is ours */
241 netMblkClChainFree(mbuf);
243 return TRUE;
246 /* service - error notification - END */
247 static void
248 notify_brcm_error(END_OBJ *end, END_ERR *error, void *spare)
252 /* service - restart - END */
253 static STATUS
254 restart_brcm_svc(void *param, void *spare)
256 return OK;
259 #ifdef BCMWPA2
260 static STATUS
261 stop_preauth_svc(void *param, void *spare)
263 return OK;
266 /* send it to loopback socket, eapd receive it in vxWorks platform */
267 static BOOL
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) {
277 int sentBytes = 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);
290 else {
291 /* EAPD_ERROR("Send %d bytes to eapd\n", sentBytes); */
294 else {
295 EAPD_ERROR("eapd vxWorks lbSocket not created\n");
298 /* Mesage is ours */
299 netMblkClChainFree(mbuf);
301 return TRUE;
304 /* service - error notification - END */
305 static void
306 notify_preauth_error(END_OBJ *end, END_ERR *error, void *spare)
310 /* service - restart - END */
311 static STATUS
312 restart_preauth_svc(void *param, void *spare)
314 return OK;
316 #endif /* BCMWPA2 */
318 #include <private/muxLibP.h>
319 static M_BLK_ID _mblk_(vx_mux_obj_t *muxobj, uint8 *pkt, int len)
321 END_OBJ *end;
322 M_BLK_ID m;
324 /* size requested should fit in our cluster buffer */
325 if (len >= 1900)
327 EAPD_ERROR("packet is too big %d on drvSocket %d\n", len, muxobj->lbSocket);
328 return NULL;
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);
346 else {
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);
351 return m;
354 static int
355 eapd_send(eapd_wksp_t *nwksp, int drvSocket, struct iovec *frags, int nfrags)
357 struct mbuf *mbuf;
358 int i, count;
359 char *buf;
360 STATUS status;
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);
366 return -1;
369 /* Convert iov to mbuf chain */
370 if (nfrags > 1) {
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);
375 return errno;
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);
382 free(buf);
384 else if (nfrags == 1) {
385 mbuf = _mblk_(muxobj, (void *)frags[0].iov_base, frags[0].iov_len);
387 else {
388 EAPD_ERROR("nfrags == 0 error on drvSocket %d\n", drvSocket);
389 return EINVAL;
392 if (!mbuf) {
393 EAPD_ERROR("failed to allocate mblk on drvSocket %d\n", drvSocket);
394 return ERROR;
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);
403 return status;
406 /* Send a canned EAPOL packet */
407 void
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;
412 eap_header_t eap;
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);
423 eap.code = code;
424 eap.id = sta->pae_id;
425 eap.length = eapol.length;
426 eap.type = type;
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);
436 void
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;
451 char dev[16];
452 vx_mux_obj_t *muxobj;
453 struct sockaddr_in addr;
456 if (nwksp == NULL || sock == NULL) {
457 EAPD_ERROR("Wrong arguments...\n");
458 return -1;
461 /* retrieve interface dev name and index */
462 _ifunit_(sock->ifname, dev, &unit);
464 lbport = _get_lbport_(dev, unit, ETHER_TYPE_BRCM);
465 if (lbport == -1) {
466 EAPD_ERROR("%s: can not get a loopback bind port ...\n", sock->ifname);
467 return -1;
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);
473 return -1;
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");
480 return -1;
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;
487 return -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;
498 return -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;
506 return -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;
517 muxobj_free(muxobj);
518 return -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);
528 return 0;
532 eapd_brcm_close(int drvSocket)
534 int ret;
535 vx_mux_obj_t *muxobj;
537 if (drvSocket < 0)
538 return -1;
540 muxobj = muxobj_find(drvSocket);
541 if (muxobj) {
542 ret = muxUnbind((void *)muxobj->pCookie, ETHER_TYPE_BRCM, recv_brcm_msg);
543 if (ret) {
544 EAPD_ERROR("brcm close failed 0x%x, drvSocket %d muxsocket %08x\n",
545 errno, drvSocket, (int)muxobj->pCookie);
547 muxobj_free(muxobj);
549 else {
550 EAPD_ERROR("muxobj not found drvSocket %d\n", drvSocket);
553 /* close lbsocket */
554 close(drvSocket);
556 return 0;
559 #ifdef BCMWPA2
561 eapd_preauth_open(eapd_wksp_t *nwksp, eapd_preauth_socket_t *sock)
563 int unit, lbport, reuse = 1;
564 char dev[16];
565 vx_mux_obj_t *muxobj;
566 struct sockaddr_in addr;
569 if (nwksp == NULL || sock == NULL) {
570 EAPD_ERROR("Wrong arguments...\n");
571 return -1;
574 /* retrieve interface dev name and index */
575 _ifunit_(sock->ifname, dev, &unit);
577 lbport = _get_lbport_(dev, unit, ETHER_TYPE_802_1X_PREAUTH);
578 if (lbport == -1) {
579 EAPD_ERROR("%s: can not get a loopback bind port ...\n", sock->ifname);
580 return -1;
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);
586 return -1;
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");
593 return -1;
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;
600 return -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;
611 return -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;
619 return -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;
630 muxobj_free(muxobj);
631 return -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);
641 return 0;
645 eapd_preauth_close(int drvSocket)
647 int ret;
648 vx_mux_obj_t *muxobj;
650 if (drvSocket < 0)
651 return -1;
653 muxobj = muxobj_find(drvSocket);
654 if (muxobj) {
655 ret = muxUnbind((void *)muxobj->pCookie, ETHER_TYPE_802_1X_PREAUTH,
656 recv_preauth_msg);
657 if (ret) {
658 EAPD_ERROR("preauth close failed 0x%x, drvSocket %d muxsocket %08x\n",
659 errno, drvSocket, (int)muxobj->pCookie);
661 muxobj_free(muxobj);
663 else {
664 EAPD_ERROR("muxobj not found drvSocket %d\n", drvSocket);
667 /* close lbsocket */
668 close(drvSocket);
670 return 0;
672 #endif /* BCMWPA2 */
675 * Configuration APIs
678 eapd_safe_get_conf(char *outval, int outval_size, char *name)
680 char *val;
682 if (name == NULL || outval == NULL) {
683 if (outval)
684 memset(outval, 0, outval_size);
685 return -1;
688 val = nvram_safe_get(name);
689 if (!strcmp(val, ""))
690 memset(outval, 0, outval_size);
691 else
692 snprintf(outval, outval_size, "%s", val);
693 return 0;
696 int eapd_main(int argc, char* argv[])
698 #ifdef BCMDBG
699 char *dbg;
700 #endif
702 #ifdef BCMDBG
703 /* get eapd_msg_level from nvram */
704 if ((dbg = nvram_get("eapd_dbg"))) {
705 eapd_msg_level = (uint)strtoul(dbg, NULL, 0);
708 #endif
710 EAPD_INFO("EAP Dispatch Start...\n");
712 /* clear muxobjs array */
713 muxobj_init();
715 /* alloc eapd work space */
716 if (!(eapd_nwksp = eapd_wksp_alloc_workspace())) {
717 EAPD_ERROR("Unable to allocate wksp memory. Quitting...\n");
718 return -1;
721 if (eapd_wksp_auto_config(eapd_nwksp)) {
722 EAPD_ERROR("Unable to auto config. Quitting...\n");
723 eapd_wksp_cleanup(eapd_nwksp);
724 return -1;
727 /* establish a handler to handle SIGTERM. */
728 signal(SIGTERM, eapd_hup_hdlr);
730 #ifdef EAPDDUMP
731 signal(SIGUSR1, eapd_dump_hdlr);
732 #endif
734 eapd_wksp_main_loop(eapd_nwksp);
736 EAPD_INFO("EAP Dispatcher Stopped...\n");
738 return 0;
742 void
743 eapdStart(void)
745 int tid = taskNameToId("EAPD");
746 ULONG ticks;
748 if (tid == ERROR) {
749 /* clear eapd wksp initialization flag */
750 eapd_wksp_clear_inited();
752 taskSpawn("EAPD",
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 */
763 ticks = tickGet();
764 do {
765 if (tickGet() - ticks < 3 * sysClkRateGet())
766 taskDelay(sysClkRateGet());
767 else {
768 printf("Unable to wait EAPD initialization finished!.\n");
769 return;
771 } while (taskNameToId("EAPD") != ERROR && !eapd_wksp_is_inited());
773 else
774 printf("EAPD task is already running.\n");
777 void
778 eapdStop(void)
780 int tid = taskNameToId("EAPD");
782 if (tid != ERROR) {
783 ULONG ticks;
785 kill(tid, SIGTERM);
787 /* wait till the task is dead */
788 ticks = tickGet();
789 do {
790 if (tickGet() - ticks < 3 * sysClkRateGet())
791 taskDelay(sysClkRateGet());
792 else {
793 printf("Unable to kill EAPD task!.\n");
794 return;
797 while (taskNameToId("EAPD") != ERROR);
798 printf("EAPD task killed.\n");
800 else
801 printf("EAPD task is not running.\n");