Merge "[Fix] Dereference after free in sta_remove_callback()" into tizen
[platform/upstream/connman.git] / plugins / telephony.c
old mode 100644 (file)
new mode 100755 (executable)
index 63e7f6e..5c37d88
@@ -2,7 +2,7 @@
  *
  *  Connection Manager
  *
- *  Copyright (C) 2011-2013  Samsung Electronics Co., Ltd. All rights reserved.
+ *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
  *
  */
 
-
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include <errno.h>
-#include <stdlib.h>
-
 #include <gdbus.h>
+#include <stdlib.h>
 #include <string.h>
 
 #define CONNMAN_API_SUBJECT_TO_CHANGE
-#include <connman/plugin.h>
-#include <connman/device.h>
-#include <connman/network.h>
-#include <connman/ipconfig.h>
 #include <connman/dbus.h>
 #include <connman/inet.h>
+#include <connman/plugin.h>
+#include <connman/network.h>
+#include <connman/setting.h>
 #include <connman/technology.h>
-#include <connman/log.h>
+
+#include <connman.h>
 
 #define PS_DBUS_SERVICE                                "com.tcore.ps"
+#define TELEPHONY_DBUS_SERVICE                 "org.tizen.telephony"
 
-#define PS_MASTER_INTERFACE            PS_DBUS_SERVICE ".master"
-#define PS_MODEM_INTERFACE             PS_DBUS_SERVICE ".modem"
+#define PS_MASTER_INTERFACE                    PS_DBUS_SERVICE ".master"
+#define PS_MODEM_INTERFACE                     PS_DBUS_SERVICE ".modem"
 #define PS_SERVICE_INTERFACE           PS_DBUS_SERVICE ".service"
 #define PS_CONTEXT_INTERFACE           PS_DBUS_SERVICE ".context"
 
 /* methods */
-#define GET_MODEMS                     "GetModems"
+#define GET_MODEMS                             "GetModems"
 #define GET_SERVICES                   "GetServices"
 #define GET_CONTEXTS                   "GetContexts"
 #define ACTIVATE_CONTEXT               "Activate"
@@ -57,7 +56,7 @@
 #define SET_PROPERTY                   "SetProperties"
 
 /* signals */
-#define MODEM_ADDED                    "ModemAdded"
+#define MODEM_ADDED                            "ModemAdded"
 #define MODEM_REMOVED                  "ModemRemoved"
 #define SERVICE_ADDED                  "ServiceAdded"
 #define SERVICE_REMOVED                        "ServiceRemoved"
@@ -65,9 +64,9 @@
 #define CONTEXT_REMOVED                        "ContextRemoved"
 #define PROPERTY_CHANGED               "PropertyChanged"
 
-#define TIMEOUT 40000
+#define TIMEOUT 130000
 
-#define STRING2BOOL(a) ((g_str_equal(a, "TRUE")) ?  (TRUE):(FALSE))
+#define STRING2BOOL(a) (!(g_strcmp0(a, "TRUE")) ? (TRUE):(FALSE))
 
 static DBusConnection *connection;
 static GHashTable      *modem_hash;
@@ -99,6 +98,10 @@ struct telephony_modem {
 
 struct telephony_network {
        char *path;
+       int if_index;
+       gboolean routing_only;
+       gboolean ipv6_link_only;
+
        struct connman_network *network;
 
        enum connman_ipconfig_method ipv4_method;
@@ -108,6 +111,8 @@ struct telephony_network {
        struct connman_ipaddress *ipv6_address;
 };
 
+static int telephony_default_subscription_id = 0;
+
 /* function prototype */
 static void telephony_connect(DBusConnection *connection, void *user_data);
 static void telephony_disconnect(DBusConnection *connection, void *user_data);
@@ -127,7 +132,7 @@ static int __network_disconnect(struct connman_network *network);
 
 
 /* dbus request and reply */
-static int __dbus_request(const char *path, const char *interface,
+static int __dbus_request(const char *service, const char *path, const char *interface,
                        const char *method,
                        DBusPendingCallNotifyFunction notify, void *user_data,
                        DBusFreeFunction free_function, int type, ...);
@@ -149,18 +154,8 @@ static void __add_service(struct telephony_modem *modem,
 static void __add_connman_device(const char *modem_path, const char *operator);
 static void __remove_connman_device(struct telephony_modem *modem);
 static void __remove_connman_networks(struct connman_device *device);
-static void __set_device_powered(struct telephony_modem *modem,
-                                       gboolean powered);
-static int __check_device_powered(const char *path, gboolean online);
-static gboolean __check_network_available(struct connman_network *network);
-static void __create_service(struct connman_network *network);
 static int __add_context(struct connman_device *device, const char *path,
                                                        DBusMessageIter *prop);
-static gboolean __set_network_ipconfig(struct telephony_network *network,
-                                                       DBusMessageIter *dict);
-static void __set_network_connected(struct telephony_network *network,
-                                                       gboolean connected);
-static char *__get_ident(const char *path);
 
 /* signal handler */
 static gboolean __changed_modem(DBusConnection *connection,
@@ -209,6 +204,7 @@ static int tech_probe(struct connman_technology *technology)
 
 static void tech_remove(struct connman_technology *technology)
 {
+       return;
 }
 
 static struct connman_technology_driver tech_driver = {
@@ -228,8 +224,8 @@ static void telephony_connect(DBusConnection *connection, void *user_data)
                                                g_free, __remove_service);
        network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                g_free, __remove_network);
+
        __request_get_modems();
-       return;
 }
 
 static void telephony_disconnect(DBusConnection *connection, void *user_data)
@@ -245,8 +241,6 @@ static void telephony_disconnect(DBusConnection *connection, void *user_data)
                g_hash_table_destroy(network_hash);
                network_hash = NULL;
        }
-
-       return;
 }
 
 static void __remove_modem(gpointer data)
@@ -281,11 +275,37 @@ static void __remove_network(gpointer data)
        connman_network_unref(info->network);
 
        g_free(info->path);
+
        connman_ipaddress_free(info->ipv4_address);
        connman_ipaddress_free(info->ipv6_address);
+
        g_free(info);
 }
 
+static void __set_device_powered(struct telephony_modem *modem,
+                                       gboolean powered)
+{
+       DBG("set modem(%s) powered(%d)", modem->path, powered);
+
+       if (modem->device)
+               connman_device_set_powered(modem->device, powered);
+}
+
+static int __check_device_powered(const char *path, gboolean powered)
+{
+       struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
+
+       if (modem == NULL)
+               return -ENODEV;
+
+       DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
+
+       if (modem->powered == powered)
+               return -EALREADY;
+
+       return 0;
+}
+
 static int __modem_probe(struct connman_device *device)
 {
        DBG("device %p", device);
@@ -321,22 +341,8 @@ static int __network_probe(struct connman_network *network)
 
 static int __network_connect(struct connman_network *network)
 {
-       struct connman_device *device;
-       struct telephony_modem *modem;
-
        DBG("network %p", network);
 
-       device = connman_network_get_device(network);
-       if (device == NULL)
-               return -ENODEV;
-
-       modem = connman_device_get_data(device);
-       if (modem == NULL)
-               return -ENODEV;
-
-       if (modem->powered == FALSE)
-               return -ENOLINK;
-
        return __request_network_activate(network);
 }
 
@@ -344,8 +350,8 @@ static int __network_disconnect(struct connman_network *network)
 {
        DBG("network %p", network);
 
-       if (connman_network_get_index(network) < 0)
-               return -ENOTCONN;
+       if (connman_network_get_associating(network) == TRUE)
+               connman_network_clear_associating(network);
 
        connman_network_set_associating(network, FALSE);
 
@@ -358,26 +364,24 @@ static void __network_remove(struct connman_network *network)
        DBG("network %p path %s", network, path);
 
        g_hash_table_remove(network_hash, path);
-       return;
 }
 
-static int __dbus_request(const char *path, const char *interface,
-                       const char *method,
-                       DBusPendingCallNotifyFunction notify, void *user_data,
-                       DBusFreeFunction free_function, int type, ...)
+static int __dbus_request(const char *service, const char *path, const char *interface,
+               const char *method,
+               DBusPendingCallNotifyFunction notify, void *user_data,
+               DBusFreeFunction free_function, int type, ...)
 {
        DBusMessage *message;
        DBusPendingCall *call;
        dbus_bool_t ok;
        va_list va;
 
-       DBG("Telephony request path %s %s.%s", path, interface, method);
+       DBG("path %s %s.%s", path, interface, method);
 
        if (path == NULL)
                return -EINVAL;
 
-       message = dbus_message_new_method_call(PS_DBUS_SERVICE, path,
-                                               interface, method);
+       message = dbus_message_new_method_call(service, path, interface, method);
        if (message == NULL)
                return -ENOMEM;
 
@@ -387,8 +391,10 @@ static int __dbus_request(const char *path, const char *interface,
        ok = dbus_message_append_args_valist(message, type, va);
        va_end(va);
 
-       if (!ok)
+       if (!ok) {
+               dbus_message_unref(message);
                return -ENOMEM;
+       }
 
        if (dbus_connection_send_with_reply(connection, message,
                                                &call, TIMEOUT) == FALSE) {
@@ -414,7 +420,7 @@ static int __request_get_modems(void)
 {
        DBG("request get modem");
        /* call connect master */
-       return __dbus_request("/", PS_MASTER_INTERFACE, GET_MODEMS,
+       return __dbus_request(PS_DBUS_SERVICE, "/", PS_MASTER_INTERFACE, GET_MODEMS,
                        __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID);
 }
 
@@ -443,6 +449,10 @@ static void __response_get_modems(DBusPendingCall *call, void *user_data)
 
        dbus_message_iter_recurse(&args, &dict);
 
+       /* DBG("message type (%d) dic(%d)",
+        *      dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
+        */
+
        while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
                DBusMessageIter entry, property;
                const char *modem_path;
@@ -462,15 +472,14 @@ static void __response_get_modems(DBusPendingCall *call, void *user_data)
 done:
        dbus_message_unref(reply);
        dbus_pending_call_unref(call);
-       return;
 }
 
 static int __request_get_services(const char *path)
 {
        DBG("request get service");
-       return __dbus_request(path, PS_MODEM_INTERFACE, GET_SERVICES,
-                               __response_get_services, g_strdup(path),
-                               g_free, DBUS_TYPE_INVALID);
+       return __dbus_request(PS_DBUS_SERVICE, path, PS_MODEM_INTERFACE, GET_SERVICES,
+                       __response_get_services, g_strdup(path),
+                       g_free, DBUS_TYPE_INVALID);
 }
 
 static void __response_get_services(DBusPendingCall *call, void *user_data)
@@ -483,10 +492,6 @@ static void __response_get_services(DBusPendingCall *call, void *user_data)
        struct telephony_modem *modem;
 
        modem = g_hash_table_lookup(modem_hash, path);
-       if (modem == NULL)
-               return;
-       if (modem->device == NULL)
-               return;
 
        DBG("");
 
@@ -500,6 +505,9 @@ static void __response_get_services(DBusPendingCall *call, void *user_data)
                goto done;
        }
 
+       if (modem == NULL || modem->device == NULL)
+               goto done;
+
        DBG("message signature (%s)", dbus_message_get_signature(reply));
 
        if (dbus_message_iter_init(reply, &args) == FALSE)
@@ -507,6 +515,10 @@ static void __response_get_services(DBusPendingCall *call, void *user_data)
 
        dbus_message_iter_recurse(&args, &dict);
 
+       /* DBG("message type (%d) dic(%d)",
+        *       dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
+        */
+
        while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
                DBusMessageIter entry, property;
                const char *service_path;
@@ -526,16 +538,15 @@ static void __response_get_services(DBusPendingCall *call, void *user_data)
 done:
        dbus_message_unref(reply);
        dbus_pending_call_unref(call);
-       return;
 }
 
 static int __request_get_contexts(struct telephony_modem *modem)
 {
        DBG("request get contexts");
-       return __dbus_request(modem->s_service->path,
-                               PS_SERVICE_INTERFACE, GET_CONTEXTS,
-                               __response_get_contexts, g_strdup(modem->path),
-                               g_free, DBUS_TYPE_INVALID);
+       return __dbus_request(PS_DBUS_SERVICE, modem->s_service->path,
+                       PS_SERVICE_INTERFACE, GET_CONTEXTS,
+                       __response_get_contexts, g_strdup(modem->path),
+                       g_free, DBUS_TYPE_INVALID);
 }
 
 static void __response_get_contexts(DBusPendingCall *call, void *user_data)
@@ -593,21 +604,43 @@ static void __response_get_contexts(DBusPendingCall *call, void *user_data)
 done:
        dbus_message_unref(reply);
        dbus_pending_call_unref(call);
-       return;
 }
 
 static int __request_network_activate(struct connman_network *network)
 {
-       DBG("request network activate");
+       int n_modems;
+       const char *path = NULL;
+       struct telephony_modem *modem = NULL;
 
-       const char *path = connman_network_get_string(network, "Path");
-       DBG("network %p, path %s", network, path);
+       n_modems = g_hash_table_size(modem_hash);
+       path = connman_network_get_string(network, "Path");
+       modem = connman_device_get_data(connman_network_get_device(network));
+       DBG("network %p, path %s, modem %s[%d]", network, path, modem->path,
+                       telephony_default_subscription_id);
+
+       if (modem && n_modems > 1 && g_str_has_suffix(path, "_1") == TRUE) {
+               char *subscribe_id = g_strdup_printf("%d", telephony_default_subscription_id);
+
+               if (g_str_has_suffix(modem->path, subscribe_id) != TRUE) {
+                       g_free(subscribe_id);
+                       return -ENOLINK;
+               }
+               g_free(subscribe_id);
+       }
 
-       return __dbus_request(path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
+       return __dbus_request(PS_DBUS_SERVICE, path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
                        __response_network_activate,
                        g_strdup(path), NULL, DBUS_TYPE_INVALID);
 }
 
+static gboolean __check_network_available(struct connman_network *network)
+{
+       if (network == NULL || connman_network_get_device(network) == NULL)
+               return FALSE;
+
+       return TRUE;
+}
+
 static void __response_network_activate(DBusPendingCall *call, void *user_data)
 {
        DBG("network activation response");
@@ -624,7 +657,7 @@ static void __response_network_activate(DBusPendingCall *call, void *user_data)
        if (info == NULL)
                goto done;
 
-       if (!__check_network_available(info->network)) {
+       if (__check_network_available(info->network) == FALSE) {
                g_hash_table_remove(network_hash, path);
                goto done;
        }
@@ -634,6 +667,14 @@ static void __response_network_activate(DBusPendingCall *call, void *user_data)
                connman_error("connection activate() %s %s",
                                        error.name, error.message);
 
+               if (connman_network_get_associating(info->network) == TRUE)
+                       connman_network_set_error(info->network,
+                                       CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+
+               if (connman_network_get_connecting(info->network) == TRUE)
+                       connman_network_set_error(info->network,
+                                       CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+
                if (connman_network_get_index(info->network) < 0)
                        connman_network_set_error(info->network,
                                        CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
@@ -645,18 +686,62 @@ static void __response_network_activate(DBusPendingCall *call, void *user_data)
 done:
        dbus_message_unref(reply);
        dbus_pending_call_unref(call);
-       return;
 }
 
 static int __request_network_deactivate(struct connman_network *network)
 {
-       DBG("request network deactivate");
-
        const char *path = connman_network_get_string(network, "Path");
        DBG("network %p, path %s", network, path);
 
-       return __dbus_request(path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
-               NULL, NULL, NULL, DBUS_TYPE_INVALID);
+       return __dbus_request(PS_DBUS_SERVICE, path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
+                       NULL, NULL, NULL, DBUS_TYPE_INVALID);
+}
+
+static void __response_get_default_subscription_id(DBusPendingCall *call,
+               void *user_data)
+{
+       DBusMessage *reply;
+       DBusError error;
+       DBusMessageIter args;
+
+       DBG("");
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       dbus_error_init(&error);
+       if (dbus_set_error_from_message(&error, reply)) {
+               connman_error("GetDefaultDataSubscription() %s %s", error.name, error.message);
+               dbus_error_free(&error);
+               goto done;
+       }
+
+       DBG("message signature (%s)", dbus_message_get_signature(reply));
+
+       if (dbus_message_iter_init(reply, &args) == FALSE)
+               goto done;
+
+       dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
+       DBG("default subscription: %d", telephony_default_subscription_id);
+
+done:
+       dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
+}
+
+static int __request_get_default_subscription_id(const char *path)
+{
+       int ret;
+       char *telephony_modem_path = NULL;
+
+       telephony_modem_path = g_strdup_printf("/org/tizen/telephony%s", path);
+       DBG("request get default subscription id %s", telephony_modem_path);
+
+       ret = __dbus_request(TELEPHONY_DBUS_SERVICE, telephony_modem_path,
+                       "org.tizen.telephony.Network", "GetDefaultDataSubscription",
+                       __response_get_default_subscription_id, NULL, NULL, DBUS_TYPE_INVALID);
+
+       g_free(telephony_modem_path);
+       return ret;
 }
 
 static void __add_modem(const char *path, DBusMessageIter *prop)
@@ -667,9 +752,9 @@ static void __add_modem(const char *path, DBusMessageIter *prop)
        if (modem != NULL)
                return;
 
-       modem = (struct telephony_modem *)malloc(
-                                       sizeof(struct telephony_modem));
-       memset(modem, 0, sizeof(struct telephony_modem));
+       modem = g_try_new0(struct telephony_modem, 1);
+       if (modem == NULL)
+               return;
 
        modem->path = g_strdup(path);
        modem->device = NULL;
@@ -689,17 +774,17 @@ static void __add_modem(const char *path, DBusMessageIter *prop)
 
                DBG("key (%s) value(%s)", key, tmp);
 
-               if (g_str_equal(key, "powered") == TRUE) {
+               if (g_strcmp0(key, "powered") == 0) {
                        modem->powered = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "operator") == TRUE) {
+               } else if (g_strcmp0(key, "operator") == 0) {
                        modem->operator = g_strdup(tmp);
-               } else if (g_str_equal(key, "sim_init") == TRUE) {
+               } else if (g_strcmp0(key, "sim_init") == 0) {
                        modem->sim_init = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "flight_mode") == TRUE) {
+               } else if (g_strcmp0(key, "flight_mode") == 0) {
                        modem->flight_mode = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
+               } else if (g_strcmp0(key, "roaming_allowed") == 0) {
                        modem->roaming_allowed = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "data_allowed") == TRUE) {
+               } else if (g_strcmp0(key, "data_allowed") == 0) {
                        modem->data_allowed = STRING2BOOL(tmp);
                }
                dbus_message_iter_next(prop);
@@ -708,14 +793,15 @@ static void __add_modem(const char *path, DBusMessageIter *prop)
        __add_connman_device(path, modem->operator);
        __set_device_powered(modem, modem->powered);
 
+       if (g_hash_table_size(modem_hash) > 1)
+               __request_get_default_subscription_id(modem->path);
+
        if (modem->powered != TRUE) {
                DBG("modem is not powered");
                return;
        }
 
        __request_get_services(modem->path);
-
-       return;
 }
 
 static void __add_service(struct telephony_modem *modem,
@@ -726,13 +812,10 @@ static void __add_service(struct telephony_modem *modem,
        if (modem->s_service != NULL)
                return;
 
-       service = (struct telephony_service *)g_try_malloc(
-                                       sizeof(struct telephony_service));
+       service = g_try_new0(struct telephony_service, 1);
        if (service == NULL)
                return;
 
-       memset(service, 0, sizeof(struct telephony_service));
-
        service->path = g_strdup(service_path);
        service->p_modem = modem;
        g_hash_table_insert(service_hash, g_strdup(service_path), service);
@@ -749,11 +832,11 @@ static void __add_service(struct telephony_modem *modem,
 
                DBG("key (%s) value(%s)", key, tmp);
 
-               if (g_str_equal(key, "roaming") == TRUE) {
+               if (g_strcmp0(key, "roaming") == 0) {
                        service->roaming = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "act") == TRUE) {
+               } else if (g_strcmp0(key, "act") == 0) {
                        service->act = g_strdup(tmp);
-               } else if (g_str_equal(key, "ps_attached") == TRUE) {
+               } else if (g_strcmp0(key, "ps_attached") == 0) {
                        service->ps_attached = STRING2BOOL(tmp);
                }
 
@@ -762,12 +845,25 @@ static void __add_service(struct telephony_modem *modem,
 
        modem->s_service = service;
        __request_get_contexts(modem);
+}
 
-       return;
+static char *__get_ident(const char *path)
+{
+       char *pos;
+
+       if (*path != '/')
+               return NULL;
+
+       pos = strrchr(path, '/');
+       if (pos == NULL)
+               return NULL;
+
+       return pos + 1;
 }
 
 static void __add_connman_device(const char *modem_path, const char *operator)
 {
+       char* ident = NULL;
        struct telephony_modem *modem;
        struct connman_device *device;
 
@@ -798,7 +894,10 @@ static void __add_connman_device(const char *modem_path, const char *operator)
        if (device == NULL)
                return;
 
-       connman_device_set_ident(device, operator);
+       ident = g_strdup_printf("%s_%s", __get_ident(modem_path), operator);
+       connman_device_set_ident(device, ident);
+       g_free(ident);
+
        connman_device_set_string(device, "Path", modem_path);
        connman_device_set_data(device, modem);
 
@@ -809,8 +908,6 @@ static void __add_connman_device(const char *modem_path, const char *operator)
        }
 
        modem->device = device;
-
-       return;
 }
 
 static void __remove_connman_device(struct telephony_modem *modem)
@@ -826,8 +923,6 @@ static void __remove_connman_device(struct telephony_modem *modem)
        connman_device_unref(modem->device);
 
        modem->device = NULL;
-
-       return;
 }
 
 static void __remove_connman_networks(struct connman_device *device)
@@ -859,384 +954,428 @@ static void __remove_connman_networks(struct connman_device *device)
        g_slist_free(info_list);
 }
 
-static void __set_device_powered(struct telephony_modem *modem,
-                                       gboolean powered)
+static gboolean connman_ipaddress_updated(struct connman_ipaddress *ipaddress,
+                                       const char *address, const char *gateway)
 {
-       DBG("set modem(%s) powered(%d)", modem->path, powered);
-
-       if (modem->device)
-               connman_device_set_powered(modem->device, powered);
-
-       return;
-}
-
-static int __check_device_powered(const char *path, gboolean powered)
-{
-       struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
-
-       if (modem == NULL)
-               return -ENODEV;
-
-       DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
-
-       if (modem->powered == powered)
-               return -EALREADY;
+       if (ipaddress == NULL || address == NULL)
+               return FALSE;
 
-       return 0;
-}
+       if (g_strcmp0(ipaddress->local, address) != 0)
+               return TRUE;
 
-static gboolean __check_network_available(struct connman_network *network)
-{
-       if (network == NULL || connman_network_get_device(network) == NULL) {
-               DBG("Modem or network was removed");
-               return FALSE;
-       }
+       if (g_strcmp0(ipaddress->gateway, gateway) != 0)
+               return TRUE;
 
-       return TRUE;
+       return FALSE;
 }
 
-static int __add_context(struct connman_device *device, const char *path,
-                               DBusMessageIter *prop)
+static void __set_network_connected(struct telephony_network *network,
+                                       gboolean connected)
 {
-       char *ident;
-       gboolean active = FALSE;
-
-       struct telephony_modem *modem = connman_device_get_data(device);
-       struct connman_network *network;
-       struct telephony_network *info;
-
-       DBG("modem %p device %p path %s", modem, device, path);
-
-       ident = __get_ident(path);
-
-       network = connman_device_get_network(device, ident);
-       if (network != NULL)
-               return -EALREADY;
-
-       info = g_hash_table_lookup(network_hash, path);
-       if (info != NULL) {
-               DBG("path %p already exists with device %p", path,
-                       connman_network_get_device(info->network));
-
-               if (connman_network_get_device(info->network))
-                       return -EALREADY;
+       gboolean setip = FALSE;
 
-               g_hash_table_remove(network_hash, path);
-       }
+       DBG("network %p connected %d", network, connected);
 
-       network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
-       if (network == NULL)
-               return -ENOMEM;
+       connman_network_set_index(network->network, network->if_index);
+       if (connman_network_get_connected(network->network) == connected)
+               return;
 
-       info = (struct telephony_network *)g_try_malloc(
-                                       sizeof(struct telephony_network));
-       if (info == NULL) {
-               connman_network_unref(network);
-               return -ENOMEM;
+       switch (network->ipv4_method) {
+       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+       case CONNMAN_IPCONFIG_METHOD_DHCP:
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
+       case CONNMAN_IPCONFIG_METHOD_OFF:
+               connman_network_set_ipv4_method(network->network,
+                                                       network->ipv4_method);
+               break;
+       case CONNMAN_IPCONFIG_METHOD_MANUAL:
+       case CONNMAN_IPCONFIG_METHOD_FIXED:
+               connman_network_set_ipv4_method(network->network,
+                                                       network->ipv4_method);
+               connman_network_set_ipaddress(network->network,
+                                                       network->ipv4_address);
+               setip = TRUE;
+               break;
        }
 
-       memset(info, 0, sizeof(struct telephony_network));
-
-       info->path = g_strdup(path);
-
-       connman_ipaddress_clear(info->ipv4_address);
-       connman_ipaddress_clear(info->ipv6_address);
-       info->network = network;
-
-       connman_network_set_string(network, "Path", path);
-       connman_network_set_name(network, path);
-
-       __create_service(network);
-
-       g_hash_table_insert(network_hash, g_strdup(path), info);
-
-       connman_network_set_available(network, TRUE);
-       connman_network_set_index(network, -1);
-       connman_network_set_bool(network, "Roaming", modem->s_service->roaming);
-
-       if (connman_device_add_network(device, network) != 0) {
-               g_hash_table_remove(network_hash, path);
-               return -EIO;
+       switch (network->ipv6_method) {
+       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+       case CONNMAN_IPCONFIG_METHOD_OFF:
+       case CONNMAN_IPCONFIG_METHOD_DHCP:
+               break;
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
+               connman_network_set_ipv6_method(network->network,
+                                                       network->ipv6_method);
+               setip = TRUE;
+               break;
+       case CONNMAN_IPCONFIG_METHOD_MANUAL:
+       case CONNMAN_IPCONFIG_METHOD_FIXED:
+               connman_network_set_ipv6_method(network->network,
+                                                       network->ipv6_method);
+               connman_network_set_ipaddress(network->network,
+                                                       network->ipv6_address);
+               setip = TRUE;
+               break;
        }
 
-       active = __set_network_ipconfig(info, prop);
-
-       if (active && (connman_network_get_connecting(network) ||
-                               connman_network_get_associating(network)))
-               __set_network_connected(info, active);
-
-       return 0;
-}
-
-static void __create_service(struct connman_network *network)
-{
-       const char *path;
-       char *group;
-
-       DBG("");
-
-       path = connman_network_get_string(network, "Path");
-
-       group = __get_ident(path);
-
-       connman_network_set_group(network, group);
+       if (setip == TRUE)
+               connman_network_set_connected(network->network, connected);
 }
 
-static gboolean __set_network_ipconfig(struct telephony_network *network,
-                                       DBusMessageIter *dict)
+static gboolean __set_network_context(
+                                                       struct telephony_network *network,
+                                                       DBusMessageIter *dict)
 {
-       DBG("set network info");
-
+       int index = 0;
        gboolean active = FALSE;
-       char *dev_name = NULL, *proxy_addr = NULL;
+       gboolean routing_only = FALSE;
+       gboolean ipv4_updated = FALSE;
+       gboolean ipv6_updated = FALSE;
+       gboolean ipv6_link_only = FALSE;
+       gboolean default_internet = FALSE;
+       gboolean active_proxy = FALSE;
+       char **proxies = NULL;
+       const char *dev_name = NULL;
+       const char *proxy_addr = NULL;
        char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL,
                                        *ipv4_dns1 = NULL, *ipv4_dns2 = NULL;
        char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL,
                                        *ipv6_dns1 = NULL, *ipv6_dns2 = NULL;
-       int index;
-       int dns_flag = 0;
+       struct connman_service *service;
 
        while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) {
                DBusMessageIter entry;
-               const char *key, *tmp;
+               const char *key, *value;
 
                dbus_message_iter_recurse(dict, &entry);
                dbus_message_iter_get_basic(&entry, &key);
 
                dbus_message_iter_next(&entry);
 
-               DBG("key (%s)", key);
-
-               if (g_str_equal(key, "dev_name") == TRUE) {
+               if (g_strcmp0(key, "dev_name") == 0) {
                        dbus_message_iter_get_basic(&entry, &dev_name);
                        DBG("dev_name (%s)", dev_name);
-               } else if (g_str_equal(key, "proxy") == TRUE) {
+               } else if (g_strcmp0(key, "proxy") == 0) {
                        dbus_message_iter_get_basic(&entry, &proxy_addr);
-               } else if (g_str_equal(key, "ipv4_address") == TRUE) {
+                       DBG("proxy_addr (%s)", proxy_addr);
+               } else if (g_strcmp0(key, "ipv4_address") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv4_addr);
-                       DBG("ipv4 address (%s)", ipv4_addr);
-               } else if (g_str_equal(key, "ipv4_gateway") == TRUE) {
+                       DBG("ipv4_addr (%s)", ipv4_addr);
+               } else if (g_strcmp0(key, "ipv4_gateway") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv4_gw);
-               } else if (g_str_equal(key, "ipv4_netmask") == TRUE) {
+                       DBG("ipv4_gw (%s)", ipv4_gw);
+               } else if (g_strcmp0(key, "ipv4_netmask") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv4_netmask);
-               } else if (g_str_equal(key, "ipv4_dns1") == TRUE) {
+                       DBG("ipv4_netmask (%s)", ipv4_netmask);
+               } else if (g_strcmp0(key, "ipv4_dns1") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv4_dns1);
-               } else if (g_str_equal(key, "ipv4_dns2") == TRUE) {
+                       DBG("ipv4_dns1 (%s)", ipv4_dns1);
+               } else if (g_strcmp0(key, "ipv4_dns2") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv4_dns2);
-               } else if (g_str_equal(key, "ipv6_address") == TRUE) {
+                       DBG("ipv4_dns2 (%s)", ipv4_dns2);
+               } else if (g_strcmp0(key, "ipv6_address") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv6_addr);
                        DBG("ipv6 address (%s)", ipv6_addr);
-               } else if (g_str_equal(key, "ipv6_gateway") == TRUE) {
+               } else if (g_strcmp0(key, "ipv6_gateway") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv6_gw);
-               } else if (g_str_equal(key, "ipv6_netmask") == TRUE) {
+                       DBG("ipv6_gw (%s)", ipv6_gw);
+               } else if (g_strcmp0(key, "ipv6_netmask") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv6_netmask);
-               } else if (g_str_equal(key, "ipv6_dns1") == TRUE) {
+                       DBG("ipv6_netmask (%s)", ipv6_netmask);
+               } else if (g_strcmp0(key, "ipv6_dns1") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv6_dns1);
-               } else if (g_str_equal(key, "ipv6_dns2") == TRUE) {
+                       DBG("ipv6_dns1 (%s)", ipv6_dns1);
+               } else if (g_strcmp0(key, "ipv6_dns2") == 0) {
                        dbus_message_iter_get_basic(&entry, &ipv6_dns2);
-               } else if (g_str_equal(key, "active") == TRUE) {
-                       dbus_message_iter_get_basic(&entry, &tmp);
-                       DBG("active (%s)", tmp);
-                       active = STRING2BOOL(tmp);
+                       DBG("ipv6_dns2 (%s)", ipv6_dns2);
+               } else if (g_strcmp0(key, "active") == 0) {
+                       dbus_message_iter_get_basic(&entry, &value);
+                       DBG("active (%s)", value);
+                       active = STRING2BOOL(value);
+               } else if (g_strcmp0(key, "routing_only") == 0) {
+                       dbus_message_iter_get_basic(&entry, &value);
+                       DBG("routing_only (%s)", value);
+                       routing_only = STRING2BOOL(value);
+                       network->routing_only = routing_only;
+               } else if (g_strcmp0(key, "ipv6_link_only") == 0) {
+                       dbus_message_iter_get_basic(&entry, &value);
+                       DBG("ipv6_link_only (%s)", value);
+                       ipv6_link_only = STRING2BOOL(value);
+                       network->ipv6_link_only = ipv6_link_only;
+               }
+               else if (g_strcmp0(key, "default_internet_conn") == 0) {
+                       dbus_message_iter_get_basic(&entry, &value);
+                       DBG("default_internet (%s)", value);
+                       default_internet = STRING2BOOL(value);
                }
 
                dbus_message_iter_next(dict);
        }
 
-       /* interface index set */
-       if (dev_name == NULL)
-               dev_name = "";
+       if(routing_only){
+               //context active does not effect the connman service status.
+               //it only for setting the routing path.
+               DBG("routing_only(%d), active(%d)", routing_only, active);
+               return active;
+       }
+
+       if (g_strcmp0(proxy_addr, ":") == 0)
+               proxy_addr = NULL;
+       if (g_strcmp0(ipv4_addr, "0.0.0.0") == 0)
+               ipv4_addr = NULL;
+       if (g_strcmp0(ipv4_gw, "0.0.0.0") == 0)
+               ipv4_gw = NULL;
+       if (g_strcmp0(ipv4_netmask, "0.0.0.0") == 0)
+               ipv4_netmask = NULL;
+       if (g_strcmp0(ipv4_dns1, "0.0.0.0") == 0)
+               ipv4_dns1 = NULL;
+       if (g_strcmp0(ipv4_dns2, "0.0.0.0") == 0)
+               ipv4_dns2 = NULL;
+       if (g_strcmp0(ipv6_addr, "::") == 0)
+               ipv6_addr = NULL;
+       if (g_strcmp0(ipv6_gw, "::") == 0)
+               ipv6_gw = NULL;
+       if (g_strcmp0(ipv6_netmask, "::") == 0)
+               ipv6_netmask = NULL;
+       if (g_strcmp0(ipv6_dns1, "::") == 0)
+               ipv6_dns1 = NULL;
+       if (g_strcmp0(ipv6_dns2, "::") == 0)
+               ipv6_dns2 = NULL;
+
+       connman_network_set_bool(network->network, "DefaultInternet",
+                                                               (bool)default_internet);
+
+       service = connman_service_lookup_from_network(network->network);
+       if (service == NULL)
+               return FALSE;
+
+       if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) {
+               /* Wi-Fi technology is always a top priority */
+               if (active == TRUE &&
+                               connman_service_is_no_ref_user_pdn_connection(service) == TRUE &&
+                               connman_service_get_type(connman_service_get_default_connection())
+                                       == CONNMAN_SERVICE_TYPE_WIFI) {
+                       __request_network_deactivate(network->network);
+
+                       return FALSE;
+               }
+       }
 
-       if (!g_str_equal(dev_name, "")) {
+       /* interface index set */
+       if (dev_name != NULL) {
                index = connman_inet_ifindex(dev_name);
-               DBG("interface %s, index %d", dev_name, index);
-               connman_network_set_index(network->network, index);
+               network->if_index = index;
+               DBG("interface index %d", index);
        }
 
        /* proxy set */
-       if (proxy_addr == NULL)
-               proxy_addr = "";
+       if (active == TRUE &&
+                       connman_network_get_connected(network->network) == TRUE)
+               active_proxy = TRUE;
 
-       DBG("proxy (%s) is set", proxy_addr);
-       connman_network_set_proxy(network->network, proxy_addr);
+       proxies = connman_service_get_proxy_servers(service);
+       if (proxies != NULL) {
+               if (proxy_addr == NULL)
+                       connman_service_set_proxy(service, proxy_addr, active_proxy);
+               else if (g_strcmp0(proxy_addr, proxies[0]) != 0)
+                       connman_service_set_proxy(service, proxy_addr, active_proxy);
+       } else if (proxy_addr != NULL)
+               connman_service_set_proxy(service, proxy_addr, active_proxy);
+
+       if (proxies != NULL)
+               g_strfreev(proxies);
+
+       __connman_service_nameserver_clear(service);
 
        /* ipv4 set */
-       if (ipv4_addr == NULL)
-               ipv4_addr = "0.0.0.0";
+       if (network->ipv4_address == NULL)
+               network->ipv4_address =
+                               connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
+
+       if (network->ipv4_address == NULL)
+               return FALSE;
 
-       if (g_str_equal(ipv4_addr, "0.0.0.0")) {
+       if (ipv4_addr == NULL && active == TRUE)
                network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF;
-       } else {
+       else
                network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
-               network->ipv4_address =
-                       connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
-               if (network->ipv4_address == NULL)
-                       return FALSE;
 
+       connman_network_set_ipv4_method(network->network, network->ipv4_method);
+
+       ipv4_updated = connman_ipaddress_updated(network->ipv4_address,
+                                               ipv4_addr, ipv4_gw);
+       if (ipv4_updated == TRUE)
                connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr,
                                                ipv4_netmask, ipv4_gw);
 
-               if (ipv4_dns1 == NULL)
-                       ipv4_dns1 = "0.0.0.0";
-               if (ipv4_dns2 == NULL)
-                       ipv4_dns2 = "0.0.0.0";
-
-               if (g_str_equal(ipv4_dns1, "0.0.0.0"))
-                       dns_flag += 1;
-
-               if (g_str_equal(ipv4_dns2, "0.0.0.0"))
-                       dns_flag += 2;
-
-               gchar *nameservers = NULL;
-
-               switch (dns_flag) {
-               case 0:
-                       nameservers = g_strdup_printf("%s %s", ipv4_dns1,
-                                                               ipv4_dns2);
-                       break;
-               case 1:
-                       nameservers = g_strdup_printf("%s", ipv4_dns2);
-                       break;
-               case 2:
-                       nameservers = g_strdup_printf("%s", ipv4_dns1);
-               }
-
-               connman_network_set_nameservers(network->network, nameservers);
-               g_free(nameservers);
-       }
-
+       if (ipv4_dns1)
+#if defined TIZEN_EXT
+               __connman_service_nameserver_append(service, ipv4_dns1, FALSE,
+                               CONNMAN_IPCONFIG_TYPE_IPV4);
+#else
+               __connman_service_nameserver_append(service, ipv4_dns1, FALSE);
+#endif
+       //if (ipv4_dns2)
+       if (ipv4_dns2 && !ipv4_dns1)
+#if defined TIZEN_EXT
+               __connman_service_nameserver_append(service, ipv4_dns2, FALSE,
+                               CONNMAN_IPCONFIG_TYPE_IPV4);
+#else
+               __connman_service_nameserver_append(service, ipv4_dns2, FALSE);
+#endif
        /* ipv6 set */
-       if (ipv6_addr == NULL)
-               ipv6_addr = "::";
-
-       if (g_str_equal(ipv6_addr, "::")) {
-               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
-       } else {
-               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
-               unsigned char prefix_length = 64;
+       if (network->ipv6_address == NULL)
                network->ipv6_address =
-                       connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
-               if (network->ipv6_address == NULL)
-                       return FALSE;
+                               connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
 
-               connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
-                                               prefix_length, ipv6_gw);
+       if (network->ipv6_address == NULL)
+               return FALSE;
+
+       if(ipv6_link_only)
+               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_AUTO;
+       else
+               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
 
-               dns_flag = 0;
+       if (ipv6_addr == NULL)
+               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
 
-               if (ipv6_dns1 == NULL)
-                       ipv6_dns1 = "::";
-               if (ipv6_dns2 == NULL)
-                       ipv6_dns2 = "::";
+       connman_network_set_ipv6_method(network->network, network->ipv6_method);
 
-               if (g_str_equal(ipv6_dns1, "::"))
-                       dns_flag += 1;
+       ipv6_updated = connman_ipaddress_updated(network->ipv6_address,
+                                               ipv6_addr, ipv6_gw);
+       if (ipv6_updated == TRUE)
+               connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
+                                               64, ipv6_gw);
+
+       if (ipv6_dns1)
+#if defined TIZEN_EXT
+               __connman_service_nameserver_append(service, ipv6_dns1, FALSE,
+                               CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
+               __connman_service_nameserver_append(service, ipv6_dns1, FALSE);
+#endif
+       //if (ipv6_dns2)
+       if (ipv6_dns2 && !ipv6_dns1)
+#if defined TIZEN_EXT
+               __connman_service_nameserver_append(service, ipv6_dns2, FALSE,
+                               CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
+               __connman_service_nameserver_append(service, ipv6_dns2, FALSE);
+#endif
 
-               if (g_str_equal(ipv6_dns2, "::"))
-                       dns_flag += 2;
+       if (active == TRUE &&
+                       connman_network_get_connected(network->network) == TRUE) {
+               if (ipv4_updated == TRUE || ipv6_updated == TRUE) {
+                       DBG("IPv4 updated %d, IPv6 updated %d", ipv4_updated, ipv6_updated);
 
-               gchar *nameservers = NULL;
+                       __set_network_connected(network, FALSE);
+               } else {
+                       DBG("Already connected");
 
-               switch (dns_flag) {
-               case 0:
-                       nameservers = g_strdup_printf("%s %s", ipv6_dns1,
-                                                               ipv6_dns2);
-                       break;
-               case 1:
-                       nameservers = g_strdup_printf("%s", ipv6_dns2);
-                       break;
-               case 2:
-                       nameservers = g_strdup_printf("%s", ipv6_dns1);
+                       return active;
                }
-
-               connman_network_set_nameservers(network->network, nameservers);
-               g_free(nameservers);
        }
 
-       if (active)
+       if (active == TRUE)
                connman_network_set_associating(network->network, TRUE);
 
        return active;
 }
 
-static void __set_network_connected(struct telephony_network *network,
-                                       gboolean connected)
+static int __add_context(struct connman_device *device, const char *path,
+                               DBusMessageIter *prop)
 {
-       gboolean setip = FALSE;
+       char *ident;
+       gboolean active = FALSE;
 
-       DBG("network %p connected %d", network, connected);
+       struct telephony_modem *modem = connman_device_get_data(device);
+       struct connman_network *network;
+       struct telephony_network *info;
 
-       switch (network->ipv4_method) {
-       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
-       case CONNMAN_IPCONFIG_METHOD_OFF:
-       case CONNMAN_IPCONFIG_METHOD_MANUAL:
-       case CONNMAN_IPCONFIG_METHOD_AUTO:
-               setip = TRUE;
-               break;
+       DBG("modem %p device %p path %s", modem, device, path);
 
-       case CONNMAN_IPCONFIG_METHOD_FIXED:
-               connman_network_set_ipv4_method(network->network,
-                                                       network->ipv4_method);
-               connman_network_set_ipaddress(network->network,
-                                                       network->ipv4_address);
-               setip = TRUE;
-               break;
+       ident = __get_ident(path);
 
-       case CONNMAN_IPCONFIG_METHOD_DHCP:
-               connman_network_set_ipv4_method(network->network,
-                                                       network->ipv4_method);
-               setip = TRUE;
-               break;
+       network = connman_device_get_network(device, ident);
+       if (network != NULL)
+               return -EALREADY;
+
+       info = g_hash_table_lookup(network_hash, path);
+       if (info != NULL) {
+               DBG("path %p already exists with device %p", path,
+                       connman_network_get_device(info->network));
+
+               if (connman_network_get_device(info->network))
+                       return -EALREADY;
+
+               g_hash_table_remove(network_hash, path);
        }
 
-       switch (network->ipv6_method) {
-       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
-       case CONNMAN_IPCONFIG_METHOD_OFF:
-       case CONNMAN_IPCONFIG_METHOD_MANUAL:
-       case CONNMAN_IPCONFIG_METHOD_DHCP:
-       case CONNMAN_IPCONFIG_METHOD_AUTO:
-               DBG("ipv6 not supported");
-               break;
+       network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
+       if (network == NULL)
+               return -ENOMEM;
 
-       case CONNMAN_IPCONFIG_METHOD_FIXED:
-               connman_network_set_ipv6_method(network->network,
-                                                       network->ipv6_method);
-               connman_network_set_ipaddress(network->network,
-                                                       network->ipv6_address);
-               setip = TRUE;
-               break;
+       info = g_try_new0(struct telephony_network, 1);
+       if (info == NULL) {
+               connman_network_unref(network);
+               return -ENOMEM;
        }
 
-       if (setip == TRUE)
-               connman_network_set_connected(network->network, connected);
+       info->path = g_strdup(path);
 
-       return;
-}
+       connman_ipaddress_clear(info->ipv4_address);
+       connman_ipaddress_clear(info->ipv6_address);
 
-static char *__get_ident(const char *path)
-{
-       char *pos;
+       info->network = network;
 
-       if (*path != '/')
-               return NULL;
+       connman_network_set_string(network, "Path", path);
+       connman_network_set_name(network, path);
 
-       pos = strrchr(path, '/');
-       if (pos == NULL)
-               return NULL;
+       connman_network_set_group(network, ident);
 
-       return pos + 1;
+       g_hash_table_insert(network_hash, g_strdup(path), info);
+
+       connman_network_set_available(network, TRUE);
+       connman_network_set_bool(network, "Roaming", (bool)modem->s_service->roaming);
+
+       if (connman_device_add_network(device, network) != 0) {
+               g_hash_table_remove(network_hash, path);
+               return -EIO;
+       }
+
+       active = __set_network_context(info, prop);
+       if(info->routing_only){
+               int err = 0;
+               struct connman_service *routing_service;
+               struct connman_ipconfig *routing_ipconfig;
+
+               if(!active)
+                       return TRUE;
+
+               routing_service = connman_service_lookup_from_network(info->network);
+               routing_ipconfig = __connman_service_get_ip4config(routing_service);
+               err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
+
+               DBG("set gateway rv(%d)", err);
+               return TRUE;
+       }
+
+       if (active == TRUE && (connman_network_get_associating(network) == TRUE ||
+                       connman_network_get_connecting(network) == TRUE))
+               __set_network_connected(info, active);
+
+       return 0;
 }
 
 static gboolean __changed_modem(DBusConnection *connection,
                                DBusMessage *message, void *user_data)
 {
-       DBG("modem changed signal");
-
+       gboolean old_powered;
        DBusMessageIter args, dict;
-       const char *path = dbus_message_get_path(message);
        struct telephony_modem *modem;
+       const char *path = dbus_message_get_path(message);
 
-       DBG("modem path %s", path);
+       DBG("modem changed signal %s", path);
 
        modem = g_hash_table_lookup(modem_hash, path);
        if (modem == NULL) {
@@ -1244,6 +1383,8 @@ static gboolean __changed_modem(DBusConnection *connection,
                return TRUE;
        }
 
+       old_powered = modem->powered;
+
        DBG("message signature (%s)", dbus_message_get_signature(message));
 
        if (dbus_message_iter_init(message, &args) == FALSE) {
@@ -1265,17 +1406,17 @@ static gboolean __changed_modem(DBusConnection *connection,
 
                DBG("key(%s), value(%s)", key, tmp);
 
-               if (g_str_equal(key, "powered") == TRUE) {
+               if (g_strcmp0(key, "powered") == 0) {
                        modem->powered = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "operator") == TRUE) {
+               } else if (g_strcmp0(key, "operator") == 0) {
                        modem->operator = g_strdup(tmp);
-               } else if (g_str_equal(key, "sim_init") == TRUE) {
+               } else if (g_strcmp0(key, "sim_init") == 0) {
                        modem->sim_init = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "flight_mode") == TRUE) {
+               } else if (g_strcmp0(key, "flight_mode") == 0) {
                        modem->flight_mode = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
+               } else if (g_strcmp0(key, "roaming_allowed") == 0) {
                        modem->roaming_allowed = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "data_allowed") == TRUE) {
+               } else if (g_strcmp0(key, "data_allowed") == 0) {
                        modem->data_allowed = STRING2BOOL(tmp);
                }
 
@@ -1285,23 +1426,21 @@ static gboolean __changed_modem(DBusConnection *connection,
        if (modem->device == NULL)
                __add_connman_device(path, modem->operator);
 
-       __set_device_powered(modem, modem->powered);
+       if (old_powered != modem->powered)
+               __set_device_powered(modem, modem->powered);
 
        if (modem->powered != TRUE) {
                DBG("modem is not powered");
                return TRUE;
        }
 
-       if (!modem->s_service) {
+       if (modem->s_service == NULL) {
                __request_get_services(modem->path);
                return TRUE;
        }
 
-       if (modem->flight_mode || !modem->data_allowed) {
-               DBG("modem(%s) flight mode(%d) data allowed(%d)",
+       DBG("modem(%s) flight mode(%d) data allowed(%d)",
                        modem->path, modem->flight_mode, modem->data_allowed);
-               return TRUE;
-       }
 
        return TRUE;
 }
@@ -1309,12 +1448,11 @@ static gboolean __changed_modem(DBusConnection *connection,
 static gboolean __added_modem(DBusConnection *connection,
                                DBusMessage *message, void *user_data)
 {
-       DBG("modem added signal");
-
        const char *modem_path = NULL;
        DBusMessageIter args, dict, tmp;
 
-       DBG("message signature (%s)", dbus_message_get_signature(message));
+       DBG("modem added signal (%s)", dbus_message_get_signature(message));
+
        if (dbus_message_iter_init(message, &args) == FALSE) {
                DBG("error to read message");
                return TRUE;
@@ -1335,7 +1473,7 @@ static gboolean __added_modem(DBusConnection *connection,
 
                DBG("key (%s) value(%s)", key, value);
 
-               if (g_str_equal(key, "path") == TRUE)
+               if (g_strcmp0(key, "path") == 0)
                        modem_path = g_strdup(value);
 
                dbus_message_iter_next(&tmp);
@@ -1350,11 +1488,11 @@ static gboolean __added_modem(DBusConnection *connection,
 static gboolean __removed_modem(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
-       DBG("modem removed signal");
-
        DBusMessageIter iter;
        const char *modem_path;
 
+       DBG("modem removed signal");
+
        if (dbus_message_iter_init(message, &iter) == FALSE) {
                DBG("error to read message");
                return TRUE;
@@ -1369,15 +1507,13 @@ static gboolean __removed_modem(DBusConnection *connection,
 static gboolean __changed_service(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
-       DBG("service changed signal");
-
        DBusMessageIter args, dict;
-       const char *service_path = dbus_message_get_path(message);
        struct telephony_modem *modem;
-       struct telephony_service *s_service;
        gboolean roaming_option = TRUE;
+       struct telephony_service *s_service;
+       const char *service_path = dbus_message_get_path(message);
 
-       DBG("service path %s", service_path);
+       DBG("service changed signal %s", service_path);
 
        s_service = g_hash_table_lookup(service_hash, service_path);
        if (s_service == NULL) {
@@ -1412,11 +1548,11 @@ static gboolean __changed_service(DBusConnection *connection,
 
                DBG("key(%s), value(%s)", key, tmp);
 
-               if (g_str_equal(key, "roaming") == TRUE) {
+               if (g_strcmp0(key, "roaming") == 0) {
                        s_service->roaming = STRING2BOOL(tmp);
-               } else if (g_str_equal(key, "act") == TRUE) {
+               } else if (g_strcmp0(key, "act") == 0) {
                        s_service->act = g_strdup(tmp);
-               } else if (g_str_equal(key, "ps_attached") == TRUE) {
+               } else if (g_strcmp0(key, "ps_attached") == 0) {
                        s_service->ps_attached = STRING2BOOL(tmp);
                }
 
@@ -1429,16 +1565,15 @@ static gboolean __changed_service(DBusConnection *connection,
        return TRUE;
 }
 
-
 static gboolean __added_service(DBusConnection *connection,
                                DBusMessage *message, void *user_data)
 {
-       DBG("service added signal");
-
-       const char *path = dbus_message_get_path(message);
+       struct telephony_modem *modem;
        const char *service_path = NULL;
        DBusMessageIter args, dict, tmp;
-       struct telephony_modem *modem;
+       const char *path = dbus_message_get_path(message);
+
+       DBG("service added signal %s", path);
 
        modem = g_hash_table_lookup(modem_hash, path);
        if (modem == NULL || modem->device == NULL)
@@ -1465,9 +1600,8 @@ static gboolean __added_service(DBusConnection *connection,
 
                DBG("key (%s) value(%s)", key, value);
 
-               if (g_str_equal(key, "path") == TRUE) {
-                       service_path = g_strdup(value);
-               }
+               if (g_strcmp0(key, "path") == 0)
+                       service_path = value;
 
                dbus_message_iter_next(&tmp);
        }
@@ -1481,11 +1615,11 @@ static gboolean __added_service(DBusConnection *connection,
 static gboolean __removed_service(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
-       DBG("service removed signal");
-
        DBusMessageIter iter;
        const char *service_path;
 
+       DBG("service removed signal");
+
        if (dbus_message_iter_init(message, &iter) == FALSE) {
                DBG("error to read message");
                return TRUE;
@@ -1500,19 +1634,18 @@ static gboolean __removed_service(DBusConnection *connection,
 static gboolean __changed_context(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
-       DBG("network changed signal");
-
        gboolean active = FALSE;
-       const char *path = dbus_message_get_path(message);
-       struct telephony_network *info;
        DBusMessageIter args, dict;
+       struct telephony_network *info;
+       const char *path = dbus_message_get_path(message);
+
+       DBG("network changed signal %s", path);
 
-       DBG("path %s", path);
        info = g_hash_table_lookup(network_hash, path);
        if (info == NULL)
                return TRUE;
 
-       if (!__check_network_available(info->network)) {
+       if (__check_network_available(info->network) == FALSE) {
                g_hash_table_remove(network_hash, path);
                return TRUE;
        }
@@ -1524,13 +1657,28 @@ static gboolean __changed_context(DBusConnection *connection,
 
        dbus_message_iter_recurse(&args, &dict);
 
-       active = __set_network_ipconfig(info, &dict);
+       active = __set_network_context(info, &dict);
+       if(info->routing_only){
+               int err = 0;
+               struct connman_service *routing_service;
+               struct connman_ipconfig *routing_ipconfig;
 
-       if (active == FALSE)
-               __set_network_connected(info, active);
-       else if ((connman_network_get_connecting(info->network) ||
-                       connman_network_get_associating(info->network)))
-               __set_network_connected(info, active);
+               if(!active)
+                       return TRUE;
+
+               routing_service = connman_service_lookup_from_network(info->network);
+               routing_ipconfig = __connman_service_get_ip4config(routing_service);
+               err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
+
+               DBG("set gateway rv(%d)", err);
+               return TRUE;
+       }
+
+       __set_network_connected(info, active);
+
+       if (active == FALSE &&
+                       connman_network_get_connecting(info->network) == TRUE)
+               connman_network_set_connected(info->network, FALSE);
 
        return TRUE;
 }
@@ -1538,13 +1686,13 @@ static gboolean __changed_context(DBusConnection *connection,
 static gboolean __added_context(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
-       DBG("network added signal");
-
-       DBusMessageIter args, dict, tmp;
-       const char *path = dbus_message_get_path(message);
        const char *network_path = NULL;
-       struct telephony_service *service = NULL;
+       DBusMessageIter args, dict, tmp;
        struct telephony_modem *modem = NULL;
+       struct telephony_service *service = NULL;
+       const char *path = dbus_message_get_path(message);
+
+       DBG("network added signal %s", path);
 
        service = g_hash_table_lookup(service_hash, path);
        if (service == NULL || service->p_modem == NULL)
@@ -1575,7 +1723,7 @@ static gboolean __added_context(DBusConnection *connection,
 
                DBG("key (%s) value(%s)", key, value);
 
-               if (g_str_equal(key, "path") == TRUE)
+               if (g_strcmp0(key, "path") == 0)
                        network_path = g_strdup(value);
 
                dbus_message_iter_next(&tmp);
@@ -1590,12 +1738,12 @@ static gboolean __added_context(DBusConnection *connection,
 static gboolean __removed_context(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
-       DBG("network removed signal");
-
        DBusMessageIter iter;
-       const char *path = dbus_message_get_path(message);
        const char *network_path = NULL;
        struct telephony_service *service = NULL;
+       const char *path = dbus_message_get_path(message);
+
+       DBG("network removed signal %s", path);
 
        service = g_hash_table_lookup(service_hash, path);
        if (service == NULL || service->p_modem == NULL)
@@ -1612,23 +1760,40 @@ static gboolean __removed_context(DBusConnection *connection,
        return TRUE;
 }
 
+static gboolean __changed_default_subscription(DBusConnection *connection,
+               DBusMessage *message, void *user_data)
+{
+       DBusMessageIter args;
+
+       DBG("message signature (%s)", dbus_message_get_signature(message));
+       if (dbus_message_iter_init(message, &args) == FALSE)
+               return TRUE;
+
+       dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
+       DBG("default subscription: %d", telephony_default_subscription_id);
+
+       return TRUE;
+}
+
 /* telephony initialization */
-static guint watch;
-static guint modem_watch;
-static guint modem_added_watch;
-static guint modem_removed_watch;
-static guint service_watch;
-static guint service_added_watch;
-static guint service_removed_watch;
-static guint context_watch;
-static guint context_added_watch;
-static guint context_removed_watch;
+static guint watch = 0;
+static guint modem_watch = 0;
+static guint modem_added_watch = 0;
+static guint modem_removed_watch = 0;
+static guint service_watch = 0;
+static guint service_added_watch = 0;
+static guint service_removed_watch = 0;
+static guint context_watch = 0;
+static guint context_added_watch = 0;
+static guint context_removed_watch = 0;
+static guint default_subscription_watch = 0;
 
 static int telephony_init(void)
 {
-       DBG("telephony plugin");
        int err;
 
+       DBG("telephony plugin");
+
        connection = connman_dbus_get_connection();
        if (connection == NULL)
                return -EIO;
@@ -1641,16 +1806,19 @@ static int telephony_init(void)
        modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
                                                PS_MODEM_INTERFACE,
                                                PROPERTY_CHANGED,
-                                               __changed_modem, NULL, NULL);
+                                               __changed_modem,
+                                               NULL, NULL);
 
        modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
                                                PS_MASTER_INTERFACE,
-                                               MODEM_ADDED, __added_modem,
+                                               MODEM_ADDED,
+                                               __added_modem,
                                                NULL, NULL);
 
        modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
                                                PS_MASTER_INTERFACE,
-                                               MODEM_REMOVED, __removed_modem,
+                                               MODEM_REMOVED,
+                                               __removed_modem,
                                                NULL, NULL);
 
        service_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
@@ -1661,7 +1829,8 @@ static int telephony_init(void)
 
        service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
                                                PS_MODEM_INTERFACE,
-                                               SERVICE_ADDED, __added_service,
+                                               SERVICE_ADDED,
+                                               __added_service,
                                                NULL, NULL);
 
        service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
@@ -1678,7 +1847,8 @@ static int telephony_init(void)
 
        context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
                                                PS_SERVICE_INTERFACE,
-                                               CONTEXT_ADDED, __added_context,
+                                               CONTEXT_ADDED,
+                                               __added_context,
                                                NULL, NULL);
 
        context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
@@ -1687,12 +1857,19 @@ static int telephony_init(void)
                                                __removed_context,
                                                NULL, NULL);
 
+       default_subscription_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               "org.tizen.telephony.Network",
+                                               "DefaultDataSubscription",
+                                               __changed_default_subscription,
+                                               NULL, NULL);
+
        if (watch == 0 || modem_watch == 0 || modem_added_watch == 0
                        || modem_removed_watch == 0 || service_watch == 0
                        || service_added_watch == 0 || context_watch == 0
                        || service_removed_watch == 0
                        || context_added_watch == 0
-                       || context_removed_watch == 0) {
+                       || context_removed_watch == 0
+                       || default_subscription_watch == 0) {
                err = -EIO;
                goto remove;
        }
@@ -1727,6 +1904,7 @@ remove:
        g_dbus_remove_watch(connection, context_watch);
        g_dbus_remove_watch(connection, context_added_watch);
        g_dbus_remove_watch(connection, context_removed_watch);
+       g_dbus_remove_watch(connection, default_subscription_watch);
 
        dbus_connection_unref(connection);
        return err;
@@ -1744,6 +1922,7 @@ static void telephony_exit(void)
        g_dbus_remove_watch(connection, context_watch);
        g_dbus_remove_watch(connection, context_added_watch);
        g_dbus_remove_watch(connection, context_removed_watch);
+       g_dbus_remove_watch(connection, default_subscription_watch);
 
        telephony_disconnect(connection, NULL);