mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
dhcpd: Supports kernel mode compilation
The previous method of terminating the dhcp daemon via a global variable has been removed; instead, the `kill pid` command is used. Also, because the original `dhcp_start` method creates tasks via `task_create`, which is not supported in kernel mode, `dhcp_start` is not compiled in kernel mode. The daemon can be started in kernel mode using `dhcpd xxx &`. Signed-off-by: zhangshuai39 <zhangshuai39@xiaomi.com>
This commit is contained in:
parent
9ad4c3c395
commit
6830e297cf
4 changed files with 135 additions and 77 deletions
|
|
@ -30,23 +30,27 @@ if(CONFIG_EXAMPLES_DHCPD)
|
||||||
STACKSIZE
|
STACKSIZE
|
||||||
${CONFIG_DEFAULT_TASK_STACKSIZE})
|
${CONFIG_DEFAULT_TASK_STACKSIZE})
|
||||||
|
|
||||||
nuttx_add_application(
|
if(NOT CONFIG_BUILD_KERNEL)
|
||||||
NAME
|
nuttx_add_application(
|
||||||
dhcpd_start
|
NAME
|
||||||
SRCS
|
dhcpd_start
|
||||||
dhcpd_start.c
|
SRCS
|
||||||
dhcpd_daemon.c
|
dhcpd_start.c
|
||||||
STACKSIZE
|
dhcpd_daemon.c
|
||||||
${CONFIG_DEFAULT_TASK_STACKSIZE})
|
STACKSIZE
|
||||||
|
${CONFIG_DEFAULT_TASK_STACKSIZE})
|
||||||
|
endif()
|
||||||
|
|
||||||
nuttx_add_application(
|
if(CONFIG_SCHED_WAITPID)
|
||||||
NAME
|
nuttx_add_application(
|
||||||
dhcpd_stop
|
NAME
|
||||||
SRCS
|
dhcpd_stop
|
||||||
dhcpd_stop.c
|
SRCS
|
||||||
dhcpd_daemon.c
|
dhcpd_stop.c
|
||||||
STACKSIZE
|
dhcpd_daemon.c
|
||||||
${CONFIG_DEFAULT_TASK_STACKSIZE})
|
STACKSIZE
|
||||||
|
${CONFIG_DEFAULT_TASK_STACKSIZE})
|
||||||
|
endif()
|
||||||
|
|
||||||
add_definitions(-DCONFIG_NETUTILS_DHCPD_HOST=1 -DHAVE_SO_REUSEADDR=1
|
add_definitions(-DCONFIG_NETUTILS_DHCPD_HOST=1 -DHAVE_SO_REUSEADDR=1
|
||||||
-DHAVE_SO_BROADCAST=1)
|
-DHAVE_SO_BROADCAST=1)
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,23 @@ include $(APPDIR)/Make.defs
|
||||||
|
|
||||||
CSRCS = dhcpd_daemon.c
|
CSRCS = dhcpd_daemon.c
|
||||||
|
|
||||||
MAINSRC = dhcpd_start.c dhcpd_stop.c target.c
|
MAINSRC = target.c
|
||||||
|
|
||||||
# DHCPD built-in application info
|
# DHCPD built-in application info
|
||||||
|
|
||||||
PROGNAME = dhcpd_start dhcpd_stop dhcpd
|
PROGNAME = dhcpd
|
||||||
PRIORITY = SCHED_PRIORITY_DEFAULT
|
PRIORITY = SCHED_PRIORITY_DEFAULT
|
||||||
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
|
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
|
||||||
MODULE = $(CONFIG_EXAMPLES_DHCPD)
|
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
|
include $(APPDIR)/Application.mk
|
||||||
|
|
|
||||||
|
|
@ -128,10 +128,12 @@ int dhcpd_daemon(int argc, FAR char *argv[], bool daemon)
|
||||||
|
|
||||||
/* Then start the dhcpd */
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
|
@ -276,8 +277,6 @@ struct dhcpd_state_s
|
||||||
struct dhcpd_daemon_s
|
struct dhcpd_daemon_s
|
||||||
{
|
{
|
||||||
uint8_t ds_state; /* See enum dhcpd_daemon_e */
|
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 */
|
pid_t ds_pid; /* Task ID of the DHCPD daemon */
|
||||||
FAR struct dhcpd_state_s *ds_data; /* DHCPD daemon data */
|
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 =
|
static struct dhcpd_daemon_s g_dhcpd_daemon =
|
||||||
{
|
{
|
||||||
DHCPD_NOT_RUNNING,
|
DHCPD_NOT_RUNNING,
|
||||||
SEM_INITIALIZER(1),
|
|
||||||
SEM_INITIALIZER(0),
|
|
||||||
-1,
|
-1,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
@ -1019,7 +1016,7 @@ static int dhcpd_sendpacket(int sockfd, int bbroadcast)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create a socket to respond with a packet to the client. We
|
/* 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 */
|
/* 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);
|
lease = dhcpd_findbymac(g_state.ds_inpacket.chaddr);
|
||||||
if (lease)
|
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.
|
* address for a period of time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -1497,10 +1494,74 @@ static inline int dhcpd_openlistener(FAR const char *interface)
|
||||||
* Name: dhcpd_task_run
|
* Name: dhcpd_task_run
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CONFIG_BUILD_KERNEL
|
||||||
static int dhcpd_task_run(int argc, char **argv)
|
static int dhcpd_task_run(int argc, char **argv)
|
||||||
{
|
{
|
||||||
return dhcpd_run(argv[1]);
|
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
|
* Public Functions
|
||||||
|
|
@ -1512,7 +1573,8 @@ static int dhcpd_task_run(int argc, char **argv)
|
||||||
|
|
||||||
int dhcpd_run(FAR const char *interface)
|
int dhcpd_run(FAR const char *interface)
|
||||||
{
|
{
|
||||||
int sockfd;
|
struct sigaction act;
|
||||||
|
int sockfd = -1;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
ninfo("Started\n");
|
ninfo("Started\n");
|
||||||
|
|
@ -1538,15 +1600,19 @@ int dhcpd_run(FAR const char *interface)
|
||||||
|
|
||||||
g_dhcpd_daemon.ds_pid = getpid();
|
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 */
|
/* Indicate that we have started */
|
||||||
|
|
||||||
g_dhcpd_daemon.ds_state = DHCPD_RUNNING;
|
g_dhcpd_daemon.ds_state = DHCPD_RUNNING;
|
||||||
|
|
||||||
sem_post(&g_dhcpd_daemon.ds_sync);
|
|
||||||
|
|
||||||
/* Now loop indefinitely, reading packets from the DHCP server socket */
|
/* Now loop indefinitely, reading packets from the DHCP server socket */
|
||||||
|
|
||||||
sockfd = -1;
|
|
||||||
while (g_dhcpd_daemon.ds_state != DHCPD_STOP_REQUESTED)
|
while (g_dhcpd_daemon.ds_state != DHCPD_STOP_REQUESTED)
|
||||||
{
|
{
|
||||||
/* Create a socket to listen for requests from DHCP clients */
|
/* 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_data = NULL;
|
||||||
g_dhcpd_daemon.ds_pid = -1;
|
g_dhcpd_daemon.ds_pid = -1;
|
||||||
g_dhcpd_daemon.ds_state = DHCPD_STOPPED;
|
g_dhcpd_daemon.ds_state = DHCPD_STOPPED;
|
||||||
sem_post(&g_dhcpd_daemon.ds_sync);
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
@ -1648,6 +1713,7 @@ int dhcpd_run(FAR const char *interface)
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CONFIG_BUILD_KERNEL
|
||||||
int dhcpd_start(FAR const char *interface)
|
int dhcpd_start(FAR const char *interface)
|
||||||
{
|
{
|
||||||
FAR char *argv[2];
|
FAR char *argv[2];
|
||||||
|
|
@ -1658,17 +1724,13 @@ int dhcpd_start(FAR const char *interface)
|
||||||
|
|
||||||
/* Is the DHCPD in a non-running state? */
|
/* Is the DHCPD in a non-running state? */
|
||||||
|
|
||||||
sem_wait(&g_dhcpd_daemon.ds_lock);
|
if (dhcpd_get_pid() < 0)
|
||||||
if (g_dhcpd_daemon.ds_state == DHCPD_NOT_RUNNING ||
|
|
||||||
g_dhcpd_daemon.ds_state == DHCPD_STOPPED)
|
|
||||||
{
|
{
|
||||||
/* Start the DHCPD daemon */
|
/* Start the DHCPD daemon */
|
||||||
|
|
||||||
g_dhcpd_daemon.ds_state = DHCPD_STARTED;
|
pid = task_create("dhcpd", CONFIG_NETUTILS_DHCPD_PRIORITY,
|
||||||
pid =
|
CONFIG_NETUTILS_DHCPD_STACKSIZE, dhcpd_task_run,
|
||||||
task_create("DHCPD daemon", CONFIG_NETUTILS_DHCPD_PRIORITY,
|
argv);
|
||||||
CONFIG_NETUTILS_DHCPD_STACKSIZE, dhcpd_task_run,
|
|
||||||
argv);
|
|
||||||
|
|
||||||
/* Handle failures to start the DHCPD daemon */
|
/* Handle failures to start the DHCPD daemon */
|
||||||
|
|
||||||
|
|
@ -1676,24 +1738,14 @@ int dhcpd_start(FAR const char *interface)
|
||||||
{
|
{
|
||||||
int errval = errno;
|
int errval = errno;
|
||||||
|
|
||||||
g_dhcpd_daemon.ds_state = DHCPD_STOPPED;
|
|
||||||
nerr("ERROR: Failed to start the DHCPD daemon: %d\n", errval);
|
nerr("ERROR: Failed to start the DHCPD daemon: %d\n", errval);
|
||||||
sem_post(&g_dhcpd_daemon.ds_lock);
|
|
||||||
return -errval;
|
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;
|
return OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: dhcpd_stop
|
* Name: dhcpd_stop
|
||||||
|
|
@ -1707,46 +1759,36 @@ int dhcpd_start(FAR const char *interface)
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_WAITPID
|
||||||
int dhcpd_stop(void)
|
int dhcpd_stop(void)
|
||||||
{
|
{
|
||||||
int ret;
|
pid_t pid;
|
||||||
|
|
||||||
/* Is the DHCPD in a running state? */
|
/* Is the DHCPD in a running state? */
|
||||||
|
|
||||||
sem_wait(&g_dhcpd_daemon.ds_lock);
|
pid = dhcpd_get_pid();
|
||||||
if (g_dhcpd_daemon.ds_state == DHCPD_STARTED ||
|
if (pid >= 0)
|
||||||
g_dhcpd_daemon.ds_state == DHCPD_RUNNING)
|
|
||||||
{
|
{
|
||||||
/* Yes.. request that the daemon stop. */
|
/* Yes.. request that the daemon stop. */
|
||||||
|
|
||||||
g_dhcpd_daemon.ds_state = DHCPD_STOP_REQUESTED;
|
if (kill(pid, CONFIG_NETUTILS_DHCPD_SIGWAKEUP) < 0)
|
||||||
|
|
||||||
/* Wait for any daemon state change */
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
/* Signal the DHCPD client */
|
nerr("ERROR: kill pid %d failed: %d\n", pid, errno);
|
||||||
|
return -errno;
|
||||||
ret = kill(g_dhcpd_daemon.ds_pid,
|
}
|
||||||
CONFIG_NETUTILS_DHCPD_SIGWAKEUP);
|
|
||||||
|
/* Wait for the DHCPD client to respond to the stop request */
|
||||||
if (ret < 0)
|
|
||||||
{
|
if (waitpid(pid, NULL, 0) < 0)
|
||||||
nerr("ERROR: kill pid %d failed: %d\n",
|
{
|
||||||
g_dhcpd_daemon.ds_pid, errno);
|
nerr("ERROR: waitpid failed: %d\n", errno);
|
||||||
break;
|
return -errno;
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for the DHCPD client to respond to the stop request */
|
|
||||||
|
|
||||||
sem_wait(&g_dhcpd_daemon.ds_sync);
|
|
||||||
}
|
}
|
||||||
while (g_dhcpd_daemon.ds_state == DHCPD_STOP_REQUESTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sem_post(&g_dhcpd_daemon.ds_lock);
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: dhcpd_set_startip
|
* Name: dhcpd_set_startip
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue