You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ag...@apache.org on 2020/04/03 12:29:31 UTC

[incubator-nuttx-apps] 02/04: wireless/wapi: add save_config/reconnect support

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

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

commit df1d0e73f8cee308dfde71061e1732f2fe5037ea
Author: chao.an <an...@xiaomi.com>
AuthorDate: Fri Apr 3 13:22:28 2020 +0800

    wireless/wapi: add save_config/reconnect support
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 include/wireless/wapi.h         |  31 +++++++++
 wireless/wapi/src/driver_wext.c | 144 ++++++++++++++++++++++++++++++++++++----
 wireless/wapi/src/util.c        |  24 ++++---
 wireless/wapi/src/wapi.c        | 143 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 322 insertions(+), 20 deletions(-)

diff --git a/include/wireless/wapi.h b/include/wireless/wapi.h
index 6407590..af05e2d 100644
--- a/include/wireless/wapi.h
+++ b/include/wireless/wapi.h
@@ -748,6 +748,23 @@ int wpa_driver_wext_set_key_ext(int sockfd, FAR const char *ifname,
                                 size_t key_len);
 
 /****************************************************************************
+ * Name: wpa_driver_wext_get_key_ext
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *   sockfd - Opened network socket
+ *   ifname - Interface name
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wpa_driver_wext_get_key_ext(int sockfd, FAR const char *ifname,
+                                enum wpa_alg_e *alg, FAR char *key,
+                                size_t *req_len);
+
+/****************************************************************************
  * Name: wpa_driver_wext_associate
  *
  * Description:
@@ -776,6 +793,20 @@ int wpa_driver_wext_set_auth_param(int sockfd, FAR const char *ifname,
                                    int idx, uint32_t value);
 
 /****************************************************************************
+ * Name: wpa_driver_wext_get_auth_param
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wpa_driver_wext_get_auth_param(int sockfd, FAR const char *ifname,
+                                   int idx, uint32_t *value);
+
+/****************************************************************************
  * Name: wpa_driver_wext_disconnect
  *
  * Description:
diff --git a/wireless/wapi/src/driver_wext.c b/wireless/wapi/src/driver_wext.c
index 20e2b67..6f473ec 100644
--- a/wireless/wapi/src/driver_wext.c
+++ b/wireless/wapi/src/driver_wext.c
@@ -70,6 +70,76 @@
  ****************************************************************************/
 
 /****************************************************************************
+ * Name: wpa_driver_wext_get_key_ext
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *   sockfd - Opened network socket
+ *   ifname - Interface name
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wpa_driver_wext_get_key_ext(int sockfd, FAR const char *ifname,
+                                enum wpa_alg_e *alg, FAR char *key,
+                                size_t *req_len)
+{
+  struct iw_encode_ext *ext;
+  struct iwreq iwr;
+  int ret;
+
+  ext = malloc(sizeof(*ext) + *req_len);
+  if (ext == NULL)
+    {
+      return -1;
+    }
+
+  memset(&iwr, 0, sizeof(iwr));
+  strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
+
+  iwr.u.encoding.pointer = (caddr_t) ext;
+  iwr.u.encoding.length = sizeof(*ext) + *req_len;
+
+  ret = ioctl(sockfd, SIOCGIWENCODEEXT, (unsigned long)&iwr);
+  if (ret >= 0)
+    {
+      switch (ext->alg)
+        {
+          case IW_ENCODE_ALG_NONE:
+            *alg = WPA_ALG_NONE;
+            break;
+
+          case IW_ENCODE_ALG_WEP:
+            *alg = WPA_ALG_WEP;
+            break;
+
+          case IW_ENCODE_ALG_TKIP:
+            *alg = WPA_ALG_TKIP;
+            break;
+
+          case IW_ENCODE_ALG_CCMP:
+            *alg = WPA_ALG_CCMP;
+            break;
+
+          default:
+            free(ext);
+            return -1;
+        }
+
+     if (key && ext->key_len < *req_len)
+       {
+         memcpy(key, ext->key, ext->key_len);
+         *req_len = ext->key_len;
+       }
+  }
+
+  free(ext);
+  return ret;
+}
+
+/****************************************************************************
  * Name: wpa_driver_wext_set_key_ext
  *
  * Description:
@@ -82,7 +152,7 @@
  *
  ****************************************************************************/
 
-int wpa_driver_wext_set_key_ext(int sockfd,  FAR const char *ifname,
+int wpa_driver_wext_set_key_ext(int sockfd, FAR const char *ifname,
                                 enum wpa_alg_e alg, FAR const char *key,
                                 size_t key_len)
 {
@@ -208,16 +278,21 @@ int wpa_driver_wext_associate(FAR struct wpa_wconfig_s *wconfig)
       goto close_socket;
     }
 
-  ret = wpa_driver_wext_set_key_ext(sockfd, wconfig->ifname, wconfig->alg,
-                                    wconfig->passphrase, wconfig->phraselen);
-  if (ret < 0)
+  if (wconfig->phraselen > 0)
     {
-      nerr("ERROR: Fail set key: %d\n", ret);
-      ret = -1;
-      goto close_socket;
+      ret = wpa_driver_wext_set_key_ext(sockfd, wconfig->ifname,
+                                        wconfig->alg,
+                                        wconfig->passphrase,
+                                        wconfig->phraselen);
+      if (ret < 0)
+        {
+          nerr("ERROR: Fail set key: %d\n", ret);
+          goto close_socket;
+        }
     }
 
-  ret = wapi_set_essid(sockfd, wconfig->ifname, wconfig->ssid, WAPI_ESSID_ON);
+  ret = wapi_set_essid(sockfd, wconfig->ifname, wconfig->ssid,
+                       WAPI_ESSID_ON);
   if (ret < 0)
     {
       nerr("ERROR: Fail set ssid: %d\n", ret);
@@ -239,8 +314,11 @@ close_socket:
  *
  ****************************************************************************/
 
-int wpa_driver_wext_set_auth_param(int sockfd, FAR const char *ifname,
-                                   int idx, uint32_t value)
+static int wpa_driver_wext_process_auth_param(int sockfd,
+                                              FAR const char *ifname,
+                                              int idx,
+                                              uint32_t *value,
+                                              bool set)
 {
   struct iwreq iwr;
   int errcode;
@@ -251,9 +329,10 @@ int wpa_driver_wext_set_auth_param(int sockfd, FAR const char *ifname,
   memset(&iwr, 0, sizeof(iwr));
   strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
   iwr.u.param.flags = idx & IW_AUTH_INDEX;
-  iwr.u.param.value = value;
+  iwr.u.param.value = set ? *value : 0;
 
-  if (ioctl(sockfd, SIOCSIWAUTH, (unsigned long)&iwr) < 0)
+  if (ioctl(sockfd, set ? SIOCSIWAUTH : SIOCGIWAUTH,
+            (unsigned long)&iwr) < 0)
     {
       errcode = errno;
       if (errcode != EOPNOTSUPP)
@@ -265,10 +344,51 @@ int wpa_driver_wext_set_auth_param(int sockfd, FAR const char *ifname,
       ret = errcode == EOPNOTSUPP ? -2 : -1;
     }
 
+  if (ret == 0 && !set)
+    {
+      *value = iwr.u.param.value;
+    }
+
   return ret;
 }
 
 /****************************************************************************
+ * Name: wpa_driver_wext_set_auth_param
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wpa_driver_wext_set_auth_param(int sockfd, FAR const char *ifname,
+                                   int idx, uint32_t value)
+{
+  return wpa_driver_wext_process_auth_param(sockfd, ifname,
+                                            idx, &value, true);
+}
+
+/****************************************************************************
+ * Name: wpa_driver_wext_get_auth_param
+ *
+ * Description:
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wpa_driver_wext_get_auth_param(int sockfd, FAR const char *ifname,
+                                   int idx, uint32_t *value)
+{
+  return wpa_driver_wext_process_auth_param(sockfd, ifname,
+                                            idx, value, false);
+}
+
+/****************************************************************************
  * Name: wpa_driver_wext_disconnect
  *
  * Description:
diff --git a/wireless/wapi/src/util.c b/wireless/wapi/src/util.c
index 7b821ef..2a51257 100644
--- a/wireless/wapi/src/util.c
+++ b/wireless/wapi/src/util.c
@@ -63,6 +63,12 @@
 #define WAPI_IOCTL_COMMAND_NAMEBUFSIZ 24
 
 /****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+static char g_ioctl_command_namebuf[WAPI_IOCTL_COMMAND_NAMEBUFSIZ];
+
+/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
@@ -135,7 +141,15 @@ static bool wapi_json_update(FAR cJSON *root,
         }
       else
         {
-          if (!strncmp(value, obj->valuestring, strlen(obj->valuestring)))
+          int len = strlen(obj->valuestring);
+          if (len > 0)
+            {
+              if (!strncmp(value, obj->valuestring, len))
+                {
+                  return false;
+                }
+            }
+          else if (len == 0 && value == NULL)
             {
               return false;
             }
@@ -159,12 +173,6 @@ static bool wapi_json_update(FAR cJSON *root,
  * Public Functions
  ****************************************************************************/
 
-static char g_ioctl_command_namebuf[WAPI_IOCTL_COMMAND_NAMEBUFSIZ];
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
 /****************************************************************************
  * Name: wapi_make_socket
  *
@@ -377,7 +385,7 @@ FAR void *wapi_load_config(FAR const char *ifname,
 
   conf->ifname     = ifname;
   conf->ssidlen    = strlen(conf->ssid);
-  conf->phraselen  = strlen(conf->passphrase);
+  conf->phraselen  = conf->passphrase ? strlen(conf->passphrase) : 0;
 
   return root;
 
diff --git a/wireless/wapi/src/wapi.c b/wireless/wapi/src/wapi.c
index e8a4577..eb7ebc7 100644
--- a/wireless/wapi/src/wapi.c
+++ b/wireless/wapi/src/wapi.c
@@ -47,6 +47,8 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include "netutils/netlib.h"
+
 #include "wireless/wapi.h"
 #include "util.h"
 
@@ -91,6 +93,10 @@ static int wapi_bitrate_cmd      (int sock, int argc, FAR char **argv);
 static int wapi_txpower_cmd      (int sock, int argc, FAR char **argv);
 static int wapi_scan_results_cmd (int sock, int argc, FAR char **argv);
 static int wapi_scan_cmd         (int sock, int argc, FAR char **argv);
+#ifdef CONFIG_WIRELESS_WAPI_INITCONF
+static int wapi_reconnect_cmd    (int sock, int argc, FAR char **argv);
+static int wapi_save_config_cmd  (int sock, int argc, FAR char **argv);
+#endif
 
 /****************************************************************************
  * Private Data
@@ -112,6 +118,10 @@ static const struct wapi_command_s g_wapi_commands[] =
   {"ap",           2, 2, wapi_ap_cmd},
   {"bitrate",      3, 3, wapi_bitrate_cmd},
   {"txpower",      3, 3, wapi_txpower_cmd},
+#ifdef CONFIG_WIRELESS_WAPI_INITCONF
+  {"reconnect",    1, 1, wapi_reconnect_cmd},
+  {"save_config",  1, 1, wapi_save_config_cmd},
+#endif
 };
 
 /****************************************************************************
@@ -739,6 +749,135 @@ static int wapi_scan_cmd(int sock, int argc, FAR char **argv)
   return wapi_scan_results_cmd(sock, 1, argv);
 }
 
+#ifdef CONFIG_WIRELESS_WAPI_INITCONF
+
+/****************************************************************************
+ * Name: wapi_reconnect_cmd
+ *
+ * Description:
+ *   Reconnect the AP in the range using given ifname interface.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static int wapi_reconnect_cmd(int sock, int argc, FAR char **argv)
+{
+  struct wpa_wconfig_s conf;
+  FAR void *load;
+  int ret;
+
+  load = wapi_load_config(argv[0], NULL, &conf);
+  if (load == NULL)
+    {
+      return -1;
+    }
+
+  ret = wpa_driver_wext_associate(&conf);
+
+  wapi_unload_config(load);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: wapi_save_config_cmd
+ *
+ * Description:
+ *   Scans available APs in the range using given ifname interface.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static int wapi_save_config_cmd(int sock, int argc, FAR char **argv)
+{
+  char essid[WAPI_ESSID_MAX_SIZE + 1];
+  enum wapi_essid_flag_e essid_flag;
+  struct wpa_wconfig_s conf;
+  uint8_t if_flags;
+  uint32_t value;
+  size_t psk_len;
+  char psk[32];
+  int ret;
+
+  ret = netlib_getifstatus(argv[0], &if_flags);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (!IFF_IS_RUNNING(if_flags))
+    {
+      return -1;
+    }
+
+  psk_len = sizeof(psk);
+
+  memset(&conf, 0, sizeof(struct wpa_wconfig_s));
+  ret = wapi_get_mode(sock, argv[0], &conf.sta_mode);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  memset(essid, 0, sizeof(essid));
+  ret = wapi_get_essid(sock, argv[0], essid, &essid_flag);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  conf.ssid = essid;
+  conf.ssidlen = strnlen(essid, sizeof(essid));
+
+  memset(psk, 0, sizeof(psk));
+  ret = wpa_driver_wext_get_key_ext(sock,
+                                    argv[0],
+                                    &conf.alg,
+                                    psk,
+                                    &psk_len);
+  if (ret == 0)
+    {
+      conf.passphrase = psk;
+      conf.phraselen = psk_len;
+    }
+
+  ret = wpa_driver_wext_get_auth_param(sock,
+                                       argv[0],
+                                       IW_AUTH_WPA_VERSION,
+                                       &value);
+  if (ret < 0)
+    {
+      conf.auth_wpa = IW_AUTH_WPA_VERSION_WPA2;
+    }
+  else
+    {
+      conf.auth_wpa = value;
+    }
+
+  ret = wpa_driver_wext_get_auth_param(sock,
+                                       argv[0],
+                                       IW_AUTH_CIPHER_PAIRWISE,
+                                       &value);
+  if (ret < 0)
+    {
+      if (conf.phraselen > 0)
+        conf.cipher_mode = IW_AUTH_CIPHER_CCMP;
+      else
+        conf.cipher_mode = IW_AUTH_CIPHER_NONE;
+    }
+  else
+    {
+      conf.cipher_mode = value;
+    }
+
+  return wapi_save_config(argv[0], NULL, &conf);
+}
+#endif
+
 /****************************************************************************
  * Name: wapi_showusage
  *
@@ -775,6 +914,10 @@ static void wapi_showusage(FAR const char *progname, int exitcode)
                    progname);
   fprintf(stderr, "\t%s txpower      <ifname> <txpower>    <index/flag>\n",
                    progname);
+#ifdef CONFIG_WIRELESS_WAPI_INITCONF
+  fprintf(stderr, "\t%s reconnect    <ifname>\n", progname);
+  fprintf(stderr, "\t%s save_config  <ifname>\n", progname);
+#endif
   fprintf(stderr, "\t%s help\n", progname);
 
   fprintf(stderr, "\nFrequency Flags:\n");