src/wifi-config.c
src/wifi-extension.c
src/ip-conflict-detect.c
+ src/clatd-handler.c
)
IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
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
#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;
}
#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
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);
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);
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;
+}
#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"
GVariantIter *iter;
const gchar *value = NULL;
struct sock_data *sd = NULL;
+ gchar *pf = NULL;
int idx = 0;
if (path == NULL || param == NULL)
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))
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;