X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fwifi-config.c;h=99c6903e6f7bbdad7b6da47aa58175ddb8cefdef;hb=HEAD;hp=080fb6fdb228a7c332b7c87c30b4290605fb421c;hpb=df5292e3bdb81c7a51330ca792952dfacfe7c42c;p=platform%2Fcore%2Fconnectivity%2Fnet-config.git diff --git a/src/wifi-config.c b/src/wifi-config.c index 080fb6f..99c6903 100755 --- a/src/wifi-config.c +++ b/src/wifi-config.c @@ -18,12 +18,17 @@ */ #include +#include #include #include #include #include #include #include +#include +#include +#include +#include #include @@ -31,6 +36,9 @@ #include "util.h" #include "neterror.h" #include "wifi-config.h" +#include "wifi-state.h" +#include "netsupplicant.h" +#include "wifi-key-encryption.h" #define CONNMAN_STORAGE "/var/lib/connman" @@ -38,26 +46,40 @@ #define WIFI_SECURITY_WEP "wep" #define WIFI_SECURITY_WPA_PSK "psk" #define WIFI_SECURITY_EAP "ieee8021x" +#define WIFI_SECURITY_SAE "sae" #define WIFI_CONFIG_PREFIX "wifi_" #define MAC_ADDRESS_LENGTH 12 #define WIFI_PREFIX_LENGTH MAC_ADDRESS_LENGTH + 6 /* wifi_485a3f2f506a_ */ #define PROFILE_PREFIX_LENGTH WIFI_PREFIX_LENGTH + 21 /* /net/connman/service/wifi_485a3f2f506a_ */ -#define WIFI_MAC_ADD_LENGTH 17 -#define WIFI_MAC_ADD_PATH "/sys/class/net/wlan0/address" +#define NET_DNS_ADDR_MAX 2 + +#define MAX_WIFI_PROFILES 200 struct wifi_eap_config { gchar *anonymous_identity; gchar *ca_cert; gchar *client_cert; gchar *private_key; + gchar *private_key_password; gchar *identity; gchar *eap_type; gchar *eap_auth_type; gchar *subject_match; }; +typedef struct { + gchar *ip_address; + gchar *subnet_mask; + gchar *gateway_address; + gchar *dns_address[NET_DNS_ADDR_MAX]; + int prefix_length; + int dns_count; + gchar *ip_type; + gchar *dns_type; +} wifi_ip_info_s; + struct wifi_config { gchar *name; gchar *ssid; @@ -66,8 +88,11 @@ struct wifi_config { gboolean favorite; gboolean autoconnect; gchar *is_hidden; + gboolean is_created; gchar *proxy_address; struct wifi_eap_config *eap_config; + wifi_ip_info_s *ip_info; + guint frequency; gchar *last_error; }; @@ -88,58 +113,77 @@ static void __free_wifi_configuration(struct wifi_config *conf) g_free(conf->eap_config->ca_cert); g_free(conf->eap_config->client_cert); g_free(conf->eap_config->private_key); + g_free(conf->eap_config->private_key_password); g_free(conf->eap_config->identity); g_free(conf->eap_config->eap_type); g_free(conf->eap_config->eap_auth_type); g_free(conf->eap_config->subject_match); g_free(conf->eap_config); } + + if (conf->ip_info) { + g_free(conf->ip_info->ip_type); + g_free(conf->ip_info->ip_address); + g_free(conf->ip_info->subnet_mask); + g_free(conf->ip_info->gateway_address); + g_free(conf->ip_info->dns_type); + conf->ip_info->prefix_length = 0; + + int i = 0, count = conf->ip_info->dns_count; + while (i < count) { + g_free(conf->ip_info->dns_address[i]); + i++; + } + g_free(conf->ip_info); + } g_free(conf); } -static gboolean __get_mac_address(gchar **mac_address) +static gboolean __get_mac_address(const gchar *interface_name, gchar **mac_address) { + FILE *fp = NULL; + char buf[WIFI_MAC_ADDR_LENGTH + 1]; + char path[WIFI_MAC_PATH_LENGTH]; gchar *tmp_mac = NULL; gchar *tmp = NULL; gchar mac[13] = { 0, }; gint i = 0, j = 0; -#if defined TIZEN_TV - FILE *fp = NULL; - char buf[WIFI_MAC_ADD_LENGTH + 1]; - if (0 == access(WIFI_MAC_ADD_PATH, F_OK)) - fp = fopen(WIFI_MAC_ADD_PATH, "r"); - if (fp == NULL) { - ERR("Failed to open file %s\n", WIFI_MAC_ADD_PATH); - *mac_address = NULL; - return FALSE; - } + snprintf(path, WIFI_MAC_PATH_LENGTH, WIFI_MAC_ADDR_PATH, interface_name); - if (fgets(buf, sizeof(buf), fp) == NULL) { - ERR("Failed to get MAC info from %s\n", WIFI_MAC_ADD_PATH); - *mac_address = NULL; - fclose(fp); - return FALSE; - } - tmp_mac = (char *)g_try_malloc0(WIFI_MAC_ADD_LENGTH + 1); - if (tmp_mac == NULL) { - ERR("malloc() failed"); - *mac_address = NULL; + if (0 == access(path, F_OK)) + fp = fopen(path, "r"); + + if (fp) { + if (fgets(buf, sizeof(buf), fp) == NULL) { + ERR("Failed to get MAC info from %s\n", path); + *mac_address = NULL; + fclose(fp); + return FALSE; + } + tmp_mac = (gchar *)malloc(WIFI_MAC_ADDR_LENGTH + 1); + if (tmp_mac == NULL) { + ERR("malloc() failed"); + *mac_address = NULL; + fclose(fp); + return FALSE; + } + memset(tmp_mac, 0, WIFI_MAC_ADDR_LENGTH + 1); + g_strlcpy(tmp_mac, buf, WIFI_MAC_ADDR_LENGTH + 1); fclose(fp); - return FALSE; - } - g_strlcpy(tmp_mac, buf, WIFI_MAC_ADD_LENGTH + 1); - fclose(fp); -#else - tmp_mac = vconf_get_str(VCONFKEY_WIFI_BSSID_ADDRESS); - if (tmp_mac == NULL) { - ERR("vconf_get_str(WIFI_BSSID_ADDRESS) Failed"); - *mac_address = NULL; - return FALSE; + } else { + ERR("Failed to open file %s\n", path); + + tmp_mac = vconf_get_str(VCONFKEY_WIFI_BSSID_ADDRESS); + if (tmp_mac == NULL) { + ERR("vconf_get_str(WIFI_BSSID_ADDRESS) Failed"); + *mac_address = NULL; + return FALSE; + } } -#endif + tmp = g_ascii_strdown(tmp_mac, (gssize)strlen(tmp_mac)); - g_free(tmp_mac); + free(tmp_mac); while (tmp && tmp[i]) { if (tmp[i] != ':') mac[j++] = tmp[i]; @@ -147,19 +191,22 @@ static gboolean __get_mac_address(gchar **mac_address) } mac[12] = '\0'; *mac_address = g_strdup(mac); + g_free(tmp); return TRUE; } -static gboolean __get_group_name(const gchar *prefix, const gchar *config_id, gchar **group_name) +gboolean wifi_config_get_group_name(const gchar *prefix, + const gchar *interface_name, const gchar *config_id, gchar **group_name) { gchar *mac_address = NULL; gchar *g_name = NULL; gboolean ret = FALSE; - ret = __get_mac_address(&mac_address); + ret = __get_mac_address(interface_name, &mac_address); if ((ret != TRUE) || (strlen(mac_address) == 0)) { ERR("Cannot get WIFI MAC address"); + g_free(mac_address); return FALSE; } @@ -187,6 +234,8 @@ static gboolean __get_security_type(const gchar *config_id, gchar **type) *type = g_strdup(WIFI_SECURITY_WPA_PSK); } else if (g_str_has_suffix(config_id, WIFI_SECURITY_EAP) == TRUE) { *type = g_strdup(WIFI_SECURITY_EAP); + } else if (g_str_has_suffix(config_id, WIFI_SECURITY_SAE) == TRUE) { + *type = g_strdup(WIFI_SECURITY_SAE); } else { *type = NULL; return FALSE; @@ -215,10 +264,10 @@ static GKeyFile *__get_configuration_keyfile(const gchar *group_name) path = g_strdup_printf(CONNMAN_STORAGE "/%s/settings", group_name); keyfile = netconfig_keyfile_load(path); - if (keyfile == NULL) { + if (keyfile == NULL) ERR("keyfile[%s] is NULL", path); - g_free(path); - } + + g_free(path); return keyfile; } @@ -240,16 +289,37 @@ static gboolean __remove_file(const gchar *pathname, const gchar *filename) return ret; } +static gboolean __remove_all_files(const gchar *pathname) +{ + DIR *dir_ptr = NULL; + struct dirent *file = NULL; + + if ((dir_ptr = opendir(pathname)) == NULL) + return TRUE; + + while ((file = readdir(dir_ptr)) != NULL) { + if (strncmp(file->d_name, ".", 1) == 0 || strncmp(file->d_name, "..", 2) == 0) + continue; + + if (__remove_file(pathname, file->d_name) != TRUE) { + ERR("Cannot remove [%s/%s]", pathname, file->d_name); + closedir(dir_ptr); + + return FALSE; + } + } + + closedir(dir_ptr); + + return TRUE; +} + static gboolean __remove_configuration(const gchar *pathname) { int ret = 0; - if (__remove_file(pathname, "settings") != TRUE) { - ERR("Cannot remove [%s/settings]", pathname); - return FALSE; - } - if (__remove_file(pathname, "data") != TRUE) { - ERR("Cannot remove [%s/data]", pathname); + if (__remove_all_files(pathname) != TRUE) { + ERR("Cannot remove [%s] directory", pathname); return FALSE; } @@ -258,18 +328,19 @@ static gboolean __remove_configuration(const gchar *pathname) ERR("Cannot remove [%s]", pathname); return FALSE; } - return TRUE; } -static gboolean _load_configuration(const gchar *config_id, struct wifi_config *config) +static gboolean _load_configuration(const gchar *interface_name, + const gchar *config_id, struct wifi_config *config) { GKeyFile *keyfile; gchar *group_name; gboolean hidden = FALSE; gboolean ret = FALSE; - ret = __get_group_name(WIFI_CONFIG_PREFIX, config_id, &group_name); + ret = wifi_config_get_group_name(WIFI_CONFIG_PREFIX, + interface_name, config_id, &group_name); if (ret != TRUE) { ERR("Fail to get_wifi_config_group_name"); return FALSE; @@ -285,8 +356,15 @@ static gboolean _load_configuration(const gchar *config_id, struct wifi_config * config->name = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_NAME, NULL); DBG("name [%s]", config->name); - ret = __get_security_type(config_id, &config->security_type); - if (ret != TRUE) { + if (config->name == NULL) { + ERR("Fail to get Name of [%s]", group_name); + g_key_file_free(keyfile); + g_free(group_name); + return FALSE; + } + + __get_security_type(config_id, &config->security_type); + if (config->security_type == NULL) { ERR("Fail to _get_security_type"); g_key_file_free(keyfile); g_free(group_name); @@ -294,6 +372,9 @@ static gboolean _load_configuration(const gchar *config_id, struct wifi_config * } DBG("security_type [%s]", config->security_type); + config->passphrase = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_PASSPHRASE, NULL); + DBG("passphrase []"); + config->proxy_address = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_PROXY_SERVER, NULL); if (config->proxy_address) DBG("proxy_address [%s]", config->proxy_address); @@ -305,11 +386,77 @@ static gboolean _load_configuration(const gchar *config_id, struct wifi_config * config->is_hidden = g_strdup("FALSE"); DBG("is_hidden [%s]", config->is_hidden); + config->frequency = g_key_file_get_integer(keyfile, group_name, WIFI_CONFIG_FREQUENCY, NULL); + if (config->frequency) + DBG("Frequency [%d]", config->frequency); + + if (config->ip_info) { + config->ip_info->ip_type = g_key_file_get_string(keyfile, group_name, + WIFI_CONFIG_IPV4_METHOD, NULL); + if (config->ip_info->ip_type) + DBG("IPv4.Method:%s", config->ip_info->ip_type); + + config->ip_info->ip_address = g_key_file_get_string(keyfile, group_name, + WIFI_CONFIG_IPV4_ADDRESS, NULL); + if (config->ip_info->ip_address) + DBG("IPv4.Address:%s", config->ip_info->ip_address); + + int prefix_len; + in_addr_t addr; + struct in_addr netmask; + char *mask; + GError *error = NULL; + prefix_len = g_key_file_get_integer(keyfile, group_name, + WIFI_CONFIG_IPV4_SUBNET_MASK, &error); + if (error != NULL) { + DBG("g_key_file_get_integer failed error[%d: %s]", error->code, error->message); + g_error_free(error); + } else { + if (prefix_len > 0 && prefix_len < 32) { + addr = 0xffffffff << (32 - prefix_len); + netmask.s_addr = htonl(addr); + mask = inet_ntoa(netmask); + config->ip_info->subnet_mask = g_strdup(mask); + } + if (config->ip_info->subnet_mask) + DBG("IPv4.SubnetMask:%s", config->ip_info->subnet_mask); + } + + config->ip_info->gateway_address = g_key_file_get_string(keyfile, + group_name, WIFI_CONFIG_IPV4_GATEWAY_ADDRESS, NULL); + if (config->ip_info->gateway_address) + DBG("IPv4.gateway:%s", config->ip_info->gateway_address); + + config->ip_info->dns_type = g_key_file_get_string(keyfile, group_name, + WIFI_CONFIG_IPV4_DNS_METHOD, NULL); + if (config->ip_info->dns_type) + DBG("DNS.IPv4Method:%s", config->ip_info->dns_type); + + char **nameservers; + gsize length; + nameservers = g_key_file_get_string_list(keyfile, group_name, + WIFI_CONFIG_DNS_ADDRESS, &length, NULL); + if (nameservers) { + if (length > 0) { + config->ip_info->dns_count = length; + int i = 0; + while (i < NET_DNS_ADDR_MAX && nameservers[i]) { + config->ip_info->dns_address[i] = g_strdup(nameservers[i]); + DBG("DNSAddress[%d]:%s", i+1, config->ip_info->dns_address[i]); + i += 1; + } + } + g_strfreev(nameservers); + } + } + + if (g_strcmp0(config->security_type, WIFI_SECURITY_EAP) == 0) { config->eap_config->anonymous_identity = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_EAP_ANONYMOUS_IDENTITY, NULL); config->eap_config->ca_cert = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_EAP_CACERT, NULL); config->eap_config->client_cert = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_EAP_CLIENTCERT, NULL); config->eap_config->private_key = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_EAP_PRIVATEKEY, NULL); + config->eap_config->private_key_password = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_EAP_PRIVATEKEY_PASSWORD, NULL); config->eap_config->identity = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_EAP_IDENTITY, NULL); config->eap_config->eap_type = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_EAP_TYPE, NULL); config->eap_config->eap_auth_type = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_EAP_AUTH_TYPE, NULL); @@ -323,6 +470,8 @@ static gboolean _load_configuration(const gchar *config_id, struct wifi_config * DBG("client_cert [%s]", config->eap_config->client_cert); if (config->eap_config->private_key) DBG("private_key [%s]", config->eap_config->private_key); + if (config->eap_config->private_key_password) + DBG("private_key_password [%s]", config->eap_config->private_key_password); if (config->eap_config->identity) DBG("identity [%s]", config->eap_config->identity); if (config->eap_config->eap_type) @@ -343,14 +492,16 @@ static gboolean _load_configuration(const gchar *config_id, struct wifi_config * return TRUE; } -static gboolean _save_configuration(const gchar *config_id, GKeyFile *keyfile) +gboolean wifi_config_save_configuration(const gchar *interface_name, + const gchar *config_id, GKeyFile *keyfile) { gchar *dir; gchar *path; gchar *group_name; gboolean ret = FALSE; - ret = __get_group_name(WIFI_CONFIG_PREFIX, config_id, &group_name); + ret = wifi_config_get_group_name(WIFI_CONFIG_PREFIX, + interface_name, config_id, &group_name); if (ret != TRUE) { ERR("Fail to get_wifi_config_group_name"); return FALSE; @@ -382,13 +533,14 @@ static gboolean _save_configuration(const gchar *config_id, GKeyFile *keyfile) return TRUE; } -static gboolean _remove_configuration(const gchar *config_id) +static gboolean _remove_configuration(const gchar *interface_name, const gchar *config_id) { gboolean ret = FALSE; gchar *dir; gchar *group_name; - ret = __get_group_name(WIFI_CONFIG_PREFIX, config_id, &group_name); + ret = wifi_config_get_group_name(WIFI_CONFIG_PREFIX, + interface_name, config_id, &group_name); if (ret != TRUE) { ERR("Fail to get_wifi_config_group_name"); return FALSE; @@ -399,9 +551,10 @@ static gboolean _remove_configuration(const gchar *config_id) if (__remove_configuration(dir) != TRUE) { ERR("[%s] is existed, but cannot remove", dir); ret = FALSE; + } else { + INFO("Success to remove [%s]", dir); + ret = TRUE; } - INFO("Success to remove [%s]", dir); - ret = TRUE; } else { ERR("[%s] is not existed", dir); ret = FALSE; @@ -414,13 +567,15 @@ static gboolean _remove_configuration(const gchar *config_id) } -static gboolean _set_field(const gchar *config_id, const gchar *key, const gchar *value) +static gboolean _set_field(const gchar *interface_name, + const gchar *config_id, const gchar *key, const gchar *value) { gboolean ret = TRUE; GKeyFile *keyfile; gchar *group_name; - ret = __get_group_name(WIFI_CONFIG_PREFIX, config_id, &group_name); + ret = wifi_config_get_group_name(WIFI_CONFIG_PREFIX, + interface_name, config_id, &group_name); if (ret != TRUE) { ERR("Fail to get_wifi_config_group_name"); return FALSE; @@ -430,6 +585,7 @@ static gboolean _set_field(const gchar *config_id, const gchar *key, const gchar keyfile = __get_configuration_keyfile(group_name); if (keyfile == NULL) { ERR("Fail to __get_configuration_keyfile"); + g_free(group_name); return FALSE; } @@ -463,7 +619,7 @@ static gboolean _set_field(const gchar *config_id, const gchar *key, const gchar ret = FALSE; } - _save_configuration(config_id, keyfile); + wifi_config_save_configuration(interface_name, config_id, keyfile); g_key_file_free(keyfile); g_free(group_name); @@ -471,7 +627,8 @@ static gboolean _set_field(const gchar *config_id, const gchar *key, const gchar return ret; } -static gboolean _get_field(const gchar *config_id, const gchar *key, gchar **value) +static gboolean _get_field(const gchar *interface_name, + const gchar *config_id, const gchar *key, gchar **value) { GKeyFile *keyfile; gchar *group_name; @@ -479,7 +636,8 @@ static gboolean _get_field(const gchar *config_id, const gchar *key, gchar **val gboolean hidden = FALSE; gboolean ret = FALSE; - ret = __get_group_name(WIFI_CONFIG_PREFIX, config_id, &group_name); + ret = wifi_config_get_group_name(WIFI_CONFIG_PREFIX, + interface_name, config_id, &group_name); if (ret != TRUE) { ERR("Fail to get_wifi_config_group_name"); return FALSE; @@ -489,13 +647,21 @@ static gboolean _get_field(const gchar *config_id, const gchar *key, gchar **val keyfile = __get_configuration_keyfile(group_name); if (keyfile == NULL) { ERR("Fail to __get_configuration_keyfile"); + g_free(group_name); return FALSE; } if (g_strcmp0(key, WIFI_CONFIG_NAME) == 0) { val = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_NAME, NULL); } else if (g_strcmp0(key, WIFI_CONFIG_PASSPHRASE) == 0) { - val = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_PASSPHRASE, NULL); + gchar *enc_pass = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_PASSPHRASE, NULL); + if (enc_pass) { + val = _netconfig_decrypt_passphrase(enc_pass); + g_free(enc_pass); + + if (!val) + ERR("Failed to decrypt the passphrase"); + } } else if (g_strcmp0(key, WIFI_CONFIG_PROXY_SERVER) == 0) { val = g_key_file_get_string(keyfile, group_name, WIFI_CONFIG_PROXY_SERVER, NULL); } else if (g_strcmp0(key, WIFI_CONFIG_HIDDEN) == 0) { @@ -536,10 +702,9 @@ static gboolean _get_field(const gchar *config_id, const gchar *key, gchar **val return TRUE; } -static GSList *_get_list(void) +static GSList *_get_list(const char *mac_addr) { GSList *list = NULL; - struct dirent ent_struct; struct dirent *dp = NULL; DIR *dir; @@ -549,14 +714,20 @@ static GSList *_get_list(void) return NULL; } - while ((readdir_r(dir, &ent_struct, &dp) == 0) && dp) { + while ((dp = readdir(dir)) != NULL) { if (g_strcmp0(dp->d_name, ".") == 0 || g_strcmp0(dp->d_name, "..") == 0 || strncmp(dp->d_name, WIFI_CONFIG_PREFIX, strlen(WIFI_CONFIG_PREFIX)) != 0) { continue; } - gchar *config_id = g_strdup(dp->d_name + WIFI_PREFIX_LENGTH); - list = g_slist_append(list, g_strdup(config_id)); - g_free(config_id); + + DBG("%s", dp->d_name); + + if (netconfig_check_mac_address(dp->d_name, mac_addr)) { + gchar *config_id = g_strdup(dp->d_name + WIFI_PREFIX_LENGTH); + DBG("%s", config_id); + list = g_slist_append(list, g_strdup(config_id)); + g_free(config_id); + } } closedir(dir); @@ -580,30 +751,353 @@ gboolean wifi_config_get_config_id(const gchar *service_profile, gchar **config_ return ret; } -gboolean wifi_config_remove_configuration(const gchar *config_id) +gboolean wifi_config_remove_configuration(const gchar *interface_name, + const gchar *config_id) { gboolean ret = FALSE; - ret = _remove_configuration(config_id); + ret = _remove_configuration(interface_name, config_id); return ret; } +int __netconfig_hex_char_to_num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return -1; +} + +int __netconfig_hex_to_byte(const char *hex) +{ + int a, b; + + a = __netconfig_hex_char_to_num(*hex++); + if (a < 0) + return -1; + + b = __netconfig_hex_char_to_num(*hex++); + if (b < 0) + return -1; + + return (a << 4) | b; +} + +int __netconfig_hex_str_to_bin(const char *hex, unsigned char *buf, size_t len) +{ + size_t i; + int a; + const char *ipos = hex; + unsigned char *opos = buf; + + for (i = 0; i < len; i++) { + a = __netconfig_hex_to_byte(ipos); + if (a < 0) + return -1; + + *opos++ = a; + ipos += 2; + } + + return 0; +} + +static int __netconfig_byte_to_txt(const unsigned char *src, char **dst, int src_len) +{ + int dst_length = 0; + int i = 0; + char *buf = NULL; + + if (src_len <= 0) { + ERR("Invalid parameter."); + return -1; + } + + *dst = (char *) g_try_malloc0((2*src_len)+1); + if (!(*dst)) { + ERR("failed to allocate memory to buffer."); + return -1; + } + + buf = (*dst); + + for (i = 0; i < src_len; i++) { + snprintf(buf, 3, "%02x", src[i]); + buf += 2; + dst_length += 2; + } + + return dst_length; +} + +static int __netconfig_unpack_ay_malloc(unsigned char **dst, GVariantIter *iter) +{ + GVariantIter *iter_copy = NULL; + int length = 0; + char tmp = 0; + unsigned char *tmp_dst = NULL; + + if (!dst || *dst || !iter) { + ERR("Invalid parameter"); + return 0; + } + + iter_copy = g_variant_iter_copy(iter); + + while (g_variant_iter_loop(iter, "y", &tmp)) + length++; + g_variant_iter_free(iter); + + tmp_dst = (unsigned char *)g_try_malloc0(length + 1); + if (!tmp_dst) { + ERR("failed to allocate memory"); + g_variant_iter_free(iter_copy); + return 0; + } + + length = 0; + while (g_variant_iter_loop(iter_copy, "y", &tmp_dst[length])) + length++; + g_variant_iter_free(iter_copy); + + if (length == 0) { + g_free(tmp_dst); + tmp_dst = NULL; + } else { + tmp_dst[length] = '\0'; + } + + *dst = tmp_dst; + DBG("Length [%d]", length); + return length; +} + +gboolean _add_vsie(const char *interface_name, int frame_id, const char* vsie) +{ + GVariant *params = NULL; + GVariant *message = NULL; + GVariantBuilder *bytearray_builder = NULL; + char *if_path; + int i = 0; + size_t vsie_len = 0; + + unsigned char *bytearray = NULL; + size_t bytearray_len = 0; + + if (frame_id >= NETCONFIG_VSIE_FRAME_MAX) { + DBG("Invalid parameter, frame-id: %d", frame_id); + return FALSE; + } + + vsie_len = strlen(vsie); + if (vsie_len == 0) { + DBG("vsie length is zero"); + return FALSE; + } + + bytearray_len = (vsie_len % 2) ? ((vsie_len / 2) + 1) : (vsie_len / 2); + + bytearray = (unsigned char *) g_try_malloc0(bytearray_len); + if (bytearray == NULL) { + DBG("Failed to allocate memory to bytearray"); + return FALSE; + } + + if (__netconfig_hex_str_to_bin(vsie, bytearray, bytearray_len) < 0) { + DBG("invalid vsie string"); + g_free(bytearray); + return FALSE; + } + + bytearray_builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); + for (i = 0; i < bytearray_len; i++) + g_variant_builder_add(bytearray_builder, "y", bytearray[i]); + + params = g_variant_new("(iay)", frame_id, bytearray_builder); + g_variant_builder_unref(bytearray_builder); + + if_path = netconfig_wifi_get_supplicant_interface_path(interface_name); + if (if_path == NULL) { + ERR("Fail to get wpa_supplicant DBus path"); + g_free(bytearray); + return FALSE; + } + + message = netconfig_supplicant_invoke_dbus_method(SUPPLICANT_SERVICE, + if_path, SUPPLICANT_INTERFACE ".Interface", "VendorElemAdd", params); + + g_free(if_path); + if (message == NULL) { + ERR("Failed to send command to wpa_supplicant"); + g_free(bytearray); + return FALSE; + } + + DBG("Succeeded to add vsie: Frame ID[%d], VSIE[%s]", frame_id, vsie); + + g_free(bytearray); + return TRUE; +} + +gboolean _get_vsie(const char *interface_name, int frame_id, char **vsie) +{ + GVariant *params = NULL; + GVariant *message = NULL; + char *if_path; + + if (frame_id >= NETCONFIG_VSIE_FRAME_MAX) { + DBG("Invalid parameter, frame-id: %d", frame_id); + return FALSE; + } + + if_path = netconfig_wifi_get_supplicant_interface_path(interface_name); + if (if_path == NULL) { + ERR("Fail to get wpa_supplicant DBus path"); + return FALSE; + } + + params = g_variant_new("(i)", frame_id); + + message = netconfig_supplicant_invoke_dbus_method(SUPPLICANT_SERVICE, + if_path, SUPPLICANT_INTERFACE ".Interface", "VendorElemGet", params); + + g_free(if_path); + if (message == NULL) { + ERR("Failed to send command to wpa_supplicant"); + return FALSE; + } else { + GVariantIter *iter = NULL; + unsigned char *vsie_bytes = NULL; + int vsie_len = 0; + int ret = 0; + + g_variant_get(message, "(ay)", &iter); + if (iter == NULL) { + ERR("vsie is not present"); + return FALSE; + } + + vsie_len = __netconfig_unpack_ay_malloc(&vsie_bytes, iter); + if (vsie_bytes == NULL) { + ERR("vsie_bytes not allocated"); + return FALSE; + } + + ret = __netconfig_byte_to_txt(vsie_bytes, vsie, vsie_len); + if (ret < 0) { + g_free(vsie_bytes); + ERR("vsie not allocated."); + return FALSE; + } + + g_free(vsie_bytes); + } + + ERR("Succeeded to get vsie: Frame ID[%d], VSIE[%s]", frame_id, *vsie); + + return TRUE; + +} + +gboolean _remove_vsie(const char *interface_name, int frame_id, const char *vsie) +{ + GVariant *params = NULL; + GVariant *message = NULL; + GVariantBuilder *bytearray_builder = NULL; + char *if_path; + int i = 0; + size_t vsie_len = 0; + + unsigned char *bytearray = NULL; + size_t bytearray_len = 0; + + if (frame_id >= NETCONFIG_VSIE_FRAME_MAX) { + DBG("Invalid parameter, frame-id: %d", frame_id); + return FALSE; + } + + vsie_len = strlen(vsie); + if (vsie_len == 0) { + DBG("vsie length is zero"); + return FALSE; + } + + bytearray_len = (vsie_len % 2) ? ((vsie_len / 2) + 1) : (vsie_len / 2); + + bytearray = (unsigned char *) g_try_malloc0(bytearray_len); + if (bytearray == NULL) { + DBG("Failed to allocate memory to bytearray"); + return FALSE; + } + + if (__netconfig_hex_str_to_bin(vsie, bytearray, bytearray_len) < 0) { + DBG("invalid vsie string"); + g_free(bytearray); + return FALSE; + } + + bytearray_builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); + for (i = 0; i < bytearray_len; i++) + g_variant_builder_add(bytearray_builder, "y", bytearray[i]); + + params = g_variant_new("(iay)", frame_id, bytearray_builder); + g_variant_builder_unref(bytearray_builder); + + if_path = netconfig_wifi_get_supplicant_interface_path(interface_name); + if (if_path == NULL) { + ERR("Fail to get wpa_supplicant DBus path"); + g_free(bytearray); + return FALSE; + } + + message = netconfig_supplicant_invoke_dbus_method(SUPPLICANT_SERVICE, + if_path, SUPPLICANT_INTERFACE ".Interface", "VendorElemRem", params); + + g_free(if_path); + if (message == NULL) { + ERR("Failed to send command to wpa_supplicant"); + g_free(bytearray); + return FALSE; + } + + DBG("Succeeded to remove vsie: Frame ID[%d], VSIE[%s]", frame_id, vsie); + + g_free(bytearray); + return TRUE; +} + /* dbus method */ -gboolean handle_get_config_ids(Wifi *wifi, GDBusMethodInvocation *context) +gboolean handle_get_config_ids(Wifi *wifi, GDBusMethodInvocation *context, + const gchar *ifname) { guint i = 0; GSList *config_ids = NULL; guint length; gchar **result = NULL; + const gchar *mac_addr = NULL; - g_return_val_if_fail(wifi != NULL, FALSE); + g_return_val_if_fail(wifi != NULL, TRUE); - config_ids = _get_list(); - if (config_ids == NULL) { + mac_addr = wifi_state_get_mac_address(ifname); + if (!mac_addr) { + ERR("Fail to get mac-address"); netconfig_error_no_profile(context); + return TRUE; + } + + DBG("%s", mac_addr); + config_ids = _get_list(mac_addr); + if (config_ids == NULL) { ERR("Fail to get config list"); - return FALSE; + netconfig_error_no_profile(context); + return TRUE; } length = g_slist_length(config_ids); @@ -619,7 +1113,7 @@ gboolean handle_get_config_ids(Wifi *wifi, GDBusMethodInvocation *context) wifi_complete_get_config_ids(wifi, context, (const gchar * const *)result); for (i = 0; i < length; i++) - if(result[i]) + if (result[i]) g_free(result[i]); if (result) @@ -629,53 +1123,104 @@ gboolean handle_get_config_ids(Wifi *wifi, GDBusMethodInvocation *context) } gboolean handle_load_configuration(Wifi *wifi, GDBusMethodInvocation *context, - const gchar *config_id) + const gchar *ifname, const gchar *config_id) { gboolean ret = FALSE; GVariantBuilder *b = NULL; struct wifi_config *conf = NULL; - g_return_val_if_fail(wifi != NULL, FALSE); + g_return_val_if_fail(wifi != NULL, TRUE); conf = g_new0(struct wifi_config, 1); + conf->ip_info = g_new0(wifi_ip_info_s, 1); - ret = _load_configuration(config_id, conf); + ret = _load_configuration(ifname, config_id, conf); if (ret != TRUE) { + g_free(conf->ip_info); g_free(conf); ERR("Fail to _load_configuration"); netconfig_error_no_profile(context); - return FALSE; + return TRUE; } b = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); g_variant_builder_add(b, "{sv}", WIFI_CONFIG_NAME, g_variant_new_string(conf->name)); g_variant_builder_add(b, "{sv}", WIFI_CONFIG_SECURITY_TYPE, g_variant_new_string(conf->security_type)); + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_PASSPHRASE, g_variant_new_string(conf->passphrase)); g_variant_builder_add(b, "{sv}", WIFI_CONFIG_HIDDEN, g_variant_new_string(conf->is_hidden)); + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_FREQUENCY, g_variant_new_uint32(conf->frequency)); if (conf->proxy_address != NULL) g_variant_builder_add(b, "{sv}", WIFI_CONFIG_PROXYADDRESS, g_variant_new_string(conf->proxy_address)); else g_variant_builder_add(b, "{sv}", WIFI_CONFIG_PROXYADDRESS, g_variant_new_string("NONE")); + if (conf->ip_info->ip_type != NULL) + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_IPV4_METHOD, g_variant_new_string(conf->ip_info->ip_type)); + + if (conf->ip_info->ip_address != NULL) + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_IPV4_ADDRESS, g_variant_new_string(conf->ip_info->ip_address)); + + if (conf->ip_info->subnet_mask != NULL) + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_IPV4_SUBNET_MASK, g_variant_new_string(conf->ip_info->subnet_mask)); + + if (conf->ip_info->prefix_length > 0) + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_IPV6_PREFIX_LEN, g_variant_new_int32(conf->ip_info->prefix_length)); + + if (conf->ip_info->gateway_address != NULL) + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_IPV4_GATEWAY_ADDRESS, g_variant_new_string(conf->ip_info->gateway_address)); + + if (conf->ip_info->dns_type != NULL) + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_IPV4_DNS_METHOD, g_variant_new_string(conf->ip_info->dns_type)); + + int i = 0, count = conf->ip_info->dns_count; + while (i < count) { + if (conf->ip_info->dns_address[i] != NULL) + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_DNS_ADDRESS, g_variant_new_string(conf->ip_info->dns_address[i])); + + i += 1; + } + if (conf->last_error != NULL) g_variant_builder_add(b, "{sv}", WIFI_CONFIG_FAILURE, g_variant_new_string(conf->last_error)); else g_variant_builder_add(b, "{sv}", WIFI_CONFIG_FAILURE, g_variant_new_string("ERROR_NONE")); - g_free(conf->proxy_address); - g_free(conf->last_error); - g_free(conf->name); - g_free(conf->security_type); - g_free(conf->is_hidden); - g_free(conf); + __free_wifi_configuration(conf); + + INFO("Success to load configuration [%s:%s]", ifname, config_id); wifi_complete_load_configuration(wifi, context, g_variant_builder_end(b)); g_variant_builder_unref(b); return TRUE; } +static unsigned char __netconfig_convert_netmask_to_prefixlen( + const char *netmask) +{ + unsigned char bits; + in_addr_t mask; + in_addr_t host; + + if (!netmask) + return 32; + + mask = inet_network(netmask); + host = ~mask; + + /* a valid netmask must be 2^n - 1 */ + if ((host & (host + 1)) != 0) + return -1; + + bits = 0; + for (; mask; mask <<= 1) + ++bits; + + return bits; +} + gboolean handle_save_configuration(Wifi *wifi, GDBusMethodInvocation *context, - const gchar *config_id, GVariant *configuration) + const gchar *ifname, const gchar *config_id, GVariant *configuration) { gboolean ret = FALSE; struct wifi_config *conf = NULL; @@ -684,14 +1229,18 @@ gboolean handle_save_configuration(Wifi *wifi, GDBusMethodInvocation *context, GVariant *value; gchar *field; gchar *group_name = NULL; + int order = 0; + int rv; + struct timeval modified_time; if ((wifi == NULL) || (config_id == NULL) || (configuration == NULL)) { ERR("Invalid parameter"); netconfig_error_invalid_parameter(context); - return FALSE; + return TRUE; } conf = g_new0(struct wifi_config, 1); + conf->ip_info = g_new0(wifi_ip_info_s, 1); g_variant_get(configuration, "a{sv}", &iter); while (g_variant_iter_loop(iter, "{sv}", &field, &value)) { @@ -723,6 +1272,71 @@ gboolean handle_save_configuration(Wifi *wifi, GDBusMethodInvocation *context, } else { conf->is_hidden = NULL; } + } else if (g_strcmp0(field, WIFI_CONFIG_FREQUENCY) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) { + conf->frequency = g_variant_get_uint32(value); + DBG("frequency [%d]", conf->frequency); + } else { + conf->frequency = 0; + } + } else if (g_strcmp0(field, WIFI_CONFIG_CREATED) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) { + conf->is_created = g_variant_get_boolean(value); + DBG("is_created [%d]", conf->is_created); + } else { + conf->is_created = FALSE; + } + } else if (g_strcmp0(field, WIFI_CONFIG_IPV4_METHOD) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + conf->ip_info->ip_type = g_strdup(g_variant_get_string(value, NULL)); + DBG("IP config type [%s]", conf->ip_info->ip_type); + } else { + conf->ip_info->ip_type = NULL; + } + } else if (g_strcmp0(field, WIFI_CONFIG_IPV4_ADDRESS) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + conf->ip_info->ip_address = g_strdup(g_variant_get_string(value, NULL)); + DBG("IP address [%s]", conf->ip_info->ip_address); + } else { + conf->ip_info->ip_address = NULL; + } + } else if (g_strcmp0(field, WIFI_CONFIG_IPV4_SUBNET_MASK) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + conf->ip_info->subnet_mask = g_strdup(g_variant_get_string(value, NULL)); + DBG("Subnet Mask [%s]", conf->ip_info->subnet_mask); + } else { + conf->ip_info->subnet_mask = NULL; + } + } else if (g_strcmp0(field, WIFI_CONFIG_IPV6_PREFIX_LEN) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) { + conf->ip_info->prefix_length = g_variant_get_int32(value); + DBG("IPv6 Prefix Length [%d]", conf->ip_info->prefix_length); + } else { + conf->ip_info->prefix_length = 0; + } + } else if (g_strcmp0(field, WIFI_CONFIG_IPV4_GATEWAY_ADDRESS) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + conf->ip_info->gateway_address = g_strdup(g_variant_get_string(value, NULL)); + DBG("Gateway address [%s]", conf->ip_info->gateway_address); + } else { + conf->ip_info->gateway_address = NULL; + } + } else if (g_strcmp0(field, WIFI_CONFIG_IPV4_DNS_METHOD) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + conf->ip_info->dns_type = g_strdup(g_variant_get_string(value, NULL)); + DBG("DNS config type [%s]", conf->ip_info->dns_type); + } else { + conf->ip_info->dns_type = NULL; + } + } else if (g_strcmp0(field, WIFI_CONFIG_DNS_ADDRESS) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + conf->ip_info->dns_address[order] = g_strdup(g_variant_get_string(value, NULL)); + DBG("DNS address [%s]", conf->ip_info->dns_address[order]); + conf->ip_info->dns_count = order + 1; + order++; + } else { + conf->ip_info->dns_address[order++] = NULL; + } } else if (g_strcmp0(field, WIFI_CONFIG_PROXYADDRESS) == 0) { if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { conf->proxy_address = g_strdup(g_variant_get_string(value, NULL)); @@ -735,22 +1349,57 @@ gboolean handle_save_configuration(Wifi *wifi, GDBusMethodInvocation *context, conf->favorite = TRUE; conf->autoconnect = TRUE; - ret = __get_group_name(WIFI_CONFIG_PREFIX, config_id, &group_name); + ret = wifi_config_get_group_name(WIFI_CONFIG_PREFIX, + ifname, config_id, &group_name); if (ret != TRUE) { + __free_wifi_configuration(conf); ERR("Fail to get_wifi_config_group_name"); - return FALSE; + netconfig_error_fail_save_congifuration(context); + return TRUE; } keyfile = g_key_file_new(); g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_NAME, conf->name); g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_SSID, conf->ssid); - if (conf->passphrase != NULL) + if (conf->passphrase != NULL) { + gchar *enc_data = NULL; + + if (conf->is_created == true) + enc_data = _netconfig_encrypt_passphrase(conf->passphrase); + else + enc_data = g_strdup(conf->passphrase); + + if (!enc_data) { + ERR("Failed to encrypt the passphrase"); + } else { + g_free(conf->passphrase); + conf->passphrase = enc_data; + } + g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_PASSPHRASE, conf->passphrase); + } g_key_file_set_boolean(keyfile, group_name, WIFI_CONFIG_FAVORITE, conf->favorite); g_key_file_set_boolean(keyfile, group_name, WIFI_CONFIG_AUTOCONNECT, conf->autoconnect); + rv = gettimeofday(&modified_time, NULL); + if (!rv) { + struct tm modified_tm; + char time_buf[255]; + time_t modified_t = modified_time.tv_sec; + + if (localtime_r(&modified_t, &modified_tm)) { + if (strftime(time_buf, sizeof(time_buf), "%FT%TZ", &modified_tm)) { + field = g_strdup(time_buf); + if (field) { + g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_MODIFIED, field); + g_free(field); + } + } + } + } + /* Optional field */ if (conf->proxy_address != NULL) { g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_PROXY_METHOD, "manual"); @@ -764,61 +1413,118 @@ gboolean handle_save_configuration(Wifi *wifi, GDBusMethodInvocation *context, g_key_file_set_boolean(keyfile, group_name, WIFI_CONFIG_HIDDEN, hidden); } - ret = _save_configuration(config_id, keyfile); + if (conf->frequency > 0) + g_key_file_set_integer(keyfile, group_name, + WIFI_CONFIG_FREQUENCY, conf->frequency); + + if (conf->ip_info->ip_type != NULL) + g_key_file_set_string(keyfile, group_name, + WIFI_CONFIG_IPV4_METHOD, conf->ip_info->ip_type); + + if (conf->ip_info->ip_address != NULL) + g_key_file_set_string(keyfile, group_name, + WIFI_CONFIG_IPV4_ADDRESS, conf->ip_info->ip_address); + + if (conf->ip_info->subnet_mask != NULL) { + unsigned char prefix_len; + prefix_len = __netconfig_convert_netmask_to_prefixlen( + conf->ip_info->subnet_mask); + if (prefix_len > 0 && prefix_len < 32) + g_key_file_set_integer(keyfile, group_name, + WIFI_CONFIG_IPV4_SUBNET_MASK, prefix_len); + } + + if (conf->ip_info->prefix_length > 0) + g_key_file_set_integer(keyfile, group_name, + WIFI_CONFIG_IPV6_PREFIX_LEN, conf->ip_info->prefix_length); + + if (conf->ip_info->gateway_address != NULL) + g_key_file_set_string(keyfile, group_name, + WIFI_CONFIG_IPV4_GATEWAY_ADDRESS, conf->ip_info->gateway_address); + + if (conf->ip_info->dns_type != NULL) + g_key_file_set_string(keyfile, group_name, + WIFI_CONFIG_IPV4_DNS_METHOD, conf->ip_info->dns_type); + + int i = 0, count = conf->ip_info->dns_count; + while (i < count) { + if (conf->ip_info->dns_address[i] != NULL) + g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_DNS_ADDRESS, + conf->ip_info->dns_address[i]); + + i += 1; + } + + ret = wifi_config_save_configuration(ifname, config_id, keyfile); if (ret == TRUE) { INFO("Success to save configuration [%s]", config_id); wifi_complete_save_configuration(wifi, context); + char *file; + if (get_files_count(CONNMAN_STORAGE) > MAX_WIFI_PROFILES) { + file = get_least_recently_profile(CONNMAN_STORAGE); + if (file) { + gchar *profileName = g_strdup_printf(CONNMAN_STORAGE "/%s", file); + INFO("least modified file: %s", profileName); + if (profileName) { + if (__remove_configuration(profileName) != TRUE) + DBG("Failed to remove profile: [%s]", profileName); + } else + ERR("Profile: [%s] does not exist", file); + + g_free(profileName); + } + } } else { INFO("Fail to save configuration [%s]", config_id); netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "FailSaveConfiguration"); } g_key_file_free(keyfile); - g_free(conf->name); - g_free(conf->ssid); - g_free(conf->passphrase); - g_free(conf->is_hidden); - g_free(conf->proxy_address); - g_free(conf); + g_free(group_name); + __free_wifi_configuration(conf); g_variant_iter_free(iter); - return ret; + return TRUE; } gboolean handle_load_eap_configuration(Wifi *wifi, GDBusMethodInvocation *context, - const gchar *config_id) + const gchar *ifname, const gchar *config_id) { gboolean ret = FALSE; GVariantBuilder *b = NULL; struct wifi_config *conf = NULL; - g_return_val_if_fail(wifi != NULL, FALSE); + g_return_val_if_fail(wifi != NULL, TRUE); conf = g_new0(struct wifi_config, 1); conf->eap_config = g_new0(struct wifi_eap_config, 1); + conf->ip_info = g_new0(wifi_ip_info_s, 1); - ret = _load_configuration(config_id, conf); + ret = _load_configuration(ifname, config_id, conf); if (ret != TRUE) { g_free(conf->eap_config); + g_free(conf->ip_info); g_free(conf); ERR("Fail to _load_configuration"); netconfig_error_no_profile(context); - return FALSE; + return TRUE; } b = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); g_variant_builder_add(b, "{sv}", WIFI_CONFIG_NAME, g_variant_new_string(conf->name)); g_variant_builder_add(b, "{sv}", WIFI_CONFIG_SECURITY_TYPE, g_variant_new_string(conf->security_type)); g_variant_builder_add(b, "{sv}", WIFI_CONFIG_HIDDEN, g_variant_new_string(conf->is_hidden)); - if (conf->proxy_address != NULL) { + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_FREQUENCY, g_variant_new_uint32(conf->frequency)); + + if (conf->proxy_address != NULL) g_variant_builder_add(b, "{sv}", WIFI_CONFIG_PROXYADDRESS, g_variant_new_string(conf->proxy_address)); - } else + else g_variant_builder_add(b, "{sv}", WIFI_CONFIG_PROXYADDRESS, g_variant_new_string("NONE")); - if (conf->last_error != NULL) { + if (conf->last_error != NULL) g_variant_builder_add(b, "{sv}", WIFI_CONFIG_FAILURE, g_variant_new_string(conf->last_error)); - } else + else g_variant_builder_add(b, "{sv}", WIFI_CONFIG_FAILURE, g_variant_new_string("ERROR_NONE")); if (conf->eap_config != NULL) { @@ -842,6 +1548,11 @@ gboolean handle_load_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex else g_variant_builder_add(b, "{sv}", WIFI_CONFIG_EAP_PRIVATEKEY, g_variant_new_string("NONE")); + if (conf->eap_config->private_key_password != NULL) + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_EAP_PRIVATEKEY_PASSWORD, g_variant_new_string(conf->eap_config->private_key_password)); + else + g_variant_builder_add(b, "{sv}", WIFI_CONFIG_EAP_PRIVATEKEY_PASSWORD, g_variant_new_string("NONE")); + if (conf->eap_config->identity != NULL) g_variant_builder_add(b, "{sv}", WIFI_CONFIG_EAP_IDENTITY, g_variant_new_string(conf->eap_config->identity)); else @@ -871,7 +1582,7 @@ gboolean handle_load_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex } gboolean handle_save_eap_configuration(Wifi *wifi, GDBusMethodInvocation *context, - const gchar *config_id, GVariant *configuration) + const gchar *ifname, const gchar *config_id, GVariant *configuration) { gboolean ret = FALSE; struct wifi_config *conf = NULL; @@ -884,7 +1595,7 @@ gboolean handle_save_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex if ((wifi == NULL) || (config_id == NULL) || (configuration == NULL)) { ERR("Invalid parameter"); netconfig_error_invalid_parameter(context); - return FALSE; + return TRUE; } conf = g_new0(struct wifi_config, 1); @@ -920,6 +1631,20 @@ gboolean handle_save_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex } else { conf->is_hidden = NULL; } + } else if (g_strcmp0(field, WIFI_CONFIG_FREQUENCY) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) { + conf->frequency = g_variant_get_uint32(value); + DBG("frequency [%d]", conf->frequency); + } else { + conf->frequency = 0; + } + } else if (g_strcmp0(field, WIFI_CONFIG_CREATED) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) { + conf->is_created = g_variant_get_boolean(value); + DBG("is_created [%d]", conf->is_created); + } else { + conf->is_created = FALSE; + } } else if (g_strcmp0(field, WIFI_CONFIG_PROXYADDRESS) == 0) { if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { conf->proxy_address = g_strdup(g_variant_get_string(value, NULL)); @@ -955,6 +1680,13 @@ gboolean handle_save_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex } else { conf->eap_config->private_key = NULL; } + } else if (g_strcmp0(field, WIFI_CONFIG_EAP_PRIVATEKEY_PASSWORD) == 0) { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + conf->eap_config->private_key_password = g_strdup(g_variant_get_string(value, NULL)); + DBG("private_key_password[%s]", conf->eap_config->private_key_password); + } else { + conf->eap_config->private_key_password = NULL; + } } else if (g_strcmp0(field, WIFI_CONFIG_EAP_IDENTITY) == 0) { if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { conf->eap_config->identity = g_strdup(g_variant_get_string(value, NULL)); @@ -988,19 +1720,34 @@ gboolean handle_save_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex conf->favorite = TRUE; conf->autoconnect = TRUE; - ret = __get_group_name(WIFI_CONFIG_PREFIX, config_id, &group_name); + ret = wifi_config_get_group_name(WIFI_CONFIG_PREFIX, + ifname, config_id, &group_name); if (ret != TRUE) { __free_wifi_configuration(conf); ERR("Fail to get_wifi_config_group_name"); - return FALSE; + return TRUE; } keyfile = g_key_file_new(); g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_NAME, conf->name); g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_SSID, conf->ssid); - if (conf->passphrase != NULL) + if (conf->passphrase != NULL) { + gchar *enc_data = NULL; + + if (conf->is_created == true) + enc_data = _netconfig_encrypt_passphrase(conf->passphrase); + else + enc_data = g_strdup(conf->passphrase); + + if (!enc_data) { + ERR("Failed to encrypt the passphrase"); + } else { + g_free(conf->passphrase); + conf->passphrase = enc_data; + } g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_PASSPHRASE, conf->passphrase); + } g_key_file_set_boolean(keyfile, group_name, WIFI_CONFIG_FAVORITE, conf->favorite); g_key_file_set_boolean(keyfile, group_name, WIFI_CONFIG_AUTOCONNECT, conf->autoconnect); @@ -1018,6 +1765,10 @@ gboolean handle_save_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex g_key_file_set_boolean(keyfile, group_name, WIFI_CONFIG_HIDDEN, hidden); } + if (conf->frequency > 0) + g_key_file_set_integer(keyfile, group_name, + WIFI_CONFIG_FREQUENCY, conf->frequency); + if (conf->eap_config->anonymous_identity != NULL) g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_EAP_ANONYMOUS_IDENTITY, conf->eap_config->anonymous_identity); @@ -1034,6 +1785,10 @@ gboolean handle_save_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_EAP_PRIVATEKEY, conf->eap_config->private_key); + if (conf->eap_config->private_key_password != NULL) + g_key_file_set_string(keyfile, group_name, + WIFI_CONFIG_EAP_PRIVATEKEY_PASSWORD, conf->eap_config->private_key_password); + if (conf->eap_config->identity != NULL) g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_EAP_IDENTITY, conf->eap_config->identity); @@ -1050,7 +1805,7 @@ gboolean handle_save_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex g_key_file_set_string(keyfile, group_name, WIFI_CONFIG_EAP_SUBJECT_MATCH, conf->eap_config->subject_match); - ret = _save_configuration(config_id, keyfile); + ret = wifi_config_save_configuration(ifname, config_id, keyfile); if (ret == TRUE) { INFO("Success to save eap configuration [%s]", config_id); wifi_complete_save_eap_configuration(wifi, context); @@ -1060,33 +1815,81 @@ gboolean handle_save_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex } g_key_file_free(keyfile); + g_free(group_name); __free_wifi_configuration(conf); g_variant_iter_free(iter); - return ret; + return TRUE; } -gboolean handle_remove_configuration(Wifi *wifi, GDBusMethodInvocation *context, const gchar *config_id) +gboolean handle_remove_configuration(Wifi *wifi, GDBusMethodInvocation *context, + const gchar *ifname, const gchar *config_id) { gboolean ret = FALSE; if ((wifi == NULL) || (config_id == NULL)) { ERR("Invalid parameter"); netconfig_error_invalid_parameter(context); - return FALSE; + return TRUE; } - ret = _remove_configuration(config_id); + ret = _remove_configuration(ifname, config_id); if (ret != TRUE) { /* no configuration or error */ ERR("No [%s] configuration", config_id); netconfig_error_no_profile(context); - return FALSE; + return TRUE; } wifi_complete_remove_configuration(wifi, context); - return ret; + return TRUE; +} + +gboolean handle_reset_wifi_config(Wifi *wifi, GDBusMethodInvocation *context) +{ + DIR *dir_ptr = NULL; + struct dirent *file = NULL; + struct stat buf; + char dir_name[512] = { 0, }; + char file_name[1024] = { 0, }; + + g_return_val_if_fail(wifi != NULL, TRUE); + + DBG("Try to remove connman Wi-Fi config files..."); + + if ((dir_ptr = opendir(CONNMAN_STORAGE)) != NULL) { + while ((file = readdir(dir_ptr)) != NULL) { + if (strncmp(file->d_name, ".", 1) == 0 || strncmp(file->d_name, "..", 2) == 0 || + strncmp(file->d_name, WIFI_CONFIG_PREFIX, strlen(WIFI_CONFIG_PREFIX)) != 0) { + continue; + } + + snprintf(dir_name, 512, CONNMAN_STORAGE"/%s", file->d_name); + + if (lstat(dir_name, &buf) == -1) + continue; + + DBG("Remove wifi config: %s", file->d_name); + + if (S_ISDIR(buf.st_mode)) { + memset(file_name, 0, 1024); + snprintf(file_name, 1024, "%s/data", dir_name); + unlink(file_name); + memset(file_name, 0, 1024); + snprintf(file_name, 1024, "%s/settings", dir_name); + unlink(file_name); + } + rmdir(dir_name); + } + + closedir(dir_ptr); + sync(); + } + + wifi_complete_reset_wifi_config(wifi, context); + + return TRUE; } /* config field key / value */ @@ -1110,23 +1913,23 @@ gboolean handle_remove_configuration(Wifi *wifi, GDBusMethodInvocation *context, * Proxy.Servers=trst.com:8888; (O) */ gboolean handle_set_config_field(Wifi *wifi, GDBusMethodInvocation *context, - const gchar *config_id, const gchar *key, const gchar *value) + const gchar *ifname, const gchar *config_id, const gchar *key, const gchar *value) { gboolean ret = FALSE; gchar *keyfile_key = NULL; - g_return_val_if_fail(wifi != NULL, FALSE); - g_return_val_if_fail(config_id != NULL, FALSE); - g_return_val_if_fail(key != NULL, FALSE); + g_return_val_if_fail(wifi != NULL, TRUE); + g_return_val_if_fail(config_id != NULL, TRUE); + g_return_val_if_fail(key != NULL, TRUE); - DBG("Key[%s] Value[%d]", key, value); + DBG("Key[%s] Value[%s]", key, value); if (g_strcmp0(key, WIFI_CONFIG_PROXYADDRESS) == 0) { - ret = _set_field(config_id, WIFI_CONFIG_PROXY_METHOD, "manual"); + ret = _set_field(ifname, config_id, WIFI_CONFIG_PROXY_METHOD, "manual"); if (!ret) { ERR("Fail to [%s]set_wifi_config_field(%s/manual)", config_id, WIFI_CONFIG_PROXY_METHOD); netconfig_error_invalid_parameter(context); - return FALSE; + return TRUE; } keyfile_key = g_strdup_printf("%s", WIFI_CONFIG_PROXY_SERVER); } else if (g_strcmp0(key, WIFI_CONFIG_HIDDEN) == 0) { @@ -1150,42 +1953,107 @@ gboolean handle_set_config_field(Wifi *wifi, GDBusMethodInvocation *context, } else { ERR("Not supported key[%s]", key); netconfig_error_invalid_parameter(context); - return FALSE; + return TRUE; } - ret = _set_field(config_id, keyfile_key, (const gchar *)value); + ret = _set_field(ifname, config_id, keyfile_key, (const gchar *)value); if (!ret) { ERR("Fail to [%s]set_wifi_config_field(%s/%s)", config_id, key, value); - ret = FALSE; } if (keyfile_key != NULL) g_free(keyfile_key); wifi_complete_set_config_field(wifi, context); - return ret; + return TRUE; } -gboolean handle_get_config_passphrase(Wifi *wifi, GDBusMethodInvocation *context, const gchar *config_id) +gboolean handle_get_config_passphrase(Wifi *wifi, GDBusMethodInvocation *context, + const gchar *ifname, const gchar *config_id) { gboolean ret = FALSE; gchar *passphrase = NULL; - if ((wifi == NULL) || (config_id == NULL)) { + if ((wifi == NULL) || (ifname == NULL) || (config_id == NULL)) { ERR("Invalid parameter"); netconfig_error_invalid_parameter(context); - return FALSE; + return TRUE; } - ret = _get_field(config_id, WIFI_CONFIG_PASSPHRASE, &passphrase); + ret = _get_field(ifname, config_id, WIFI_CONFIG_PASSPHRASE, &passphrase); if (!ret) { ERR("Fail to [%s] _get_field(%s)", config_id, WIFI_CONFIG_PASSPHRASE); netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed"); - return FALSE; + return TRUE; } wifi_complete_get_config_passphrase(wifi, context, passphrase); g_free(passphrase); - return ret; + return TRUE; +} + +gboolean handle_add_vsie(Wifi *wifi, GDBusMethodInvocation *context, + const gchar *ifname, int frame_id, const gchar *vsie) +{ + DBG("Frame ID: [%d] VSIE: [%s]", frame_id, vsie); + + g_return_val_if_fail(wifi != NULL, TRUE); + g_return_val_if_fail(vsie != NULL, TRUE); + + gboolean ret = FALSE; + + ret = _add_vsie(ifname, frame_id, vsie); + if (!ret) { + DBG("Failed to add vsie: %s", vsie); + netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed"); + return TRUE; + } + + wifi_complete_add_vsie(wifi, context); + return TRUE; +} + +gboolean handle_get_vsie(Wifi *wifi, GDBusMethodInvocation *context, + const gchar *ifname, int frame_id) +{ + DBG("Frame ID: [%d]", frame_id); + + g_return_val_if_fail(wifi != NULL, TRUE); + + gboolean ret = FALSE; + gchar *vsie = NULL; + + ret = _get_vsie(ifname, frame_id, &vsie); + if (!ret) { + DBG("Failed to get vsie for frame:[%d]", frame_id); + netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed"); + return TRUE; + } + + DBG("Received vsie: %s", vsie); + wifi_complete_get_vsie(wifi, context, vsie); + + return TRUE; +} + +gboolean handle_remove_vsie(Wifi *wifi, GDBusMethodInvocation *context, + const gchar *ifname, int frame_id, const gchar *vsie) +{ + DBG("Frame ID: [%d] VSIE: [%s]", frame_id, vsie); + + g_return_val_if_fail(wifi != NULL, TRUE); + g_return_val_if_fail(vsie != NULL, TRUE); + + gboolean ret = FALSE; + + ret = _remove_vsie(ifname, frame_id, vsie); + if (!ret) { + DBG("Failed to remove vsie: %s", vsie); + netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed"); + return TRUE; + } + + wifi_complete_remove_vsie(wifi, context); + return TRUE; }