NET_SOCK_* is defined by nuttx/net/netconfig.h and then can be shared Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
522 lines
12 KiB
C
522 lines
12 KiB
C
/****************************************************************************
|
|
* apps/wireless/wapi/src/util.c
|
|
*
|
|
* Copyright (C) 2011, 2017Gregory Nutt. All rights reserved.
|
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
*
|
|
* Adapted for NuttX from WAPI:
|
|
*
|
|
* Copyright (c) 2010, Volkan YAZICI <volkan.yazici@gmail.com>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* - Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <ctype.h>
|
|
#include <netinet/ether.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <nuttx/net/netconfig.h>
|
|
|
|
#include "wireless/wapi.h"
|
|
#include "util.h"
|
|
|
|
#ifdef CONFIG_WIRELESS_WAPI_INITCONF
|
|
#include "netutils/cJSON.h"
|
|
#endif /* CONFIG_WIRELESS_WAPI_INITCONF */
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/* Size of the command buffer */
|
|
|
|
#define WAPI_IOCTL_COMMAND_NAMEBUFSIZ 24
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
static char g_ioctl_command_namebuf[WAPI_IOCTL_COMMAND_NAMEBUFSIZ];
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_WIRELESS_WAPI_INITCONF
|
|
static FAR void *wapi_json_load(FAR const char *confname)
|
|
{
|
|
FAR cJSON *root = NULL;
|
|
struct stat sb;
|
|
FAR char *buf;
|
|
int fd = -1;
|
|
|
|
if (stat(confname, &sb) < 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
buf = malloc(sb.st_size);
|
|
if (!buf)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
fd = open(confname, O_RDONLY);
|
|
if (fd < 0)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
if (read(fd, buf, sb.st_size) != sb.st_size)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
root = cJSON_Parse(buf);
|
|
|
|
errout:
|
|
if (buf)
|
|
{
|
|
free(buf);
|
|
}
|
|
|
|
if (fd > 0)
|
|
{
|
|
close(fd);
|
|
}
|
|
|
|
return root;
|
|
}
|
|
|
|
static bool wapi_json_update(FAR cJSON *root,
|
|
FAR const char *key,
|
|
FAR void *value,
|
|
bool integer)
|
|
{
|
|
intptr_t intval = (intptr_t)value;
|
|
FAR cJSON *item;
|
|
FAR cJSON *obj;
|
|
|
|
obj = cJSON_GetObjectItem(root, key);
|
|
if (obj)
|
|
{
|
|
if (integer)
|
|
{
|
|
if (intval == obj->valueint)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
item = cJSON_CreateNumber(intval);
|
|
}
|
|
else
|
|
{
|
|
int len = strlen(obj->valuestring);
|
|
if (len > 0)
|
|
{
|
|
if (!strncmp(value, obj->valuestring, len))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (len == 0 && value == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
item = cJSON_CreateString(value);
|
|
}
|
|
|
|
cJSON_ReplaceItemInObject(root, key, item);
|
|
}
|
|
else
|
|
{
|
|
integer ? cJSON_AddNumberToObject(root, key, intval) :
|
|
cJSON_AddStringToObject(root, key, value);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#endif /* CONFIG_WIRELESS_WAPI_INITCONF */
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: wapi_make_socket
|
|
*
|
|
* Description:
|
|
* Creates an AF_INET socket to be used in ioctl() calls.
|
|
*
|
|
* Returned Value:
|
|
* Non-negative on success.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int wapi_make_socket(void)
|
|
{
|
|
return socket(NET_SOCK_FAMILY, NET_SOCK_TYPE, NET_SOCK_PROTOCOL);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: wapi_ioctl_command_name
|
|
*
|
|
* Description:
|
|
* Return name string for IOCTL command
|
|
*
|
|
* Returned Value:
|
|
* Name string for IOCTL command
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR const char *wapi_ioctl_command_name(int cmd)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case SIOCADDRT:
|
|
return "SIOCADDRT";
|
|
|
|
case SIOCDELRT:
|
|
return "SIOCDELRT";
|
|
|
|
case SIOCGIFADDR:
|
|
return "SIOCGIFADDR";
|
|
|
|
case SIOCGIWAP:
|
|
return "SIOCGIWAP";
|
|
|
|
case SIOCGIWESSID:
|
|
return "SIOCGIWESSID";
|
|
|
|
case SIOCGIWFREQ:
|
|
return "SIOCGIWFREQ";
|
|
|
|
case SIOCGIWMODE:
|
|
return "SIOCGIWMODE";
|
|
|
|
case SIOCGIWRANGE:
|
|
return "SIOCGIWRANGE";
|
|
|
|
case SIOCGIWRATE:
|
|
return "SIOCGIWRATE";
|
|
|
|
case SIOCGIWSCAN:
|
|
return "SIOCGIWSCAN";
|
|
|
|
case SIOCGIWTXPOW:
|
|
return "SIOCGIWTXPOW";
|
|
|
|
case SIOCSIFADDR:
|
|
return "SIOCSIFADDR";
|
|
|
|
case SIOCSIWAP:
|
|
return "SIOCSIWAP";
|
|
|
|
case SIOCSIWESSID:
|
|
return "SIOCSIWESSID";
|
|
|
|
case SIOCSIWFREQ:
|
|
return "SIOCSIWFREQ";
|
|
|
|
case SIOCSIWMODE:
|
|
return "SIOCSIWMODE";
|
|
|
|
case SIOCSIWRATE:
|
|
return "SIOCSIWRATE";
|
|
|
|
case SIOCSIWSCAN:
|
|
return "SIOCSIWSCAN";
|
|
|
|
case SIOCSIWTXPOW:
|
|
return "SIOCSIWTXPOW";
|
|
|
|
default:
|
|
snprintf(g_ioctl_command_namebuf, WAPI_IOCTL_COMMAND_NAMEBUFSIZ,
|
|
"0x%x", cmd);
|
|
return g_ioctl_command_namebuf;
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_WIRELESS_WAPI_INITCONF
|
|
|
|
/****************************************************************************
|
|
* Name: wapi_unload_config
|
|
*
|
|
* Description:
|
|
*
|
|
* Input Parameters:
|
|
* load - Config resource handler, allocate by wapi_load_config()
|
|
*
|
|
* Returned Value:
|
|
*
|
|
****************************************************************************/
|
|
|
|
void wapi_unload_config(FAR void *load)
|
|
{
|
|
if (load)
|
|
{
|
|
cJSON_Delete(load);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: wapi_load_config
|
|
*
|
|
* Description:
|
|
*
|
|
* Input Parameters:
|
|
*
|
|
* Returned Value:
|
|
* Return a pointer to the hold the config resource, NULL On error.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR void *wapi_load_config(FAR const char *ifname,
|
|
FAR const char *confname,
|
|
FAR struct wpa_wconfig_s *conf)
|
|
{
|
|
FAR struct ether_addr *ap;
|
|
FAR cJSON *ifobj;
|
|
FAR cJSON *root;
|
|
FAR cJSON *obj;
|
|
|
|
if (ifname == NULL ||
|
|
conf == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (confname == NULL)
|
|
{
|
|
confname = CONFIG_WIRELESS_WAPI_CONFIG_PATH;
|
|
}
|
|
|
|
root = wapi_json_load(confname);
|
|
if (!root)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* Set up the network configuration */
|
|
|
|
ifobj = cJSON_GetObjectItem(root, ifname);
|
|
if (!ifobj)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
memset(conf, 0, sizeof(*conf));
|
|
|
|
obj = cJSON_GetObjectItem(ifobj, "mode");
|
|
if (!obj)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
conf->sta_mode = obj->valueint;
|
|
|
|
obj = cJSON_GetObjectItem(ifobj, "auth");
|
|
if (!obj)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
conf->auth_wpa = obj->valueint;
|
|
|
|
obj = cJSON_GetObjectItem(ifobj, "cmode");
|
|
if (!obj)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
conf->cipher_mode = obj->valueint;
|
|
|
|
obj = cJSON_GetObjectItem(ifobj, "alg");
|
|
if (!obj)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
conf->alg = obj->valueint;
|
|
|
|
obj = cJSON_GetObjectItem(ifobj, "ssid");
|
|
if (!obj || !obj->valuestring)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
conf->ssid = (FAR const char *)obj->valuestring;
|
|
|
|
obj = cJSON_GetObjectItem(ifobj, "bssid");
|
|
if (!obj || !obj->valuestring)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
ap = ether_aton(obj->valuestring);
|
|
if (ap != NULL)
|
|
{
|
|
conf->bssid = (FAR const char *)ap->ether_addr_octet;
|
|
}
|
|
|
|
obj = cJSON_GetObjectItem(ifobj, "psk");
|
|
if (!obj || !obj->valuestring)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
conf->passphrase = (FAR const char *)obj->valuestring;
|
|
|
|
conf->ifname = ifname;
|
|
conf->ssidlen = strlen(conf->ssid);
|
|
conf->phraselen = conf->passphrase ? strlen(conf->passphrase) : 0;
|
|
|
|
return root;
|
|
|
|
errout:
|
|
cJSON_Delete(root);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: wapi_save_config
|
|
*
|
|
* Description:
|
|
*
|
|
* Input Parameters:
|
|
*
|
|
* Returned Value:
|
|
*
|
|
****************************************************************************/
|
|
|
|
int wapi_save_config(FAR const char *ifname,
|
|
FAR const char *confname,
|
|
FAR const struct wpa_wconfig_s *conf)
|
|
{
|
|
FAR char *buf = NULL;
|
|
FAR cJSON *ifobj;
|
|
FAR cJSON *root;
|
|
int ret = -1;
|
|
int fd = -1;
|
|
bool update;
|
|
|
|
if (ifname == NULL || conf == NULL)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if (confname == NULL)
|
|
{
|
|
confname = CONFIG_WIRELESS_WAPI_CONFIG_PATH;
|
|
}
|
|
|
|
root = wapi_json_load(confname);
|
|
if (!root)
|
|
{
|
|
root = cJSON_CreateObject();
|
|
if (root == NULL)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ifobj = cJSON_GetObjectItem(root, ifname);
|
|
if (!ifobj)
|
|
{
|
|
ifobj = cJSON_CreateObject();
|
|
if (ifobj == NULL)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
cJSON_AddItemToObject(root, ifname, ifobj);
|
|
}
|
|
|
|
update = wapi_json_update(ifobj, "mode",
|
|
(FAR void *)(intptr_t)conf->sta_mode, true);
|
|
update |= wapi_json_update(ifobj, "auth",
|
|
(FAR void *)(intptr_t)conf->auth_wpa, true);
|
|
update |= wapi_json_update(ifobj, "cmode",
|
|
(FAR void *)(intptr_t)conf->cipher_mode, true);
|
|
update |= wapi_json_update(ifobj, "alg",
|
|
(FAR void *)(intptr_t)conf->alg, true);
|
|
update |= wapi_json_update(ifobj, "ssid",
|
|
(FAR void *)conf->ssid, false);
|
|
update |= wapi_json_update(ifobj, "bssid",
|
|
(FAR void *)conf->bssid, false);
|
|
update |= wapi_json_update(ifobj, "psk",
|
|
(FAR void *)conf->passphrase, false);
|
|
|
|
if (!update)
|
|
{
|
|
ret = OK;
|
|
goto errout;
|
|
}
|
|
|
|
buf = cJSON_PrintUnformatted(root);
|
|
if (!buf)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
fd = open(confname, O_RDWR | O_CREAT | O_TRUNC);
|
|
if (fd < 0)
|
|
{
|
|
goto errout;
|
|
}
|
|
|
|
ret = write(fd, buf, strlen(buf));
|
|
|
|
errout:
|
|
if (buf)
|
|
{
|
|
free(buf);
|
|
}
|
|
|
|
if (fd > 0)
|
|
{
|
|
close(fd);
|
|
}
|
|
|
|
cJSON_Delete(root);
|
|
|
|
return ret < 0 ? ret : OK;
|
|
}
|
|
#endif /* CONFIG_WIRELESS_WAPI_INITCONF */
|