This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 6830e297c dhcpd: Supports kernel mode compilation
6830e297c is described below

commit 6830e297cf0bcb5730b3a4b87b64c01027ed2bc3
Author: zhangshuai39 <[email protected]>
AuthorDate: Thu Aug 7 14:33:52 2025 +0800

    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 <[email protected]>
---
 examples/dhcpd/CMakeLists.txt |  36 +++++-----
 examples/dhcpd/Makefile       |  14 +++-
 examples/dhcpd/dhcpd_daemon.c |   8 ++-
 netutils/dhcpd/dhcpd.c        | 150 +++++++++++++++++++++++++++---------------
 4 files changed, 133 insertions(+), 75 deletions(-)

diff --git a/examples/dhcpd/CMakeLists.txt b/examples/dhcpd/CMakeLists.txt
index b59cb5485..5b2ba7cd2 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 84ce2efc4..6c6ab3ba8 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 5b8f52186..b4f16e787 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 367dda526..558991c22 100644
--- a/netutils/dhcpd/dhcpd.c
+++ b/netutils/dhcpd/dhcpd.c
@@ -47,6 +47,7 @@
 
 #include <sys/socket.h>
 #include <sys/ioctl.h>
+#include <sys/wait.h>
 
 #include <inttypes.h>
 #include <sched.h>
@@ -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

Reply via email to