/**************************************************************************** * apps/wireless/wapi/src/util.c * * Copyright (C) 2011, 2017Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Adapted for NuttX from WAPI: * * Copyright (c) 2010, Volkan YAZICI * 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 #include #include #include #include #include #include #include #include #include #include #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 */