From: Jaehyun Kim Date: Fri, 16 Aug 2019 13:13:16 +0000 (+0900) Subject: Added support to enable clatd service X-Git-Tag: submit/tizen/20190927.130602~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=159b7574b60911318f349e63ef50703cdbe57954;p=platform%2Fcore%2Fconnectivity%2Fnet-config.git Added support to enable clatd service Change-Id: I943f9e5be057a1dc9959f7a36e00397777b6bd45 Signed-off-by: Jaehyun Kim --- diff --git a/CMakeLists.txt b/CMakeLists.txt index b210f77..71d17c9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ SET(SRCS src/wifi-config.c src/wifi-extension.c src/ip-conflict-detect.c + src/clatd-handler.c ) IF("${CMAKE_BUILD_TYPE}" STREQUAL "") diff --git a/include/network-state.h b/include/network-state.h index a38b1af..ee624d4 100755 --- a/include/network-state.h +++ b/include/network-state.h @@ -43,6 +43,12 @@ char *netconfig_get_ifname(const char *profile); void state_object_create_and_init(void); void state_object_deinit(void); +#define MAX_DNS 2 +struct clatd_ctrl_hint { + char *nameserver[MAX_DNS]; +}; +char *netconfig_get_connected_cellular_internet_ipv6only_profile(struct clatd_ctrl_hint *hint); + #ifdef __cplusplus } #endif diff --git a/src/clatd-handler.c b/src/clatd-handler.c index b953eed..4d442f4 100755 --- a/src/clatd-handler.c +++ b/src/clatd-handler.c @@ -23,74 +23,126 @@ #include "log.h" #include "util.h" #include "network-state.h" +#include "netdbus.h" #include "clatd-handler.h" -#define CLAT_EXEC_PATH "/usr/sbin/clatd" -#define ROUTE_EXEC_PATH "/sbin/route" -#define KILLALL_EXEC_PATH "/usr/bin/killall" -#define IFCONFIG_EXEC_PATH "/sbin/ifconfig" +#define CLATD_SERVICE "com.samsung.clatd" +#define CLATD_PATH "/com/samsung/clatd" +#define CLATD_INTERFACE "com.samsung.clatd.Control" -char g_ifname[32] = {0, }; +static gboolean g_is_running = FALSE; -int netconfig_clatd_enable(void) +static void __netconfig_clatd_async_callback(GObject *source_object, + GAsyncResult *res, gpointer user_data) { - int rv = 0; + GDBusConnection *conn = NULL; + GVariant *reply = NULL; + GError *error = NULL; + DBG("__netconfig_clatd_async_callback"); + + conn = G_DBUS_CONNECTION(source_object); + reply = g_dbus_connection_call_finish(conn, res, &error); + if (error) { + ERR("Dbus error : %s", error->message); + g_error_free(error); + } else { + int is_clat_enabled = -1; + g_variant_get(reply, "(i)", &is_clat_enabled); + + if (is_clat_enabled == 0) { + DBG("OK"); + } else if (is_clat_enabled == 1) { + INFO("already on going"); + g_is_running = TRUE; + } else { + ERR("Failed to clat enable, %d", is_clat_enabled); + } + } - if (g_ifname[0] != '\0') { - rv = netconfig_clatd_disable(); + if (reply) + g_variant_unref(reply); +} - if (rv < 0) { - DBG("Failed to disable existing clatd process"); - return -1; - } +int netconfig_clatd_enable(void) +{ + DBG(""); + GVariant *params = NULL; + GVariantBuilder *builder = NULL; + gboolean rv = FALSE; + struct clatd_ctrl_hint hint = {0 ,}; + char ns_buff[256] = {0, }; + + if (g_is_running) { + INFO("clatd is already ENABLED"); + return 0; } const char *if_name = netconfig_get_default_ifname(); - if (if_name == NULL) { - DBG("There is no interface name"); + int idx; + for (idx = 0; idx < MAX_DNS; idx++) + g_free(hint.nameserver[idx]); + + ERR("There is no interface name"); return -1; + } else { + DBG("if_name : %s", if_name); } - memset(g_ifname, 0, sizeof(g_ifname)); - g_strlcat(g_ifname, if_name, 32); + builder = g_variant_builder_new(G_VARIANT_TYPE ("a{is}")); - const char *path = CLAT_EXEC_PATH; - char *const args[] = { "/usr/sbin/clatd", "-i", g_ifname, NULL }; + g_variant_builder_add(builder, "{is}", 'i', if_name); - rv = netconfig_execute_clatd(path, args); + // nameserver addresses + if (hint.nameserver[0] != NULL || hint.nameserver[1] != NULL) { + g_snprintf(ns_buff, 256, "%s;%s", + ((hint.nameserver[0] != NULL) ? hint.nameserver[0] : "NULL"), + ((hint.nameserver[1] != NULL) ? hint.nameserver[1] : "NULL")); + } + g_variant_builder_add(builder, "{is}", 'd', ns_buff); + + params = g_variant_builder_end(builder); + g_variant_builder_unref(builder); + + rv = netconfig_invoke_dbus_method_nonblock(CLATD_SERVICE, CLATD_PATH, + CLATD_INTERFACE, "Start", g_variant_new("(@a{is})", params), __netconfig_clatd_async_callback); + + if (!rv) { + DBG("Failed to dbus call"); + g_variant_unref(params); - if (rv < 0) { - DBG("Failed to enable clatd process %d", rv); + int idx; + for (idx = 0; idx < MAX_DNS; idx++) + g_free(hint.nameserver[idx]); return -1; } - DBG("Successfully enabled clatd process with %s interface", g_ifname); + g_is_running = TRUE; + DBG("clatd enabled[%d]", g_is_running); + int idx; + for (idx = 0; idx < MAX_DNS; idx++) + g_free(hint.nameserver[idx]); return 0; } int netconfig_clatd_disable(void) { - int rv = 0; + DBG(""); + gboolean rv = FALSE; - const char *path = KILLALL_EXEC_PATH; - char *const args[] = { "/usr/bin/kill -15", "clatd", NULL }; - char *const envs[] = { NULL }; - - if (g_ifname[0] == '\0') { - DBG("There is no clatd process"); - return -1; + if (!g_is_running) { + ERR("clatd is already DISABLED"); + return 0; } - memset(g_ifname, 0, sizeof(g_ifname)); - - rv = netconfig_execute_file(path, args, envs); - - if (rv < 0) { - DBG("Failed to disable clatd process %d", rv); + rv = netconfig_invoke_dbus_method_nonblock(CLATD_SERVICE, CLATD_PATH, + CLATD_INTERFACE, "Stop", NULL, NULL); + g_is_running = FALSE; + DBG("clatd disabled[%d]", g_is_running); + if (!rv) { + DBG("Failed to dbus call"); return -1; } - DBG("Successfully disable clatd process");; return 0; } diff --git a/src/network-state.c b/src/network-state.c index 428550c..84de50a 100755 --- a/src/network-state.c +++ b/src/network-state.c @@ -38,6 +38,7 @@ #include "network-dpm.h" #include "network-monitor.h" #include "netsupplicant.h" +#include "clatd-handler.h" #if defined TIZEN_DEBUG_ENABLE #include "network-dump.h" #endif @@ -792,6 +793,9 @@ static void __netconfig_update_default_connection_info(void) DBG("Successfully clear IP and PROXY up"); + /* Try to disable CLATD if it was enabled */ + DBG("Disable clatd"); + netconfig_clatd_disable(); } else if (profile != NULL) { char *old_ip = vconf_get_str(VCONFKEY_NETWORK_IP); char *old_ip6 = vconf_get_str(VCONFKEY_NETWORK_IP6); @@ -828,6 +832,11 @@ static void __netconfig_update_default_connection_info(void) netconfig_set_system_event(SYS_EVT_NETWORK_STATUS, EKEY_NETWORK_STATUS, EVAL_NETWORK_CELLULAR); + /* Enable clatd if IPv6 is set and no IPv4 address */ + if (!ip_addr && ip_addr6) { + DBG("Enable clatd"); + netconfig_clatd_enable(); + } } else if (netconfig_is_ethernet_profile(profile) == TRUE) { netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_ETHERNET); @@ -1571,3 +1580,118 @@ void state_object_deinit(void) g_object_unref(tcpdump_object); #endif } + +static gboolean __netconfig_check_ipv6_address(const char *address) +{ + unsigned char buf[sizeof(struct in6_addr)]; + int err; + + if (!address) + return FALSE; + + err = inet_pton(AF_INET6, address, buf); + if (err > 0) + return TRUE; + + return FALSE; +} + +char *netconfig_get_connected_cellular_internet_ipv6only_profile(struct clatd_ctrl_hint *hint) +{ + GVariant *message = NULL; + GVariantIter *iter = NULL; + GVariantIter *next = NULL; + gchar *cellular_internet_profile = NULL; + gchar *object_path = NULL; + + message = netconfig_invoke_dbus_method(CONNMAN_SERVICE, + CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, + "GetServices", NULL); + if (message == NULL) { + ERR("Failed to get profiles"); + return NULL; + } + + g_variant_get(message, "(a(oa{sv}))", &iter); + while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) { + if (object_path == NULL) + continue; + + if (netconfig_is_cellular_profile(object_path) == FALSE) + continue; + + if (netconfig_is_cellular_internet_profile(object_path) == FALSE) + continue; + + if (__netconfig_is_connected(next) == TRUE) { + DBG("found connected profiles"); + gchar *key = NULL; + gboolean has_v4 = FALSE, has_v6 = FALSE; + + GVariant *variant = NULL; + while (g_variant_iter_loop(next, "{sv}", &key, &variant)) { + if (g_strcmp0(key, "IPv4") == 0) { + GVariantIter *ipv4_iter = NULL; + GVariant *ipv4_variant = NULL; + gchar *ipv4_key = NULL; + const gchar *ipv4_value = NULL; + g_variant_get(variant, "a{sv}", &ipv4_iter); + while (g_variant_iter_loop(ipv4_iter, "{sv}", + &ipv4_key, &ipv4_variant)) { + if (g_strcmp0(ipv4_key, "Address") == 0) { + ipv4_value = g_variant_get_string(ipv4_variant, NULL); + DBG("ipv4: %s", ipv4_value); + has_v4 = TRUE; + } + } + g_variant_iter_free (ipv4_iter); + } else if (g_strcmp0(key, "IPv6") == 0) { + GVariantIter *ipv6_iter = NULL; + GVariant *ipv6_variant = NULL; + gchar *ipv6_key = NULL; + const gchar *ipv6_value = NULL; + g_variant_get(variant, "a{sv}", &ipv6_iter); + while (g_variant_iter_loop(ipv6_iter, "{sv}", + &ipv6_key, &ipv6_variant)) { + if (g_strcmp0(ipv6_key, "Address") == 0) { + ipv6_value = g_variant_get_string(ipv6_variant, NULL); + DBG("ipv6: %s", ipv6_value); + has_v6 = TRUE; + } + } + g_variant_iter_free (ipv6_iter); + } else if (hint && g_strcmp0(key, "Nameservers") == 0) { + int idx = 0; + GVariantIter *ns_iter = NULL; + gchar *nameserver = NULL; + g_variant_get(variant, "as", &ns_iter); + while(g_variant_iter_loop(ns_iter, "s", &nameserver)) { + INFO("nameserver[%d]: %s", idx, nameserver); + if (idx >= MAX_DNS) { + INFO("index exceeded %d -- skip", idx); + continue; + } + if (__netconfig_check_ipv6_address(nameserver) == TRUE) { + hint->nameserver[idx] = g_strdup(nameserver); + idx++; + } else { + INFO("malformed address %s -- skip", nameserver); + } + } + } + } + + if (!has_v4 && has_v6) { + DBG("found 'ipv6-only/connected/internet cellular profile'"); + cellular_internet_profile = g_strdup(object_path); + g_free(object_path); + g_variant_iter_free(next); + break; + } + } + } + g_variant_iter_free(iter); + g_variant_unref(message); + + return cellular_internet_profile; +} diff --git a/src/signal-handler.c b/src/signal-handler.c index d653171..9a57730 100755 --- a/src/signal-handler.c +++ b/src/signal-handler.c @@ -41,6 +41,7 @@ #include "wifi-tdls.h" #include "ip-conflict-detect.h" #include "wifi-key-encryption.h" +#include "clatd-handler.h" #if defined TIZEN_DEBUG_ENABLE #include "network-dump.h" #define NETWORK_LOG_DUMP_SCRIPT "/opt/var/lib/net-config/network_log_dump.sh" @@ -310,6 +311,7 @@ static void _service_signal_cb(GDBusConnection *conn, GVariantIter *iter; const gchar *value = NULL; struct sock_data *sd = NULL; + gchar *pf = NULL; int idx = 0; if (path == NULL || param == NULL) @@ -403,6 +405,16 @@ static void _service_signal_cb(GDBusConnection *conn, if (netconfig_is_cellular_internet_profile(path)) netconfig_update_default_profile(path); } + } else { + pf = netconfig_get_connected_cellular_internet_ipv6only_profile(NULL); + if (pf) + { + g_free(pf); + + /* Enable clatd if it is not in running state */ + DBG("Connected to ipv6 only cellular, enable clatd"); + netconfig_clatd_enable(); + } } if (netconfig_is_cellular_profile(path) && netconfig_is_cellular_internet_profile(path)) @@ -414,9 +426,14 @@ static void _service_signal_cb(GDBusConnection *conn, goto done; } - if (netconfig_is_cellular_profile(path) && netconfig_is_cellular_internet_profile(path)) + if (netconfig_is_cellular_profile(path) && netconfig_is_cellular_internet_profile(path)) { cellular_state_set_service_state(NETCONFIG_CELLULAR_IDLE); + /* Disable clatd if it is in running state */ + DBG("disable clatd"); + netconfig_clatd_disable(); + } + if (g_strcmp0(path, netconfig_get_default_profile()) != 0) { g_free(property); goto done;