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 6c50a3f9f system/wifibridge: keep the configuration across resets.
6c50a3f9f is described below

commit 6c50a3f9f7a466f261309fae2d2df180823e9fd5
Author: Daniel P. Carvalho <[email protected]>
AuthorDate: Sun Oct 18 16:33:16 2026 -0300

    system/wifibridge: keep the configuration across resets.
    
    Add the save and clear commands, and the wifibridge_save(),
    wifibridge_load() and wifibridge_clear() functions behind them, enabled by
    NETUTILS_WIFIBRIDGE_PERSIST.  save keeps the SSID, the passphrase, the
    channel, the security, the address and the DHCP server option; start then
    uses them instead of the defaults of the configuration, and the options of
    start win for that run only.  clear forgets them.
    
    The configuration is a record with a magic number, a version and a CRC-32,
    written at the start of NETUTILS_WIFIBRIDGE_STORAGE: a file of a file
    system mounted at boot, or a block device such as the MTD of a few pages
    of flash.  A record that is missing or damaged is ignored and the
    defaults are used.  The passphrase is stored as is.
    
    The parameters of the SoftAP are now checked in one place, also by start
    before anything is changed.
    
    Tested on an EV49N51A with the MTD of two pages of the program flash
    (PIC32MZ_PROGMEM, FTL and BCH, as /dev/mtdblock1): start with an empty
    storage uses the defaults; after save -s Persist -p persist1234 -c 11
    -a 10.0.0.7 -d, start comes up with that SSID, channel, address and the
    DHCP server, also after a reset; the options of start override it for one
    run; clear brings the defaults back; save refuses a short passphrase.
    
    Assisted-by: Claude Code:claude-sonnet-5-5
    Signed-off-by: Daniel P. Carvalho <[email protected]>
---
 include/netutils/wifibridge.h       |  67 +++++++++-
 netutils/wifibridge/Kconfig         |  23 ++++
 netutils/wifibridge/wifibridge.c    | 260 ++++++++++++++++++++++++++++++++++--
 system/wifibridge/wifibridge_main.c | 128 ++++++++++++++++--
 4 files changed, 453 insertions(+), 25 deletions(-)

diff --git a/include/netutils/wifibridge.h b/include/netutils/wifibridge.h
index f0b96996b..d6fa58e6e 100644
--- a/include/netutils/wifibridge.h
+++ b/include/netutils/wifibridge.h
@@ -33,6 +33,13 @@
 #include <stdint.h>
 #include <netinet/in.h>
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define WIFIBRIDGE_SSID_MAXLEN        32
+#define WIFIBRIDGE_PASSPHRASE_MAXLEN  63
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -52,8 +59,12 @@ struct wifibridge_config_s
   FAR const char *bridge;     /* Bridge interface to create, e.g. "br0" */
   FAR const char *ethif;      /* Ethernet port, e.g. "eth0" */
   FAR const char *wlanif;     /* Wi-Fi port, e.g. "wlan0" */
-  FAR const char *ssid;       /* SoftAP SSID */
-  FAR const char *passphrase; /* SoftAP passphrase, 8..63 characters */
+
+  /* SoftAP SSID and passphrase (8..63 characters) */
+
+  char ssid[WIFIBRIDGE_SSID_MAXLEN + 1];
+  char passphrase[WIFIBRIDGE_PASSPHRASE_MAXLEN + 1];
+
   uint8_t channel;            /* 2.4 GHz channel, 1..13 */
   enum wifibridge_security_e security;
   in_addr_t ipaddr;           /* Bridge address, network byte order */
@@ -66,8 +77,11 @@ struct wifibridge_status_s
   bool exists;                /* The bridge interface exists */
   bool eth_up;                /* The Ethernet port is up */
   bool wlan_up;               /* The Wi-Fi port is up */
-  char ssid[33];              /* SSID the Wi-Fi port is set to */
   struct in_addr ipaddr;      /* Bridge address */
+
+  /* SSID the Wi-Fi port is set to */
+
+  char ssid[WIFIBRIDGE_SSID_MAXLEN + 1];
 };
 
 /****************************************************************************
@@ -125,6 +139,53 @@ int wifibridge_stop(FAR const struct wifibridge_config_s 
*config);
 int wifibridge_status(FAR const struct wifibridge_config_s *config,
                       FAR struct wifibridge_status_s *status);
 
+#ifdef CONFIG_NETUTILS_WIFIBRIDGE_PERSIST
+
+/****************************************************************************
+ * Name: wifibridge_save
+ *
+ * Description:
+ *   Keep the SSID, passphrase, channel, security, address and DHCP server
+ *   option of the configuration in the storage
+ *   (CONFIG_NETUTILS_WIFIBRIDGE_STORAGE), to survive a reset.
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int wifibridge_save(FAR const struct wifibridge_config_s *config);
+
+/****************************************************************************
+ * Name: wifibridge_load
+ *
+ * Description:
+ *   Read what wifibridge_save() kept and set the matching fields of the
+ *   configuration.  The other fields of the configuration are left alone.
+ *
+ * Returned Value:
+ *   Zero (OK) on success; -ENOENT if nothing is saved, or another negated
+ *   errno value on failure.
+ *
+ ****************************************************************************/
+
+int wifibridge_load(FAR struct wifibridge_config_s *config);
+
+/****************************************************************************
+ * Name: wifibridge_clear
+ *
+ * Description:
+ *   Forget what wifibridge_save() kept.
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int wifibridge_clear(void);
+
+#endif /* CONFIG_NETUTILS_WIFIBRIDGE_PERSIST */
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/netutils/wifibridge/Kconfig b/netutils/wifibridge/Kconfig
index e7b384605..b319971eb 100644
--- a/netutils/wifibridge/Kconfig
+++ b/netutils/wifibridge/Kconfig
@@ -29,4 +29,27 @@ config NETUTILS_WIFIBRIDGE_DHCPD
                interface.  Leave it unused when another DHCP server is
                reachable through the Ethernet port.
 
+config NETUTILS_WIFIBRIDGE_PERSIST
+       bool "Keep the configuration in non-volatile memory"
+       default n
+       ---help---
+               Allow the library to save the SoftAP configuration (SSID,
+               passphrase, channel, security, address and DHCP server option) 
in
+               a file or in a block device, and to load it again.  The record 
has
+               a CRC and is the only thing in the first bytes of the storage.
+               The passphrase is stored as is.
+
+if NETUTILS_WIFIBRIDGE_PERSIST
+
+config NETUTILS_WIFIBRIDGE_STORAGE
+       string "File or device that keeps the configuration"
+       default "/data/wifibridge.conf"
+       ---help---
+               A file of a file system that is mounted at boot, or a block 
device
+               such as the MTD of a part of the flash (it needs BCH to be 
opened
+               by name).  Writing it also erases the flash that holds it, so it
+               should be a device used for this alone.
+
+endif # NETUTILS_WIFIBRIDGE_PERSIST
+
 endif # NETUTILS_WIFIBRIDGE
diff --git a/netutils/wifibridge/wifibridge.c b/netutils/wifibridge/wifibridge.c
index 4612f47c3..165a8c41e 100644
--- a/netutils/wifibridge/wifibridge.c
+++ b/netutils/wifibridge/wifibridge.c
@@ -29,6 +29,8 @@
 #include <sys/socket.h>
 
 #include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -44,10 +46,70 @@
 #  include "netutils/dhcpd.h"
 #endif
 
+#ifdef CONFIG_NETUTILS_WIFIBRIDGE_PERSIST
+#  include <nuttx/crc32.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define WIFIBRIDGE_SAVED_VERSION  1
+#define WIFIBRIDGE_RECORD_MAGIC   0x42574657  /* 'WFWB' */
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_NETUTILS_WIFIBRIDGE_PERSIST
+
+/* What is written to the storage: a record that is checked before it is
+ * used.
+ */
+
+struct wifibridge_record_s
+{
+  uint32_t magic;                     /* WIFIBRIDGE_RECORD_MAGIC */
+  uint32_t crc;                       /* CRC-32 of the fields below */
+  uint8_t version;                    /* WIFIBRIDGE_SAVED_VERSION */
+  uint8_t channel;                    /* 2.4 GHz channel, 1..13 */
+  uint8_t security;                   /* enum wifibridge_security_e */
+  uint8_t dhcpd;                      /* Run the DHCP server on the bridge */
+  uint32_t ipaddr;                    /* Bridge address, network byte order */
+  char ssid[WIFIBRIDGE_SSID_MAXLEN + 1];
+  char passphrase[WIFIBRIDGE_PASSPHRASE_MAXLEN + 1];
+};
+
+#endif
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: wifibridge_validate
+ *
+ * Description:
+ *   Check the parameters of the SoftAP.
+ *
+ ****************************************************************************/
+
+static int wifibridge_validate(FAR const struct wifibridge_config_s *cfg)
+{
+  size_t ssidlen = strnlen(cfg->ssid, WIFIBRIDGE_SSID_MAXLEN + 1);
+  size_t passlen = strnlen(cfg->passphrase,
+                           WIFIBRIDGE_PASSPHRASE_MAXLEN + 1);
+
+  if (ssidlen < 1 || ssidlen > WIFIBRIDGE_SSID_MAXLEN || passlen < 8 ||
+      passlen > WIFIBRIDGE_PASSPHRASE_MAXLEN ||
+      cfg->channel < 1 || cfg->channel > 13)
+    {
+      return -EINVAL;
+    }
+
+  return OK;
+}
+
 /****************************************************************************
  * Name: wifibridge_setup_softap
  *
@@ -60,15 +122,9 @@
 static int wifibridge_setup_softap(int sock,
                                    FAR const struct wifibridge_config_s *cfg)
 {
-  size_t passlen = strnlen(cfg->passphrase, 64);
   int version;
   int ret;
 
-  if (passlen < 8 || passlen > 63 || cfg->channel < 1 || cfg->channel > 13)
-    {
-      return -EINVAL;
-    }
-
   version = cfg->security == WIFIBRIDGE_SEC_WPA3 ?
             IW_AUTH_WPA_VERSION_WPA3 : IW_AUTH_WPA_VERSION_WPA2;
 
@@ -94,7 +150,8 @@ static int wifibridge_setup_softap(int sock,
     }
 
   ret = wpa_driver_wext_set_key_ext(sock, cfg->wlanif, WPA_ALG_CCMP,
-                                    cfg->passphrase, passlen);
+                                    cfg->passphrase,
+                                    strlen(cfg->passphrase));
   if (ret < 0)
     {
       return ret;
@@ -172,12 +229,17 @@ int wifibridge_start(FAR const struct wifibridge_config_s 
*config)
   int ret;
 
   if (config == NULL || config->bridge == NULL || config->ethif == NULL ||
-      config->wlanif == NULL || config->ssid == NULL ||
-      config->passphrase == NULL)
+      config->wlanif == NULL)
     {
       return -EINVAL;
     }
 
+  ret = wifibridge_validate(config);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
   if (if_nametoindex(config->bridge) != 0)
     {
       return -EEXIST;
@@ -346,3 +408,183 @@ int wifibridge_status(FAR const struct 
wifibridge_config_s *config,
   close(sock);
   return OK;
 }
+
+#ifdef CONFIG_NETUTILS_WIFIBRIDGE_PERSIST
+
+/****************************************************************************
+ * Name: wifibridge_record_crc
+ *
+ * Description:
+ *   CRC-32 of the record after the CRC field.
+ *
+ ****************************************************************************/
+
+static uint32_t wifibridge_record_crc(
+                              FAR const struct wifibridge_record_s *record)
+{
+  return crc32((FAR const uint8_t *)&record->version,
+               sizeof(*record) - offsetof(struct wifibridge_record_s,
+                                          version));
+}
+
+/****************************************************************************
+ * Name: wifibridge_record_io
+ *
+ * Description:
+ *   Read or write the record at the start of the storage.
+ *
+ ****************************************************************************/
+
+static int wifibridge_record_io(FAR struct wifibridge_record_s *record,
+                                bool store)
+{
+  ssize_t nbytes;
+  int ret = OK;
+  int fd;
+
+  fd = open(CONFIG_NETUTILS_WIFIBRIDGE_STORAGE,
+            store ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY, 0600);
+  if (fd < 0)
+    {
+      return -errno;
+    }
+
+  if (store)
+    {
+      nbytes = write(fd, record, sizeof(*record));
+      if (nbytes == sizeof(*record))
+        {
+          ret = fsync(fd);
+          if (ret < 0)
+            {
+              ret = -errno;
+            }
+        }
+      else
+        {
+          ret = nbytes < 0 ? -errno : -EIO;
+        }
+    }
+  else
+    {
+      nbytes = read(fd, record, sizeof(*record));
+      if (nbytes != sizeof(*record))
+        {
+          ret = nbytes < 0 ? -errno : -ENOENT;
+        }
+    }
+
+  close(fd);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: wifibridge_save
+ ****************************************************************************/
+
+int wifibridge_save(FAR const struct wifibridge_config_s *config)
+{
+  struct wifibridge_record_s record;
+  int ret;
+
+  if (config == NULL)
+    {
+      return -EINVAL;
+    }
+
+  ret = wifibridge_validate(config);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  memset(&record, 0, sizeof(record));
+  record.magic    = WIFIBRIDGE_RECORD_MAGIC;
+  record.version  = WIFIBRIDGE_SAVED_VERSION;
+  record.channel  = config->channel;
+  record.security = config->security;
+  record.dhcpd    = config->dhcpd;
+  record.ipaddr   = config->ipaddr;
+  strlcpy(record.ssid, config->ssid, sizeof(record.ssid));
+  strlcpy(record.passphrase, config->passphrase,
+          sizeof(record.passphrase));
+  record.crc = wifibridge_record_crc(&record);
+
+  return wifibridge_record_io(&record, true);
+}
+
+/****************************************************************************
+ * Name: wifibridge_load
+ ****************************************************************************/
+
+int wifibridge_load(FAR struct wifibridge_config_s *config)
+{
+  struct wifibridge_config_s old_config;
+  struct wifibridge_record_s record;
+  int ret;
+
+  if (config == NULL)
+    {
+      return -EINVAL;
+    }
+
+  ret = wifibridge_record_io(&record, false);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* A blank or cleared storage has no record */
+
+  if (record.magic != WIFIBRIDGE_RECORD_MAGIC)
+    {
+      return -ENOENT;
+    }
+
+  /* Do not trust the rest: it can be damaged or come from another version */
+
+  if (record.crc != wifibridge_record_crc(&record) ||
+      record.version != WIFIBRIDGE_SAVED_VERSION)
+    {
+      return -EINVAL;
+    }
+
+  /* The configuration keeps its values if the record is not valid */
+
+  old_config = *config;
+
+  memcpy(config->ssid, record.ssid, sizeof(config->ssid));
+  config->ssid[WIFIBRIDGE_SSID_MAXLEN] = '\0';
+  memcpy(config->passphrase, record.passphrase, sizeof(config->passphrase));
+  config->passphrase[WIFIBRIDGE_PASSPHRASE_MAXLEN] = '\0';
+  config->channel  = record.channel;
+  config->security = record.security;
+  config->ipaddr   = record.ipaddr;
+  config->dhcpd    = record.dhcpd != 0;
+
+  ret = wifibridge_validate(config);
+  if (ret < 0)
+    {
+      *config = old_config;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: wifibridge_clear
+ ****************************************************************************/
+
+int wifibridge_clear(void)
+{
+  struct wifibridge_record_s record;
+
+  /* A record that is not one: a storage that is a device has no way to
+   * delete it.
+   */
+
+  memset(&record, 0, sizeof(record));
+  return wifibridge_record_io(&record, true);
+}
+
+#endif /* CONFIG_NETUTILS_WIFIBRIDGE_PERSIST */
diff --git a/system/wifibridge/wifibridge_main.c 
b/system/wifibridge/wifibridge_main.c
index 181d993b1..5c361c248 100644
--- a/system/wifibridge/wifibridge_main.c
+++ b/system/wifibridge/wifibridge_main.c
@@ -44,10 +44,15 @@ static void wifibridge_usage(FAR const char *progname)
 {
   fprintf(stderr, "Usage:\n");
   fprintf(stderr, "  %s start [-s <ssid>] [-p <passphrase>] [-c <channel>]"
-          " [-3] [-a <ipaddr>] [-d]\n", progname);
+          " [-3] [-a <ipaddr>] [-d|-D]\n", progname);
   fprintf(stderr, "  %s stop\n", progname);
   fprintf(stderr, "  %s status\n", progname);
-  fprintf(stderr, "\nstart options:\n");
+#ifdef CONFIG_NETUTILS_WIFIBRIDGE_PERSIST
+  fprintf(stderr, "  %s save [-s <ssid>] [-p <passphrase>] [-c <channel>]"
+          " [-3] [-a <ipaddr>] [-d|-D]\n", progname);
+  fprintf(stderr, "  %s clear\n", progname);
+#endif
+  fprintf(stderr, "\nstart and save options:\n");
   fprintf(stderr, "  -s  SoftAP SSID (default %s)\n",
           CONFIG_SYSTEM_WIFIBRIDGE_SSID);
   fprintf(stderr, "  -p  SoftAP passphrase, 8..63 characters\n");
@@ -56,26 +61,45 @@ static void wifibridge_usage(FAR const char *progname)
   fprintf(stderr, "  -3  WPA3-Personal instead of WPA2-PSK\n");
   fprintf(stderr, "  -a  bridge IPv4 address, netmask 255.255.255.0\n");
   fprintf(stderr, "  -d  run the DHCP server on the bridge\n");
+  fprintf(stderr, "  -D  do not run the DHCP server\n");
+#ifdef CONFIG_NETUTILS_WIFIBRIDGE_PERSIST
+  fprintf(stderr, "\nThe options are applied over the saved configuration,"
+          " if there is one,\nand over the defaults otherwise.  save keeps"
+          " them, start only uses them.\n");
+#endif
 }
 
-static int wifibridge_start_cmd(FAR struct wifibridge_config_s *config,
-                                int argc, FAR char **argv)
+static int wifibridge_parse(FAR struct wifibridge_config_s *config,
+                            int argc, FAR char **argv)
 {
   struct in_addr addr;
   int option;
-  int ret;
 
   optind = 1;
-  while ((option = getopt(argc, argv, "s:p:c:3a:d")) != ERROR)
+  while ((option = getopt(argc, argv, "s:p:c:3a:dD")) != ERROR)
     {
       switch (option)
         {
           case 's':
-            config->ssid = optarg;
+            if (strlen(optarg) > WIFIBRIDGE_SSID_MAXLEN)
+              {
+                fprintf(stderr, "The SSID has more than %d characters\n",
+                        WIFIBRIDGE_SSID_MAXLEN);
+                return ERROR;
+              }
+
+            strlcpy(config->ssid, optarg, sizeof(config->ssid));
             break;
 
           case 'p':
-            config->passphrase = optarg;
+            if (strlen(optarg) > WIFIBRIDGE_PASSPHRASE_MAXLEN)
+              {
+                fprintf(stderr, "The passphrase has more than %d "
+                        "characters\n", WIFIBRIDGE_PASSPHRASE_MAXLEN);
+                return ERROR;
+              }
+
+            strlcpy(config->passphrase, optarg, sizeof(config->passphrase));
             break;
 
           case 'c':
@@ -90,7 +114,7 @@ static int wifibridge_start_cmd(FAR struct 
wifibridge_config_s *config,
             if (inet_pton(AF_INET, optarg, &addr) != 1)
               {
                 fprintf(stderr, "Invalid IPv4 address: %s\n", optarg);
-                return EXIT_FAILURE;
+                return ERROR;
               }
 
             config->ipaddr = addr.s_addr;
@@ -102,14 +126,31 @@ static int wifibridge_start_cmd(FAR struct 
wifibridge_config_s *config,
             break;
 #else
             fprintf(stderr, "The DHCP server is not enabled\n");
-            return EXIT_FAILURE;
+            return ERROR;
 #endif
 
+          case 'D':
+            config->dhcpd = false;
+            break;
+
           default:
-            return EXIT_FAILURE;
+            return ERROR;
         }
     }
 
+  return OK;
+}
+
+static int wifibridge_start_cmd(FAR struct wifibridge_config_s *config,
+                                int argc, FAR char **argv)
+{
+  int ret;
+
+  if (wifibridge_parse(config, argc, argv) < 0)
+    {
+      return EXIT_FAILURE;
+    }
+
   ret = wifibridge_start(config);
   if (ret < 0)
     {
@@ -120,6 +161,42 @@ static int wifibridge_start_cmd(FAR struct 
wifibridge_config_s *config,
   return EXIT_SUCCESS;
 }
 
+#ifdef CONFIG_NETUTILS_WIFIBRIDGE_PERSIST
+static int wifibridge_save_cmd(FAR struct wifibridge_config_s *config,
+                               int argc, FAR char **argv)
+{
+  int ret;
+
+  if (wifibridge_parse(config, argc, argv) < 0)
+    {
+      return EXIT_FAILURE;
+    }
+
+  ret = wifibridge_save(config);
+  if (ret < 0)
+    {
+      fprintf(stderr, "Failed to save the configuration: %d\n", ret);
+      return EXIT_FAILURE;
+    }
+
+  return EXIT_SUCCESS;
+}
+
+static int wifibridge_clear_cmd(void)
+{
+  int ret;
+
+  ret = wifibridge_clear();
+  if (ret < 0 && ret != -ENOENT)
+    {
+      fprintf(stderr, "Failed to clear the configuration: %d\n", ret);
+      return EXIT_FAILURE;
+    }
+
+  return EXIT_SUCCESS;
+}
+#endif
+
 static int
 wifibridge_status_cmd(FAR const struct wifibridge_config_s *config)
 {
@@ -164,8 +241,9 @@ int main(int argc, FAR char *argv[])
   config.bridge     = CONFIG_SYSTEM_WIFIBRIDGE_BRIDGE;
   config.ethif      = CONFIG_SYSTEM_WIFIBRIDGE_ETHIF;
   config.wlanif     = CONFIG_SYSTEM_WIFIBRIDGE_WLANIF;
-  config.ssid       = CONFIG_SYSTEM_WIFIBRIDGE_SSID;
-  config.passphrase = CONFIG_SYSTEM_WIFIBRIDGE_PASSPHRASE;
+  strlcpy(config.ssid, CONFIG_SYSTEM_WIFIBRIDGE_SSID, sizeof(config.ssid));
+  strlcpy(config.passphrase, CONFIG_SYSTEM_WIFIBRIDGE_PASSPHRASE,
+          sizeof(config.passphrase));
   config.channel    = CONFIG_SYSTEM_WIFIBRIDGE_CHANNEL;
   config.security   = WIFIBRIDGE_SEC_WPA2;
   config.ipaddr     = htonl(CONFIG_SYSTEM_WIFIBRIDGE_IPADDR);
@@ -177,6 +255,19 @@ int main(int argc, FAR char *argv[])
       return EXIT_FAILURE;
     }
 
+#ifdef CONFIG_NETUTILS_WIFIBRIDGE_PERSIST
+  /* The saved configuration, if there is one, replaces the defaults */
+
+  if (strcmp(argv[1], "start") == 0 || strcmp(argv[1], "save") == 0)
+    {
+      ret = wifibridge_load(&config);
+      if (ret < 0 && ret != -ENOENT)
+        {
+          fprintf(stderr, "Ignoring the saved configuration: %d\n", ret);
+        }
+    }
+#endif
+
   if (strcmp(argv[1], "start") == 0)
     {
       return wifibridge_start_cmd(&config, argc - 1, argv + 1);
@@ -197,6 +288,17 @@ int main(int argc, FAR char *argv[])
       return wifibridge_status_cmd(&config);
     }
 
+#ifdef CONFIG_NETUTILS_WIFIBRIDGE_PERSIST
+  else if (strcmp(argv[1], "save") == 0)
+    {
+      return wifibridge_save_cmd(&config, argc - 1, argv + 1);
+    }
+  else if (strcmp(argv[1], "clear") == 0)
+    {
+      return wifibridge_clear_cmd();
+    }
+#endif
+
   wifibridge_usage(argv[0]);
   return EXIT_FAILURE;
 }

Reply via email to