diff --git a/examples/dhcpd/CMakeLists.txt b/examples/dhcpd/CMakeLists.txt index b59cb548511..5b2ba7cd239 100644 --- a/examples/dhcpd/CMakeLists.txt +++ b/examples/dhcpd/CMakeLists.txt @@ -30,23 +30,27 @@ if(CONFIG_EXAMPLES_DHCPD) STACKSIZE ${CONFIG_DEFAULT_TASK_STACKSIZE}) - nuttx_add_application( - NAME - dhcpd_start - SRCS - dhcpd_start.c - dhcpd_daemon.c - STACKSIZE - ${CONFIG_DEFAULT_TASK_STACKSIZE}) + if(NOT CONFIG_BUILD_KERNEL) + nuttx_add_application( + NAME + dhcpd_start + SRCS + dhcpd_start.c + dhcpd_daemon.c + STACKSIZE + ${CONFIG_DEFAULT_TASK_STACKSIZE}) + endif() - nuttx_add_application( - NAME - dhcpd_stop - SRCS - dhcpd_stop.c - dhcpd_daemon.c - STACKSIZE - ${CONFIG_DEFAULT_TASK_STACKSIZE}) + if(CONFIG_SCHED_WAITPID) + nuttx_add_application( + NAME + dhcpd_stop + SRCS + dhcpd_stop.c + dhcpd_daemon.c + STACKSIZE + ${CONFIG_DEFAULT_TASK_STACKSIZE}) + endif() add_definitions(-DCONFIG_NETUTILS_DHCPD_HOST=1 -DHAVE_SO_REUSEADDR=1 -DHAVE_SO_BROADCAST=1) diff --git a/examples/dhcpd/Makefile b/examples/dhcpd/Makefile index 84ce2efc4f0..6c6ab3ba849 100644 --- a/examples/dhcpd/Makefile +++ b/examples/dhcpd/Makefile @@ -26,13 +26,23 @@ include $(APPDIR)/Make.defs CSRCS = dhcpd_daemon.c -MAINSRC = dhcpd_start.c dhcpd_stop.c target.c +MAINSRC = target.c # DHCPD built-in application info -PROGNAME = dhcpd_start dhcpd_stop dhcpd +PROGNAME = dhcpd PRIORITY = SCHED_PRIORITY_DEFAULT STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE) MODULE = $(CONFIG_EXAMPLES_DHCPD) +ifneq ($(CONFIG_BUILD_KERNEL),y) +MAINSRC += dhcpd_start.c +PROGNAME += dhcpd_start +endif + +ifeq ($(CONFIG_SCHED_WAITPID),y) +MAINSRC += dhcpd_stop.c +PROGNAME += dhcpd_stop +endif + include $(APPDIR)/Application.mk diff --git a/examples/dhcpd/dhcpd_daemon.c b/examples/dhcpd/dhcpd_daemon.c index 5b8f521862b..b4f16e78742 100644 --- a/examples/dhcpd/dhcpd_daemon.c +++ b/examples/dhcpd/dhcpd_daemon.c @@ -128,10 +128,12 @@ int dhcpd_daemon(int argc, FAR char *argv[], bool daemon) /* Then start the dhcpd */ - if (daemon) +#ifndef CONFIG_BUILD_KERNEL + if (!daemon) { - return dhcpd_run(devname); + return dhcpd_start(devname); } +#endif - return dhcpd_start(devname); + return dhcpd_run(devname); } diff --git a/netutils/dhcpd/dhcpd.c b/netutils/dhcpd/dhcpd.c index 367dda5265d..558991c227c 100644 --- a/netutils/dhcpd/dhcpd.c +++ b/netutils/dhcpd/dhcpd.c @@ -47,6 +47,7 @@ #include #include +#include #include #include @@ -276,8 +277,6 @@ struct dhcpd_state_s struct dhcpd_daemon_s { uint8_t ds_state; /* See enum dhcpd_daemon_e */ - sem_t ds_lock; /* Used to protect the whole structure */ - sem_t ds_sync; /* Used to synchronize start and stop events */ pid_t ds_pid; /* Task ID of the DHCPD daemon */ FAR struct dhcpd_state_s *ds_data; /* DHCPD daemon data */ }; @@ -314,8 +313,6 @@ static const uint8_t g_magiccookie[4] = static struct dhcpd_daemon_s g_dhcpd_daemon = { DHCPD_NOT_RUNNING, - SEM_INITIALIZER(1), - SEM_INITIALIZER(0), -1, NULL }; @@ -1019,7 +1016,7 @@ static int dhcpd_sendpacket(int sockfd, int bbroadcast) #endif /* Create a socket to respond with a packet to the client. We - * cannot re-use the listener socket because it is not bound correctly + * cannot reuse the listener socket because it is not bound correctly */ /* Then send the response to the DHCP client port at that address */ @@ -1407,7 +1404,7 @@ static inline int dhcpd_decline(void) lease = dhcpd_findbymac(g_state.ds_inpacket.chaddr); if (lease) { - /* Disassociate the IP from the MAC, but prevent re-used of this + /* Disassociate the IP from the MAC, but prevent reused of this * address for a period of time. */ @@ -1497,10 +1494,74 @@ static inline int dhcpd_openlistener(FAR const char *interface) * Name: dhcpd_task_run ****************************************************************************/ +#ifndef CONFIG_BUILD_KERNEL static int dhcpd_task_run(int argc, char **argv) { return dhcpd_run(argv[1]); } +#endif + +/**************************************************************************** + * Name: dhcpd_get_pid + * + * Description: + * Use /proc filesystem to get dhcpd process PID + * + * Returned Value: + * PID of dhcpd process on success, -1 on failure + * + ****************************************************************************/ + +#if !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_SCHED_WAITPID) +static pid_t dhcpd_get_pid(void) +{ + pid_t pid = -1; + +#if !defined(CONFIG_BUILD_KERNEL) + pid = g_dhcpd_daemon.ds_pid; +#elif defined(CONFIG_SYSTEM_POPEN) + FAR FILE *fp; + char line[32]; + + fp = popen(("pidof dhcpd"), "r"); + if (fp == NULL) + { + return -errno; + } + + if (fgets(line, sizeof(line), fp) != NULL) + { + pid = atoi(line); + } + + pclose(fp); +#endif + + return pid; +} +#endif + +/**************************************************************************** + * Name: dhcpd_signal_handler + * + * Description: + * Signal handler for CONFIG_NETUTILS_DHCPD_SIGWAKEUP + * This function allows dhcpd_stop to terminate dhcpd daemon + * + * Input Parameters: + * signo - Signal number + * info - Signal information + * ctx - Signal context + * + ****************************************************************************/ + +static void +dhcpd_signal_handler(int signo, FAR siginfo_t *info, FAR void *ctx) +{ + /* Set global flag to indicate stop request */ + + g_dhcpd_daemon.ds_state = DHCPD_STOP_REQUESTED; +} /**************************************************************************** * Public Functions @@ -1512,7 +1573,8 @@ static int dhcpd_task_run(int argc, char **argv) int dhcpd_run(FAR const char *interface) { - int sockfd; + struct sigaction act; + int sockfd = -1; int nbytes; ninfo("Started\n"); @@ -1538,15 +1600,19 @@ int dhcpd_run(FAR const char *interface) g_dhcpd_daemon.ds_pid = getpid(); + /* Install signal handler for CONFIG_NETUTILS_DHCPD_SIGWAKEUP */ + + memset(&act, 0, sizeof(act)); + act.sa_sigaction = dhcpd_signal_handler; + act.sa_flags = SA_SIGINFO; + sigaction(CONFIG_NETUTILS_DHCPD_SIGWAKEUP, &act, NULL); + /* Indicate that we have started */ g_dhcpd_daemon.ds_state = DHCPD_RUNNING; - sem_post(&g_dhcpd_daemon.ds_sync); - /* Now loop indefinitely, reading packets from the DHCP server socket */ - sockfd = -1; while (g_dhcpd_daemon.ds_state != DHCPD_STOP_REQUESTED) { /* Create a socket to listen for requests from DHCP clients */ @@ -1631,7 +1697,6 @@ int dhcpd_run(FAR const char *interface) g_dhcpd_daemon.ds_data = NULL; g_dhcpd_daemon.ds_pid = -1; g_dhcpd_daemon.ds_state = DHCPD_STOPPED; - sem_post(&g_dhcpd_daemon.ds_sync); return OK; } @@ -1648,6 +1713,7 @@ int dhcpd_run(FAR const char *interface) * ****************************************************************************/ +#ifndef CONFIG_BUILD_KERNEL int dhcpd_start(FAR const char *interface) { FAR char *argv[2]; @@ -1658,17 +1724,13 @@ int dhcpd_start(FAR const char *interface) /* Is the DHCPD in a non-running state? */ - sem_wait(&g_dhcpd_daemon.ds_lock); - if (g_dhcpd_daemon.ds_state == DHCPD_NOT_RUNNING || - g_dhcpd_daemon.ds_state == DHCPD_STOPPED) + if (dhcpd_get_pid() < 0) { /* Start the DHCPD daemon */ - g_dhcpd_daemon.ds_state = DHCPD_STARTED; - pid = - task_create("DHCPD daemon", CONFIG_NETUTILS_DHCPD_PRIORITY, - CONFIG_NETUTILS_DHCPD_STACKSIZE, dhcpd_task_run, - argv); + pid = task_create("dhcpd", CONFIG_NETUTILS_DHCPD_PRIORITY, + CONFIG_NETUTILS_DHCPD_STACKSIZE, dhcpd_task_run, + argv); /* Handle failures to start the DHCPD daemon */ @@ -1676,24 +1738,14 @@ int dhcpd_start(FAR const char *interface) { int errval = errno; - g_dhcpd_daemon.ds_state = DHCPD_STOPPED; nerr("ERROR: Failed to start the DHCPD daemon: %d\n", errval); - sem_post(&g_dhcpd_daemon.ds_lock); return -errval; } - - /* Wait for any daemon state change */ - - do - { - sem_wait(&g_dhcpd_daemon.ds_sync); - } - while (g_dhcpd_daemon.ds_state == DHCPD_STARTED); } - sem_post(&g_dhcpd_daemon.ds_lock); return OK; } +#endif /**************************************************************************** * Name: dhcpd_stop @@ -1707,46 +1759,36 @@ int dhcpd_start(FAR const char *interface) * ****************************************************************************/ +#ifdef CONFIG_SCHED_WAITPID int dhcpd_stop(void) { - int ret; + pid_t pid; /* Is the DHCPD in a running state? */ - sem_wait(&g_dhcpd_daemon.ds_lock); - if (g_dhcpd_daemon.ds_state == DHCPD_STARTED || - g_dhcpd_daemon.ds_state == DHCPD_RUNNING) + pid = dhcpd_get_pid(); + if (pid >= 0) { /* Yes.. request that the daemon stop. */ - g_dhcpd_daemon.ds_state = DHCPD_STOP_REQUESTED; - - /* Wait for any daemon state change */ - - do + if (kill(pid, CONFIG_NETUTILS_DHCPD_SIGWAKEUP) < 0) { - /* Signal the DHCPD client */ - - ret = kill(g_dhcpd_daemon.ds_pid, - CONFIG_NETUTILS_DHCPD_SIGWAKEUP); - - if (ret < 0) - { - nerr("ERROR: kill pid %d failed: %d\n", - g_dhcpd_daemon.ds_pid, errno); - break; - } + nerr("ERROR: kill pid %d failed: %d\n", pid, errno); + return -errno; + } - /* Wait for the DHCPD client to respond to the stop request */ + /* Wait for the DHCPD client to respond to the stop request */ - sem_wait(&g_dhcpd_daemon.ds_sync); + if (waitpid(pid, NULL, 0) < 0) + { + nerr("ERROR: waitpid failed: %d\n", errno); + return -errno; } - while (g_dhcpd_daemon.ds_state == DHCPD_STOP_REQUESTED); } - sem_post(&g_dhcpd_daemon.ds_lock); return OK; } +#endif /**************************************************************************** * Name: dhcpd_set_startip