Merge "[net-config] Suspend/Resume WLAN driver" into tizen accepted/tizen/unified/20181107.081842 submit/tizen/20181105.105104
authorcheoleun moon <chleun.moon@samsung.com>
Mon, 5 Nov 2018 10:50:39 +0000 (10:50 +0000)
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>
Mon, 5 Nov 2018 10:50:39 +0000 (10:50 +0000)
14 files changed:
haltests/haltests.h
haltests/net-config-haltests.cpp
include/util.h
include/wifi-config.h
packaging/net-config.spec
src/ip-conflict-detect.c
src/network-state.c
src/signal-handler.c
src/utils/util.c
src/wifi-bssid-scan.c
src/wifi-config.c
src/wifi-firmware.c
src/wifi-indicator.c
src/wifi.c

index 7c56f1d..f114a4f 100755 (executable)
@@ -28,7 +28,8 @@ extern "C" {
 #define MAX_PATH_LENGTH 256
 
 #define FEATURE_WIFI       "http://tizen.org/feature/network.wifi"
-#define WIFIDIRECT_FEATURE "http://tizen.org/feature/network.wifi.direct"
+#define FEATURE_WIFIDIRECT "http://tizen.org/feature/network.wifi.direct"
+#define FEATURE_SOFTAP     "http://tizen.org/feature/network.wifi.softap"
 
 #define WIFI_ADDRESS_PATH    "/sys/class/net/wlan0/address"
 #define WIFI_P2P_PATH        "/sys/class/net/p2p0/address"
@@ -39,6 +40,7 @@ GMainLoop *g_pMainLoop;
 guint g_nTimeoutId;
 bool g_bFeatureWifi;
 bool g_bFeatureP2P;
+bool g_bFeatureSoftap;
 
 #define RUN_GMAIN_LOOP(callback) {\
        g_pMainLoop = g_main_loop_new(NULL, false);\
@@ -53,6 +55,13 @@ bool g_bFeatureP2P;
                g_main_loop_quit(g_pMainLoop);\
 }
 
+#define SKIP_NOT_SUPPORTED(bFeature) {\
+       if (!bFeature) {\
+               printf("Feature is not support\n");\
+               return;\
+       } \
+}
+
 #ifdef __cplusplus
 }
 #endif
index 11ae2a7..16c25b5 100755 (executable)
@@ -50,7 +50,6 @@ static bool __check_feature_supported(char *key)
        int ret = system_info_get_platform_bool(key, &value);
 
        EXPECT_EQ(SYSTEM_INFO_ERROR_NONE, ret) << "system_info_get_platform_bool failed";
-       EXPECT_EQ(true, value) << key << " feature is not supported";
 
        return value;
 }
@@ -144,7 +143,7 @@ static bool __found_ap_callback(wifi_manager_ap_h ap, void *user_data)
 TEST(Hal_wifi, Init_p)
 {
        g_bFeatureWifi = __check_feature_supported((char*)FEATURE_WIFI);
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureWifi);
 
        int rv = wifi_manager_initialize(&wifi);
        EXPECT_EQ(WIFI_MANAGER_ERROR_NONE, rv) << "Initialization failure";
@@ -152,7 +151,7 @@ TEST(Hal_wifi, Init_p)
 
 TEST(Hal_wifi, Activate_p)
 {
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureWifi);
 
        int rv;
        bool activated;
@@ -178,7 +177,7 @@ done:
 
 TEST(Hal_wifi, Scan_p)
 {
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureWifi);
 
        int rv = wifi_manager_scan(wifi, __test_callback, NULL);
        ASSERT_EQ(WIFI_MANAGER_ERROR_NONE, rv) << "Failed to scan";
@@ -191,7 +190,7 @@ TEST(Hal_wifi, Scan_p)
 
 TEST(Hal_wifi, Connect_p)
 {
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureWifi);
 
        wifi_manager_connection_state_e connection_state;
        int ret = WIFI_MANAGER_ERROR_NONE;
@@ -220,7 +219,7 @@ TEST(Hal_wifi, Connect_p)
 
 TEST(Hal_wifi, Disconnect_p)
 {
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureWifi);
 
        int ret = WIFI_MANAGER_ERROR_NONE;
        wifi_manager_ap_h hAP = NULL;
@@ -244,7 +243,7 @@ TEST(Hal_wifi, Disconnect_p)
 
 TEST(Hal_wifi, Deactivate_p)
 {
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureWifi);
 
        int rv = wifi_manager_deactivate(wifi, __test_callback, NULL);
        ASSERT_EQ(WIFI_MANAGER_ERROR_NONE, rv) << "Failed to deactivate Wi-Fi device";
@@ -253,14 +252,11 @@ TEST(Hal_wifi, Deactivate_p)
 
        EXPECT_EQ(WIFI_MANAGER_ERROR_NONE, rst) << "Deactivation failure";
        rst = WIFI_MANAGER_ERROR_NOT_SUPPORTED;
-
-       rv = access(WIFI_ADDRESS_PATH, F_OK);
-       EXPECT_EQ(-1, rv) << WIFI_ADDRESS_PATH << " is exist";
 }
 
 TEST(Hal_wifi, Deinit_p)
 {
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureWifi);
 
        int rv = wifi_manager_deinitialize(wifi);
        EXPECT_EQ(WIFI_MANAGER_ERROR_NONE, rv) << "Deinitialization failure";
@@ -268,8 +264,8 @@ TEST(Hal_wifi, Deinit_p)
 
 TEST(Hal_wifi_direct, Init_p)
 {
-       g_bFeatureP2P = __check_feature_supported((char*)WIFIDIRECT_FEATURE);
-       ASSERT_EQ(true, g_bFeatureP2P) << WIFIDIRECT_FEATURE << " feature is not supported";
+       g_bFeatureP2P = __check_feature_supported((char*)FEATURE_WIFIDIRECT);
+       SKIP_NOT_SUPPORTED(g_bFeatureP2P);
 
        int rv = wifi_direct_initialize();
        EXPECT_EQ(WIFI_DIRECT_ERROR_NONE, rv) << "Initialization failure";
@@ -277,7 +273,7 @@ TEST(Hal_wifi_direct, Init_p)
 
 TEST(Hal_wifi_direct, Activate_p)
 {
-       ASSERT_EQ(true, g_bFeatureP2P) << WIFIDIRECT_FEATURE << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureP2P);
 
        int rv;
        wifi_direct_state_e state = WIFI_DIRECT_STATE_ACTIVATED;
@@ -313,7 +309,7 @@ done:
 
 TEST(Hal_wifi_direct, Deactivate_p)
 {
-       ASSERT_EQ(true, g_bFeatureP2P) << WIFIDIRECT_FEATURE << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureP2P);
 
        int rv;
 
@@ -331,19 +327,13 @@ TEST(Hal_wifi_direct, Deactivate_p)
 
        EXPECT_EQ(WIFI_DIRECT_STATE_DEACTIVATED, state) << "Deactivetion failure";
 
-       if (p2p_ifname[0])
-               rv = access(p2p_ifname, F_OK);
-       else
-               rv = access(WIFI_P2P_PATH, F_OK);
-       EXPECT_EQ(-1, rv) << WIFI_P2P_PATH << " is exist";
-
        rv = wifi_direct_unset_device_state_changed_cb();
        EXPECT_EQ(WIFI_DIRECT_ERROR_NONE, rv) << "Failed to unset activation callback";
 }
 
 TEST(Hal_wifi_direct, Deinit_p)
 {
-       ASSERT_EQ(true, g_bFeatureP2P) << WIFIDIRECT_FEATURE << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureP2P);
 
        int rv = wifi_direct_deinitialize();
        EXPECT_EQ(WIFI_DIRECT_ERROR_NONE, rv) << "Deinitialization failure";
@@ -351,8 +341,8 @@ TEST(Hal_wifi_direct, Deinit_p)
 
 TEST(Hal_softap, Init_p)
 {
-       g_bFeatureWifi = __check_feature_supported((char*)FEATURE_WIFI);
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       g_bFeatureSoftap = __check_feature_supported((char*)FEATURE_SOFTAP);
+       SKIP_NOT_SUPPORTED(g_bFeatureSoftap);
 
        int ret = SOFTAP_ERROR_NONE;
 
@@ -368,7 +358,7 @@ TEST(Hal_softap, Init_p)
 
 TEST(Hal_softap, Activate_p)
 {
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureSoftap);
 
        int ret = SOFTAP_ERROR_NONE;
        bool enabled = false;
@@ -394,7 +384,7 @@ done:
 
 TEST(Hal_softap, Deactivate_p)
 {
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureSoftap);
 
        int ret = SOFTAP_ERROR_NONE;
 
@@ -404,14 +394,11 @@ TEST(Hal_softap, Deactivate_p)
        RUN_GMAIN_LOOP(__timeout_callback);
 
        EXPECT_EQ(SOFTAP_ERROR_NONE, g_error) << "Failed to disable SoftAP" << g_code;
-
-       ret = access(WIFI_ADDRESS_PATH, F_OK);
-       EXPECT_EQ(-1, ret) << WIFI_ADDRESS_PATH << " is exist";
 }
 
 TEST(Hal_softap, Deinit_p)
 {
-       ASSERT_EQ(true, g_bFeatureWifi) << FEATURE_WIFI << " feature is not supported";
+       SKIP_NOT_SUPPORTED(g_bFeatureSoftap);
 
        int ret = SOFTAP_ERROR_NONE;
 
index fd8168a..6e9b936 100755 (executable)
@@ -37,19 +37,13 @@ extern "C" {
 #define ETHERNET_FEATURE "http://tizen.org/feature/network.ethernet"
 #define TETHERING_FEATURE "http://tizen.org/feature/network.tethering"
 #define WIFI_DIRECT_FEATURE "http://tizen.org/feature/network.wifi.direct"
-
-/** Macros to handle rtattributes */
-#define RTA_ALIGNTO    4
-#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
-#define RTA_LENGTH(len)        (RTA_ALIGN(sizeof(struct rtattr)) + (len))
-#define RTA_DATA(rta)   ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
-#define NLMSG_TAIL(nmsg) \
-       ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+#define WIFI_SOFTAP_FEATURE "http://tizen.org/feature/network.wifi.softap"
 
 typedef enum {
        NETCONFIG_SUPPORTED_FEATURE_ETHERNET = 0,
        NETCONFIG_SUPPORTED_FEATURE_TETHERING,
        NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT,
+       NETCONFIG_SUPPORTED_FEATURE_WIFI_SOFTAP,
        NETCONFIG_SUPPORTED_FEATURE_MAX,
 } netconfig_supported_feature_e;
 
@@ -81,8 +75,8 @@ int netconfig_execute_file(const char *file_path, char *const args[], char *cons
 int netconfig_execute_file_no_wait(const char *file_path,
                char *const args[]);
 int netconfig_execute_clatd(const char *file_path, char *const args[]);
-int netconfig_add_route_ipv6(gchar *interface, gchar *gateway);
-int netconfig_del_route_ipv6(gchar *interface, gchar *gateway);
+int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len);
+int netconfig_del_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len);
 int netconfig_add_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gint address_family);
 int netconfig_del_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gint address_family);
 
index dd871a1..6dd783b 100755 (executable)
@@ -40,6 +40,7 @@ extern "C" {
 #define WIFI_CONFIG_IPV6_DNS_METHOD                    "Nameservers.IPv6method"
 #define WIFI_CONFIG_IPV4_ADDRESS                       "IPv4.local_address"
 #define WIFI_CONFIG_IPV4_SUBNET_MASK                   "IPv4.netmask_prefixlen"
+#define WIFI_CONFIG_IPV6_PREFIX_LEN                    "IPv6.netmask_prefixlen"
 #define WIFI_CONFIG_IPV4_GATEWAY_ADDRESS               "IPv4.gateway"
 #define WIFI_CONFIG_DNS_ADDRESS                        "Nameservers"
 #define WIFI_CONFIG_FAILURE                    "Failure"
index c37ef80..716d7d5 100755 (executable)
@@ -1,6 +1,6 @@
 Name:          net-config
 Summary:       TIZEN Network Configuration service
-Version:       1.1.136
+Version:       1.1.137
 Release:       3
 Group:         System/Network
 License:       Apache-2.0
index 0490866..4f9fc98 100755 (executable)
@@ -226,6 +226,7 @@ static gboolean send_arp(gpointer data)
        int ifindex = 0;
        errno = 0;
        const char *default_ip = NULL;
+       const char *if_name = NULL;
        static int initial_send_arp_count = 0;
 
        if (initial_bursts && initial_send_arp_count >= INITIAL_BURST_ARP_COUNT) {
@@ -272,7 +273,14 @@ static gboolean send_arp(gpointer data)
 
        memset(&net_ifr, 0, sizeof(net_ifr));
        /* ifreq structure creation */
-       size_t if_name_len = strlen(netconfig_get_default_ifname());
+       if_name = netconfig_get_default_ifname();
+       size_t if_name_len = strlen(if_name);
+
+       if (if_name_len == 0) {
+               INFO("Error : Unable to get interface name ");
+               goto err;
+       }
+
        if (if_name_len < sizeof(net_ifr.ifr_name)) {
                memcpy(net_ifr.ifr_name, netconfig_get_default_ifname(), if_name_len);
                net_ifr.ifr_name[if_name_len] = 0;
index 1c08078..e668dd5 100755 (executable)
@@ -744,6 +744,7 @@ static void __netconfig_update_default_connection_info(void)
                }
 
                params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
+               g_variant_builder_unref(builder);
 
                netconfig_dbus_emit_signal(NULL, NETCONFIG_NETWORK_PATH,
                                                   NETCONFIG_NETWORK_INTERFACE, "NetworkConfigChanged",
@@ -787,6 +788,8 @@ static void __netconfig_update_default_connection_info(void)
                                                   params);
                netconfig_set_vconf_int("memory/private/wifi/frequency", 0);
 
+               g_variant_builder_unref(builder);
+
                DBG("Successfully clear IP and PROXY up");
 
        } else if (profile != NULL) {
@@ -897,6 +900,8 @@ static void __netconfig_update_default_connection_info(void)
                                                   NETCONFIG_NETWORK_INTERFACE, "NetworkConfigChanged",
                                                   params);
 
+               g_variant_builder_unref(builder);
+
                DBG("Successfully update default network configuration");
        }
 
@@ -1172,10 +1177,8 @@ void netconfig_update_default_profile(const char *profile)
                netconfig_default_connection_info.freq = 0;
                netconfig_default_connection_info.is_metered = FALSE;
 
-               if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
-                       g_free(netconfig_default_connection_info.essid);
-                       netconfig_default_connection_info.essid = NULL;
-               }
+               g_free(netconfig_default_connection_info.essid);
+               netconfig_default_connection_info.essid = NULL;
        }
 
        /* default profile is NULL and new connected profile is NULL */
@@ -1295,6 +1298,10 @@ static gboolean handle_add_route(
        gchar *const args[] = { "/sbin/route", "add", "-net", ip_addr, gw_str,
                "netmask", netmask, "dev", interface, NULL };
        gchar *const envs[] = { NULL };
+       const gchar* buf = NULL;
+       gchar* ch = NULL;
+       int prefix_len = 0;
+       int pos = 0;
 
        DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
 
@@ -1320,7 +1327,17 @@ static gboolean handle_add_route(
                        return TRUE;
                }
 
-               if (netconfig_add_route_ipv6(interface, gateway) < 0) {
+               buf = ip_addr;
+               ch = strchr(buf, '/');
+               pos = ch - buf + 1;
+               if (ch) {
+                       prefix_len = atoi(ch + 1);
+                       ip_addr[pos-1] = '\0';
+               } else {
+                       prefix_len = 128;
+               }
+
+               if (netconfig_add_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
                        DBG("Failed to add a new route");
                        netconfig_error_permission_denied(context);
                        return TRUE;
@@ -1351,6 +1368,10 @@ static gboolean handle_remove_route(
        gchar *const args[] = { "/sbin/route", "del", "-net", ip_addr, gw_str,
                "netmask", netmask, "dev", interface, NULL };
        char *const envs[] = { NULL };
+       const char* buf = NULL;
+       char* ch = NULL;
+       int prefix_len = 0;
+       int pos = 0;
 
        DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
 
@@ -1374,7 +1395,17 @@ static gboolean handle_remove_route(
                        return TRUE;
                }
 
-               if (netconfig_del_route_ipv6(interface, gateway) < 0) {
+               buf = ip_addr;
+               ch = strchr(buf, '/');
+               pos = ch - buf + 1;
+               if (ch) {
+                       prefix_len = atoi(ch + 1);
+                       ip_addr[pos-1] = '\0';
+               } else {
+                       prefix_len = 128;
+               }
+
+               if (netconfig_del_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
                        DBG("Failed to remove the route");
                        netconfig_error_permission_denied(context);
                        return TRUE;
index e1cd52e..8d7b66b 100755 (executable)
@@ -143,6 +143,8 @@ static void __netconfig_extract_ipv4_signal_data(GVariant *dictionary,
                                params = g_variant_new("(@a{sv})",
                                                                           g_variant_builder_end(builder));
 
+                               g_variant_builder_unref(builder);
+
                                netconfig_dbus_emit_signal(NULL, NETCONFIG_NETWORK_PATH,
                                                   NETCONFIG_NETWORK_INTERFACE, "NetworkConfigChanged",
                                                   params);
@@ -185,6 +187,7 @@ static void __netconfig_extract_ipv6_signal_data(GVariant *dictionary,
 
                                params = g_variant_new("(@a{sv})",
                                                                           g_variant_builder_end(builder));
+                               g_variant_builder_unref(builder);
 
                                netconfig_dbus_emit_signal(NULL, NETCONFIG_NETWORK_PATH,
                                                   NETCONFIG_NETWORK_INTERFACE, "NetworkConfigChanged",
@@ -323,19 +326,6 @@ static void _service_signal_cb(GDBusConnection *conn,
                g_variant_get(variant, "s", &property);
 
                DBG("[%s] %s", property, path);
-               if (netconfig_is_wifi_profile(path) || netconfig_is_ethernet_profile(path)) {
-                       if (g_strcmp0(property, "ready") == 0) {
-                               for (idx = 0; idx < MAX_SOCKET_OPEN_RETRY; idx++) {
-                                       sd = start_ip_conflict_mon();
-                                       if (sd != NULL)
-                                               break;
-                               }
-                       } else if (g_strcmp0(property, "online") == 0) {
-                               // do nothing
-                       } else {
-                               stop_ip_conflict_mon();
-                       }
-               }
 
                if (netconfig_is_wifi_profile(path) == TRUE) {
                        int wifi_state = 0;
@@ -450,12 +440,27 @@ static void _service_signal_cb(GDBusConnection *conn,
                                netconfig_update_default_profile(NULL);
                        }
                }
+
+               if (netconfig_is_wifi_profile(path) || netconfig_is_ethernet_profile(path)) {
+                       if (g_strcmp0(property, "ready") == 0) {
+                               for (idx = 0; idx < MAX_SOCKET_OPEN_RETRY; idx++) {
+                                       sd = start_ip_conflict_mon();
+                                       if (sd != NULL)
+                                               break;
+                               }
+                       } else if (g_strcmp0(property, "online") == 0) {
+                               // do nothing
+                       } else {
+                               stop_ip_conflict_mon();
+                       }
+               }
+
                g_free(property);
        } else if (g_strcmp0(sigvalue, "Proxy") == 0) {
                if (netconfig_is_wifi_profile(path) != TRUE || g_strcmp0(path, netconfig_get_default_profile()) != 0)
                        goto done;
 
-               if (!g_variant_type_equal(variant, G_VARIANT_TYPE_ARRAY))
+               if (!g_variant_is_of_type(variant, G_VARIANT_TYPE_ARRAY))
                        goto done;
 
                g_variant_get(variant, "a{sv}", &iter);
@@ -479,6 +484,7 @@ static void _service_signal_cb(GDBusConnection *conn,
 
                                sig_params = g_variant_new("(@a{sv})",
                                                                g_variant_builder_end(builder));
+                               g_variant_builder_unref(builder);
 
                                netconfig_dbus_emit_signal(NULL, NETCONFIG_NETWORK_PATH,
                                                   NETCONFIG_NETWORK_INTERFACE, "NetworkConfigChanged",
@@ -500,6 +506,7 @@ static void _service_signal_cb(GDBusConnection *conn,
 
                                        sig_params = g_variant_new("(@a{sv})",
                                                                g_variant_builder_end(builder));
+                                       g_variant_builder_unref(builder);
 
                                        netconfig_dbus_emit_signal(NULL, NETCONFIG_NETWORK_PATH,
                                                           NETCONFIG_NETWORK_INTERFACE,
index e4dbc3f..27c2238 100755 (executable)
@@ -34,9 +34,6 @@
 #include <vconf-keys.h>
 #include <tzplatform_config.h>
 #include <system_info.h>
-#include <stdint.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
 
 #include "log.h"
 #include "util.h"
 #define HEADED_PLUGIN_FILEPATH         "/usr/lib/net-config-plugin-headed.so"
 #define TELEPHONY_PLUGIN_FILEPATH      "/usr/lib/net-config-plugin-telephony.so"
 
-typedef struct {
-       uint8_t family;
-       uint8_t bytelen;
-       int16_t bitlen;
-       uint32_t flags;
-       uint32_t data[8];
-} netconfig_inet_prefix_s;
-
-typedef struct {
-       int                     fd;
-       struct sockaddr_nl      local;
-       struct sockaddr_nl      peer;
-       uint32_t                seq;
-       uint32_t                dump;
-} netconfig_rtnl_s;
-netconfig_rtnl_s rth = { .fd = -1 };
-
 static gboolean netconfig_device_picker_test = FALSE;
 static int mdnsd_ref_count = 0;
 typedef struct {
@@ -782,190 +762,36 @@ int netconfig_del_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gi
        return 1;
 }
 
-static int __netconfig_rtnl_talk(netconfig_rtnl_s *rtnl, struct nlmsghdr *n, pid_t peer,
-               unsigned groups, struct nlmsghdr *answer)
+int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
 {
-       struct nlmsghdr *h;
-       struct sockaddr_nl nladdr;
-       struct iovec iov = {
-               .iov_base = (void*)n,
-               .iov_len = n->nlmsg_len
-       };
-       struct msghdr msg = {
-               .msg_name = &nladdr,
-               .msg_namelen = sizeof(nladdr),
-               .msg_iov = &iov,
-               .msg_iovlen = 1,
-       };
-       int status;
-       unsigned seq;
-       char buf[16384];
+       struct in6_rtmsg rt;
+       int fd = 0;
+       int err = 0;
        char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
 
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-       nladdr.nl_pid = peer;
-       nladdr.nl_groups = groups;
+       memset(&rt, 0, sizeof(rt));
 
-       n->nlmsg_seq = seq = ++rtnl->seq;
+       rt.rtmsg_dst_len = prefix_len;
 
-       if (answer == NULL)
-               n->nlmsg_flags |= NLM_F_ACK;
+       rt.rtmsg_flags = RTF_UP | RTF_HOST;
 
-       status = sendmsg(rtnl->fd, &msg, 0);
-       if (status < 0) {
-               DBG("failed to send message to kernel, status: %d", status);
+       errno = 0;
+       if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
+               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+               DBG("inet_pton failed : %s", error_buf);
                return -1;
        }
 
-       memset(buf, 0, sizeof(buf));
-
-       iov.iov_base = buf;
-
-       while (1) {
-               iov.iov_len = sizeof(buf);
-               status = recvmsg(rtnl->fd, &msg, 0);
-               DBG("status: %d", status);
-
-               if (status < 0) {
-                       if (errno == EINTR || errno == EAGAIN)
-                               continue;
+       if (gateway != NULL) {
+               rt.rtmsg_flags |= RTF_GATEWAY;
+               if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
                        strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
-                       DBG("netlink receive error %s (%d)", error_buf, errno);
-                       return -1;
-               }
-               if (status == 0) {
-                       DBG("EOF on netlink");
-                       return -1;
-               }
-               if (msg.msg_namelen != sizeof(nladdr)) {
-                       DBG("sender address length == %d", msg.msg_namelen);
-                       return -1;
-               }
-               for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
-                       int len = h->nlmsg_len;
-                       int l = len - sizeof(*h);
-
-                       if (l < 0 || len > status) {
-                               if (msg.msg_flags & MSG_TRUNC) {
-                                       DBG("truncated message");
-                                       return -1;
-                               }
-                               DBG("malformed message: len=%d", len);
-                               return -1;
-                       }
-
-                       if (nladdr.nl_pid != peer ||
-                                       h->nlmsg_pid != rtnl->local.nl_pid ||
-                                       h->nlmsg_seq != seq) {
-                               /** Don't forget to skip that message. */
-                               status -= NLMSG_ALIGN(len);
-                               h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
-                               continue;
-                       }
-
-                       if (h->nlmsg_type == NLMSG_ERROR) {
-                               struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
-                               if (l < sizeof(struct nlmsgerr)) {
-                                       DBG("Error truncated message");
-                               } else {
-                                       if (!err->error) {
-                                               if (answer)
-                                                       memcpy(answer, h, h->nlmsg_len);
-                                               return 0;
-                                       }
-
-                                       errno = -err->error;
-                                       strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
-                                       DBG("RTNETLINK answers: %s", error_buf);
-                               }
-                               return -1;
-                       }
-                       if (answer) {
-                               memcpy(answer, h, h->nlmsg_len);
-                               return 0;
-                       }
-
-                       DBG("Unexpected reply");
-
-                       status -= NLMSG_ALIGN(len);
-                       h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
-               }
-               if (msg.msg_flags & MSG_TRUNC) {
-                       DBG("Message truncated");
-                       continue;
-               }
-               if (status) {
-                       DBG("Remnant of size %d", status);
-                       return -1;
-               }
-       }
-}
-
-static int __netconfig_get_prefix(netconfig_inet_prefix_s *dst, char *arg, int family)
-{
-       if (family != AF_UNSPEC && family != AF_INET6) {
-               DBG("Error: invalid address family.");
-               return -1;
-       }
-
-       memset(dst, 0, sizeof(*dst));
-
-       if (strchr(arg, ':')) {
-               dst->family = AF_INET6;
-               if (inet_pton(AF_INET6, arg, dst->data) <= 0) {
-                       DBG("Error: invalid ipv6 address.");
+                       DBG("inet_pton failed : %s", error_buf);
                        return -1;
                }
-               dst->bytelen = 16;
-               dst->bitlen = 128;
-       }
-
-       return 0;
-}
-
-static int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
-               int alen)
-{
-       int len = RTA_LENGTH(alen);
-       struct rtattr *rta;
-
-       if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
-               DBG("Error message exceeded bound of %d", maxlen);
-               return -1;
        }
-       rta = NLMSG_TAIL(n);
-       rta->rta_type = type;
-       rta->rta_len = len;
-       memcpy(RTA_DATA(rta), data, alen);
-       n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
-
-       return 0;
-}
 
-static int __netconfig_iproute_modify(int cmd, unsigned flags, char *interface, char *ip_addr)
-{
-       struct {
-               struct nlmsghdr n;
-               struct rtmsg    r;
-               char            buf[1024];
-       } req;
-
-       struct ifreq ifr;
-       int fd, idx, ret;
-       char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
-
-       memset(&req, 0, sizeof(req));
-
-       req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
-       req.n.nlmsg_flags = NLM_F_REQUEST|flags;
-       req.n.nlmsg_type = cmd;
-       req.r.rtm_family = AF_INET6;
-
-       if (cmd != RTM_DELROUTE) {
-               req.r.rtm_protocol = RTPROT_BOOT;
-               req.r.rtm_type = RTN_UNICAST;
-       }
+       rt.rtmsg_metric = 1;
 
        fd = socket(AF_INET6, SOCK_DGRAM, 0);
        if (fd < 0) {
@@ -974,144 +800,78 @@ static int __netconfig_iproute_modify(int cmd, unsigned flags, char *interface,
                return -1;
        }
 
-       memset(&ifr, 0, sizeof(ifr));
-       strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1);
-       ioctl(fd, SIOCGIFINDEX, &ifr);
-       idx = ifr.ifr_ifindex;
-       close(fd);
+       rt.rtmsg_ifindex = 0;
 
-       if (ifr.ifr_ifindex == 0) {
-               DBG("Cannot find device %s", interface);
-               return -1;
+       if (interface) {
+               struct ifreq ifr;
+               memset(&ifr, 0, sizeof(ifr));
+               strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1);
+               ioctl(fd, SIOCGIFINDEX, &ifr);
+               rt.rtmsg_ifindex = ifr.ifr_ifindex;
        }
 
-       netconfig_inet_prefix_s dst;
-
-       ret = __netconfig_get_prefix(&dst, ip_addr, req.r.rtm_family);
-       if (ret < 0)
+       if ((err = ioctl(fd, SIOCADDRT, &rt)) < 0) {
+               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+               DBG("Failed to add route: %s", error_buf);
+               close(fd);
                return -1;
-
-       req.r.rtm_dst_len = dst.bitlen;
-       if (dst.bytelen) {
-               ret = addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen);
-               if (ret < 0)
-                       return -1;
        }
 
-       ret = addattr_l(&req.n, sizeof(req), RTA_OIF, &idx, sizeof(uint32_t));
-       if (ret < 0)
-               return -1;
-
-       if (__netconfig_rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) {
-               DBG("__netconfig_rtnl_talk failed");
-               return -1;
-       }
+       close(fd);
 
-       return 0;
+       return 1;
 }
 
-static void __netconfig_rtnl_close()
+int netconfig_del_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
 {
-       if (rth.fd >= 0) {
-               close(rth.fd);
-               rth.fd = -1;
-       }
-}
+       struct in6_rtmsg rt;
+       int fd = 0;
+       int err = 0;
 
-static int __netconfig_rtnl_open(netconfig_rtnl_s *rth, unsigned subscriptions,
-               int protocol)
-{
-       socklen_t addr_len;
-       int sndbuf = 32768;
-       int rcvbuf = 1024 * 1024;
-       char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
+       memset(&rt, 0, sizeof(rt));
 
-       memset(rth, 0, sizeof(*rth));
+       rt.rtmsg_dst_len = prefix_len;
 
-       rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
-       if (rth->fd < 0) {
-               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
-               DBG("Failed to open netlink socket: %s", error_buf);
-               return -1;
-       }
+       rt.rtmsg_flags = RTF_UP | RTF_HOST;
 
-       if (setsockopt(rth->fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0) {
-               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
-               DBG("Failed to set option(SO_SNDBUF) on socket [Error: %s]", error_buf);
-               return -1;
+       if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
+               err = -errno;
+               return err;
        }
 
-       if (setsockopt(rth->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0) {
-               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
-               DBG("Failed to set option(SO_RCVBUF) on socket [Error: %s]", error_buf);
-               return -1;
+       if (gateway != NULL) {
+               rt.rtmsg_flags |= RTF_GATEWAY;
+               if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
+                       err = -errno;
+                       return err;
+               }
        }
 
-       memset(&rth->local, 0, sizeof(rth->local));
-       rth->local.nl_family = AF_NETLINK;
-       rth->local.nl_groups = subscriptions;
-
-       if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
-               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
-               DBG("Failed to bind netlink socket [Error: %s]", error_buf);
-               return -1;
-       }
+       rt.rtmsg_metric = 1;
 
-       addr_len = sizeof(rth->local);
-       if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
-               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
-               DBG("Failed to getsockname [Error: %s]", error_buf);
-               return -1;
-       }
-       if (addr_len != sizeof(rth->local)) {
-               DBG("Wrong address length %d", addr_len);
-               return -1;
-       }
-       if (rth->local.nl_family != AF_NETLINK) {
-               DBG("Wrong address family %d", rth->local.nl_family);
+       fd = socket(AF_INET6, SOCK_DGRAM, 0);
+       if (fd < 0)
                return -1;
-       }
-       rth->seq = time(NULL);
 
-       return 0;
-}
-
-int netconfig_add_route_ipv6(gchar *interface, gchar *gateway)
-{
-       int ret = __netconfig_rtnl_open(&rth, 0, NETLINK_ROUTE);
-       if (ret < 0) {
-               DBG("Failed to open rtnl socket");
-               return -1;
-       }
+       rt.rtmsg_ifindex = 0;
 
-       ret = __netconfig_iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_EXCL, interface, gateway);
-       if (ret < 0) {
-               DBG("Failed to modify ipv6 route.");
-               __netconfig_rtnl_close();
-               return -1;
+       if (interface) {
+               struct ifreq ifr;
+               memset(&ifr, 0, sizeof(ifr));
+               strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1);
+               ioctl(fd, SIOCGIFINDEX, &ifr);
+               rt.rtmsg_ifindex = ifr.ifr_ifindex;
        }
 
-       __netconfig_rtnl_close();
-       return 0;
-}
-
-int netconfig_del_route_ipv6(gchar *interface, gchar *gateway)
-{
-       int ret = __netconfig_rtnl_open(&rth, 0, NETLINK_ROUTE);
-       if (ret < 0) {
-               DBG("Failed to open rtnl socket");
+       if ((err = ioctl(fd, SIOCDELRT, &rt)) < 0) {
+               DBG("Failed to del route: %d\n", err);
+               close(fd);
                return -1;
        }
 
-       ret = __netconfig_iproute_modify(RTM_DELROUTE, NLM_F_CREATE|NLM_F_EXCL, interface, gateway);
-       if (ret < 0) {
-               DBG("Failed to delete ipv6 route.");
-               __netconfig_rtnl_close();
-               return -1;
-       }
+       close(fd);
 
-       __netconfig_rtnl_close();
-       return 0;
+       return 1;
 }
 
 gboolean handle_launch_direct(Wifi *wifi, GDBusMethodInvocation *context)
@@ -1587,6 +1347,9 @@ bool netconfig_check_feature_supported(netconfig_supported_feature_e feature)
                case NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT:
                        key = WIFI_DIRECT_FEATURE;
                        break;
+               case NETCONFIG_SUPPORTED_FEATURE_WIFI_SOFTAP:
+                       key = WIFI_SOFTAP_FEATURE;
+                       break;
                default:
                        ERR("Uknown feature");
                        return false;
index 0f925f9..f285c52 100755 (executable)
@@ -436,6 +436,7 @@ static int  __netconfig_wifi_bssid_create_interface(void)
        builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
        g_variant_builder_add(builder, "{sv}", key, g_variant_new_string(val));
        message = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
+       g_variant_builder_unref(builder);
 
        g_dbus_connection_call(connection,
                        SUPPLICANT_SERVICE,
index 1643e2c..1c7ae99 100755 (executable)
@@ -123,6 +123,7 @@ static void __free_wifi_configuration(struct wifi_config *conf)
                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) {
@@ -346,55 +347,64 @@ 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->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;
-       prefix_len = g_key_file_get_integer(keyfile, group_name,
-                                                                         WIFI_CONFIG_IPV4_SUBNET_MASK, NULL);
-       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;
+       if (config->ip_info) {
+               GError *error = NULL;
+               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;
+               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);
                }
-               g_strfreev(nameservers);
        }
 
 
@@ -1078,6 +1088,9 @@ gboolean handle_load_configuration(Wifi *wifi, GDBusMethodInvocation *context,
        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));
 
@@ -1200,6 +1213,13 @@ gboolean handle_save_configuration(Wifi *wifi, GDBusMethodInvocation *context,
                        } 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));
@@ -1288,11 +1308,16 @@ gboolean handle_save_configuration(Wifi *wifi, GDBusMethodInvocation *context,
        if (conf->ip_info->subnet_mask != NULL) {
                unsigned char prefix_len;
                prefix_len = __netconfig_convert_netmask_to_prefixlen(
-                                                                 conf->ip_info->subnet_mask);
-               g_key_file_set_integer(keyfile, group_name,
-                                                WIFI_CONFIG_IPV4_SUBNET_MASK, prefix_len);
+                               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);
@@ -1339,10 +1364,12 @@ gboolean handle_load_eap_configuration(Wifi *wifi, GDBusMethodInvocation *contex
 
        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);
        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);
index 812755f..ba63664 100755 (executable)
@@ -131,7 +131,8 @@ static int __netconfig_p2p_firmware_stop(void)
 
 static int __netconfig_softap_firmware_start(void)
 {
-       if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING))
+       if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING)
+                       && !netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_SOFTAP))
                return -ENODEV;
 
        int rv = 0;
@@ -152,7 +153,8 @@ static int __netconfig_softap_firmware_start(void)
 
 static int __netconfig_softap_firmware_stop(void)
 {
-       if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING))
+       if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING)
+                       && !netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_SOFTAP))
                return -ENODEV;
 
        int rv = 0;
index 86fd4d8..dd6c7b5 100755 (executable)
@@ -118,25 +118,72 @@ static int __netconfig_wifi_update_and_get_rssi(void)
        return rssi_dbm;
 }
 
-int netconfig_wifi_rssi_level(const int rssi_dbm)
+static int __netconfig_wifi_convert_dbm_to_level_24(int rssi_dbm)
 {
-       int snr_level = 0;
+       int rssi_level = 0;
 
-       /* Wi-Fi Signal Strength Display
+       /* Wi-Fi Signal Strength Display (for 2.4G (dB))
         *
-        * Excellent :  -63 ~
-        * Good:                -74 ~ -64
-        * Weak:                -82 ~ -75
-        * Very weak:           ~ -83
+        * Excellent :     ~ -63
+        * Good      : -64 ~ -74
+        * Weak      : -75 ~ -82
+        * Very weak : -83 ~ -88
+        * No signal : -89 ~
         */
+
        if (rssi_dbm >= -63)
-               snr_level = 4;
+               rssi_level = 4;
        else if (rssi_dbm >= -74)
-               snr_level = 3;
+               rssi_level = 3;
        else if (rssi_dbm >= -82)
-               snr_level = 2;
+               rssi_level = 2;
+       else if (rssi_dbm >= -88)
+               rssi_level = 1;
+       else
+               rssi_level = 0;
+
+       return rssi_level;
+}
+
+static int __netconfig_wifi_convert_dbm_to_level_50(int rssi_dbm)
+{
+       int rssi_level = 0;
+
+       /* Wi-Fi Signal Strength Display (for 5G (dB))
+        *
+        * Excellent :     ~ -72
+        * Good      : -73 ~ -78
+        * Weak      : -79 ~ -83
+        * Very weak : -84 ~ -88
+        * No signal : -89 ~
+        */
+
+       if (rssi_dbm >= -72)
+               rssi_level = 4;
+       else if (rssi_dbm >= -78)
+               rssi_level = 3;
+       else if (rssi_dbm >= -83)
+               rssi_level = 2;
+       else if (rssi_dbm >= -88)
+               rssi_level = 1;
+       else
+               rssi_level = 0;
+
+       return rssi_level;
+}
+
+int netconfig_wifi_rssi_level(const int rssi_dbm)
+{
+       int snr_level = 0;
+       int freq = 0;
+       int ret = 0;
+
+       ret = netconfig_vconf_get_int("memory/private/wifi/frequency", &freq);
+
+       if (!ret && freq > 4900)
+               snr_level = __netconfig_wifi_convert_dbm_to_level_50(rssi_dbm);
        else
-               snr_level = 1;
+               snr_level = __netconfig_wifi_convert_dbm_to_level_24(rssi_dbm);
 
        return snr_level;
 }
index d47a352..8d3303a 100755 (executable)
@@ -22,6 +22,8 @@
 #include <unistd.h>
 #include <vconf.h>
 #include <vconf-keys.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
 #include "log.h"
 #include "wifi.h"
@@ -46,6 +48,7 @@
 #include "wifi-extension.h"
 
 #define SPRD_CP2_FIRMWARE_PATH "/usr/bin/cp2-downloader"
+#define SPRD_CP2_FIRMWARE_STATE_PATH "/tmp/.wifi-firmware-loaded"
 static int is_wifi_firmware_downloaded = FALSE;
 
 static Wifi *wifi_object = NULL;
@@ -111,6 +114,30 @@ void __netconfig_wifi_connect_reply(GObject *source_object, GAsyncResult *res,
        return;
 }
 
+static void _update_wifi_firmware_state(void)
+{
+       int fd;
+       mode_t mode = S_IRGRP | S_IWUSR | S_IXGRP;
+
+       fd = creat(SPRD_CP2_FIRMWARE_STATE_PATH, mode);
+       if (fd >= 0)
+               close(fd);
+       else
+               DBG("Failed to create wifi firmware state file");
+
+       is_wifi_firmware_downloaded = TRUE;
+}
+
+static int _get_wifi_firmware_state(void)
+{
+       if (!is_wifi_firmware_downloaded
+                       && access(SPRD_CP2_FIRMWARE_STATE_PATH, F_OK) != 0)
+               is_wifi_firmware_downloaded = FALSE;
+       else
+               is_wifi_firmware_downloaded = TRUE;
+       return is_wifi_firmware_downloaded;
+}
+
 int wifi_firmware_download(void)
 {
        int rv = 0;
@@ -118,13 +145,13 @@ int wifi_firmware_download(void)
        char *const args[] = { SPRD_CP2_FIRMWARE_PATH, NULL };
        char *const envs[] = { NULL };
 
-       if (!is_wifi_firmware_downloaded) {
+       if (!_get_wifi_firmware_state()) {
                rv = netconfig_execute_file(path, args, envs);
                if (rv < 0) {
                        DBG("wifi firmware download fails");
                        return -EIO;
                }
-               is_wifi_firmware_downloaded = TRUE;
+               _update_wifi_firmware_state();
                DBG("wifi firmware download successes");
        }