*
* 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 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"
#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"
#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;
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;
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);
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,
static void tech_remove(struct connman_technology *technology)
{
+ return;
}
static struct connman_technology_driver tech_driver = {
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)
g_hash_table_destroy(network_hash);
network_hash = NULL;
}
-
- return;
}
static void __remove_modem(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);
static int __network_connect(struct connman_network *network)
{
- struct connman_device *device;
- struct telephony_modem *modem;
- struct telephony_service *service;
-
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;
-
- service = modem->s_service;
- if (service == NULL)
- return -ENOLINK;
-
- if (modem->powered == FALSE)
- return -ENOLINK;
-
- if (modem->data_allowed == FALSE || service->ps_attached == FALSE)
- return -ENOLINK;
-
return __request_network_activate(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);
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, ...)
+ 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(PS_DBUS_SERVICE, path, interface, method);
if (message == NULL)
return -ENOMEM;
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;
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);
+ __response_get_services, g_strdup(path),
+ g_free, DBUS_TYPE_INVALID);
}
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;
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);
+ 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)
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,
__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");
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;
}
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);
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);
+ 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_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)
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;
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);
__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,
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);
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);
}
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;
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);
}
modem->device = device;
-
- return;
}
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)
g_slist_free(info_list);
}
-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);
-
- return;
-}
-
-static int __check_device_powered(const char *path, gboolean powered)
+static gboolean connman_ipaddress_updated(struct connman_ipaddress *ipaddress,
+ const char *address, const char *gateway)
{
- 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)
+ __connman_service_nameserver_append(service, ipv4_dns1, FALSE);
+ //if (ipv4_dns2)
+ if (ipv4_dns2 && !ipv4_dns1)
+ __connman_service_nameserver_append(service, ipv4_dns2, FALSE);
/* ipv6 set */
- if (ipv6_addr == NULL)
- ipv6_addr = "::";
+ if (network->ipv6_address == NULL)
+ network->ipv6_address =
+ connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
- if (g_str_equal(ipv6_addr, "::")) {
- network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
- } else {
+ 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;
- unsigned char prefix_length = 64;
- network->ipv6_address =
- connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
- if (network->ipv6_address == NULL)
- return FALSE;
- connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
- prefix_length, ipv6_gw);
+ if (ipv6_addr == NULL)
+ network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
- dns_flag = 0;
+ connman_network_set_ipv6_method(network->network, network->ipv6_method);
- if (ipv6_dns1 == NULL)
- ipv6_dns1 = "::";
- if (ipv6_dns2 == NULL)
- ipv6_dns2 = "::";
+ 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 (g_str_equal(ipv6_dns1, "::"))
- dns_flag += 1;
+ if (ipv6_dns1)
+ __connman_service_nameserver_append(service, ipv6_dns1, FALSE);
+ //if (ipv6_dns2)
+ if (ipv6_dns2 && !ipv6_dns1)
+ __connman_service_nameserver_append(service, ipv6_dns2, FALSE);
- 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:
- break;
- case CONNMAN_IPCONFIG_METHOD_AUTO:
- connman_network_set_ipv6_method(network->network,
- network->ipv6_method);
- setip = TRUE;
- 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) {
return TRUE;
}
+ old_powered = modem->powered;
+
DBG("message signature (%s)", dbus_message_get_signature(message));
if (dbus_message_iter_init(message, &args) == FALSE) {
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);
}
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;
}
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;
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);
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;
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) {
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);
}
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)
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);
}
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;
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;
}
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;
}
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)
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);
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)
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;
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,
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,
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,
__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;
}
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;
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);
bool hidden_service;
char *config_file;
char *config_entry;
+#if defined TIZEN_EXT
+ /*
+ * Description: TIZEN implements system global connection management.
+ * It's only for PDP (cellular) bearer. Wi-Fi is managed
+ * by ConnMan automatically. Reference count can help to
+ * manage open/close connection requests by each application.
+ */
+ int user_pdn_connection_refcount;
+#endif
+#if defined TIZEN_TV_EXT
+ enum connman_dnsconfig_method dns_config_method;
+#endif
};
static bool allow_property_changed(struct connman_service *service);
struct connman_service *service;
};
+#if defined TIZEN_EXT
+/*
+ * Public APIs to use user_pdn_connection_refcount
+ */
+void connman_service_user_pdn_connection_ref(struct connman_service *service)
+{
+ __sync_fetch_and_add(&service->user_pdn_connection_refcount, 1);
+
+ DBG("User made PDN connection referenced: %d",
+ service->user_pdn_connection_refcount);
+}
+
+gboolean connman_service_user_pdn_connection_unref_and_test(
+ struct connman_service *service)
+{
+ __sync_synchronize();
+
+ DBG("User made PDN connection referenced: %d, which will be decreased",
+ service->user_pdn_connection_refcount);
+
+ if (service->user_pdn_connection_refcount < 1)
+ return TRUE;
+
+ if (__sync_sub_and_fetch(&service->user_pdn_connection_refcount, 1) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+gboolean connman_service_is_no_ref_user_pdn_connection(
+ struct connman_service *cellular)
+{
+ if (cellular == NULL)
+ return TRUE;
+
+ __sync_synchronize();
+ if (cellular->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ cellular->user_pdn_connection_refcount == 0)
+ return TRUE;
+
+ return FALSE;
+}
+#endif
+
static void compare_path(gpointer value, gpointer user_data)
{
struct connman_service *service = value;
g_timer_reset(service->stats_roaming.timer);
}
+#if defined TIZEN_EXT
+static gboolean __connman_service_is_internet_profile(
+ struct connman_service *cellular)
+{
+ const char internet_suffix[] = "_1";
+
+ DBG("Service path: %s", cellular->path);
+
+ if (g_str_has_suffix(cellular->path, internet_suffix) == TRUE)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean __connman_service_is_tethering_profile(
+ struct connman_service *cellular)
+{
+ const char tethering_suffix[] = "_5";
+
+ DBG("Service path: %s", cellular->path);
+
+ if (g_str_has_suffix(cellular->path, tethering_suffix) == TRUE)
+ return TRUE;
+
+ return FALSE;
+}
+
+struct connman_service *connman_service_get_default_connection(void)
+{
+ GList *list;
+ struct connman_service *service;
+ struct connman_service *default_service = NULL;
+
+ for (list = service_list; list; list = list->next) {
+ service = list->data;
+
+ DBG("service: %p %s %s %s", service, service->name,
+ state2string(service->state),
+ __connman_service_type2string(service->type));
+
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ is_connected(service) == TRUE) {
+ return service;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_is_internet_profile(service) == TRUE) {
+ if (default_service == NULL)
+ default_service = service;
+ else if (is_connected(service) == TRUE &&
+ is_connected(default_service) == FALSE)
+ default_service = service;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET &&
+ is_connected(service) == TRUE) {
+ if (default_service == NULL)
+ default_service = service;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH &&
+ is_connected(service) == TRUE) {
+ if (default_service == NULL)
+ default_service = service;
+ }
+ }
+
+ return default_service;
+}
+#endif
+
struct connman_service *__connman_service_get_default(void)
{
struct connman_service *service;
return service->timeservers;
}
+#if defined TIZEN_EXT
+/*
+ * Description: Telephony plug-in requires manual PROXY setting function
+ */
+int connman_service_set_proxy(struct connman_service *service,
+ const char *proxy, gboolean active)
+{
+ char **proxies_array = NULL;
+
+ if (service == NULL)
+ return -EINVAL;
+
+ switch (service->type) {
+ case CONNMAN_SERVICE_TYPE_CELLULAR:
+ case CONNMAN_SERVICE_TYPE_ETHERNET:
+ case CONNMAN_SERVICE_TYPE_WIFI:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ g_strfreev(service->proxies);
+ service->proxies = NULL;
+
+ if (proxy != NULL)
+ proxies_array = g_strsplit(proxy, " ", 0);
+
+ service->proxies = proxies_array;
+
+ if (proxy == NULL) {
+ service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
+ DBG("proxy changed (%d)", active);
+ } else {
+ service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
+ DBG("proxy chagned %s (%d)", proxy, active);
+ }
+
+ if (active == TRUE) {
+ proxy_changed(service);
+
+ __connman_notifier_proxy_changed(service);
+ }
+
+ return 0;
+}
+#endif
+
void connman_service_set_proxy_method(struct connman_service *service,
enum connman_service_proxy_method method)
{
CONNMAN_SERVICE_CONNECT_REASON_USER) {
DBG("service %p name %s is user connected",
service, service->name);
+#if defined TIZEN_EXT
+ /* We can connect to a favorite service like
+ * wifi even we have a userconnect for cellular
+ * because we have refount for cellular service
+ */
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ break;
+#endif
return NULL;
}
}
DBG("service %p", service);
+#if defined TIZEN_EXT
+ /*
+ * Description: TIZEN implements system global connection management.
+ */
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ connman_service_user_pdn_connection_ref(service);
+#endif
+
if (service->pending)
return __connman_error_in_progress(msg);
for (list = service_list; list; list = list->next) {
struct connman_service *temp = list->data;
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ break;
+#endif
if (!is_connecting(temp) && !is_connected(temp))
break;
DBG("service %p", service);
+#if defined TIZEN_EXT
+ /*
+ * Description: TIZEN implements system global connection management.
+ */
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
+ if (connman_service_user_pdn_connection_unref_and_test(service) != TRUE)
+ return __connman_error_failed(msg, EISCONN);
+
+ if (is_connected(service) == TRUE &&
+ service == connman_service_get_default_connection())
+ return __connman_error_failed(msg, EISCONN);
+ }
+#endif
+
if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
uid_t uid;
if (connman_dbus_get_connection_unix_user_sync(conn,
service->provider = NULL;
service->wps = false;
+#if defined TIZEN_EXT
+ /*
+ * Description: TIZEN implements system global connection management.
+ */
+ service->user_pdn_connection_refcount = 0;
+ __sync_synchronize();
+#endif
}
/**
services_dirty = true;
}
+#if defined TIZEN_EXT
+/**
+ * Returns profile count if there is any connected profiles
+ * that use same interface
+ */
+int __connman_service_get_connected_count_of_iface(
+ struct connman_service *service)
+{
+ GList *list;
+ int count = 0;
+ int index1 = 0;
+ int index2 = 0;
+
+ DBG("");
+
+ index1 = __connman_service_get_index(service);
+
+ if (index1 <= 0)
+ return 0;
+
+ for (list = service_list; list; list = list->next) {
+ struct connman_service *service2 = list->data;
+
+ if (service == service2)
+ continue;
+
+ index2 = __connman_service_get_index(service2);
+
+ if (is_connected(service2) && index2 > 0 && index1 == index2)
+ count++;
+
+ index2 = 0;
+ }
+
+ DBG("Interface index %d, count %d", index1, count);
+
+ return count;
+}
+#endif
+
/**
* __connman_service_set_favorite_delayed:
* @service: service structure
bool favorite,
bool delay_ordering)
{
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ return -EIO;
+#endif
if (service->hidden)
return -EOPNOTSUPP;
return -EALREADY;
}
+#if defined TIZEN_EXT
+static gboolean __connman_service_can_drop(struct connman_service *service)
+{
+ if (is_connected(service) == TRUE || is_connecting(service) == TRUE) {
+ if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
+ return TRUE;
+ else if (connman_service_is_no_ref_user_pdn_connection(service) == TRUE)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static struct connman_device *default_connecting_device = NULL;
+
+static void __connman_service_disconnect_default(struct connman_service *service)
+{
+ struct connman_device *default_device = NULL;
+
+ if (default_connecting_device == NULL)
+ return;
+
+ default_device = connman_network_get_device(
+ __connman_service_get_network(service));
+
+ DBG("Disconnecting service %p %s", service, service->path);
+ DBG("Disconnecting device %p %p %s",
+ default_connecting_device,
+ default_device,
+ connman_device_get_string(default_device, "Name"));
+
+ if (default_connecting_device == default_device)
+ default_connecting_device = NULL;
+}
+
+static void __connman_service_connect_default(struct connman_service *current)
+{
+ int err;
+ GList *list;
+ bool default_internet;
+ struct connman_service *service;
+ struct connman_service *default_service = NULL;
+ struct connman_device *default_device = NULL;
+
+ if (current->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
+ switch (current->state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ return;
+ default:
+ break;
+ }
+
+ if (default_connecting_device &&
+ __connman_service_is_internet_profile(current) == TRUE) {
+ if (current->network == NULL)
+ return;
+
+ default_device = connman_network_get_device(current->network);
+ if (default_connecting_device == default_device) {
+ DBG("Cellular service[%s] %p %s",
+ state2string(current->state), current, current->path);
+ DBG("Cellular device %p %p %s",
+ default_connecting_device, default_device,
+ connman_device_get_string(default_device, "Name"));
+
+ default_connecting_device = NULL;
+ }
+ }
+
+ return;
+ } else if (is_connected(current) == TRUE || is_connecting(current) == TRUE)
+ return;
+
+ /* Always-on: keep default cellular connection as possible */
+ for (list = service_list; list; list = list->next) {
+ service = list->data;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
+ __connman_service_is_internet_profile(service) != TRUE ||
+ service->network == NULL) {
+ continue;
+ }
+
+ default_internet =
+ connman_network_get_bool(service->network, "DefaultInternet");
+
+ DBG("service: %p %s %s %s (default: %d)", service, service->name,
+ __connman_service_type2string(service->type),
+ state2string(service->state), default_internet);
+
+ if (default_internet) {
+ default_service = service;
+ if (is_connected(default_service) == TRUE ||
+ is_connecting(default_service) == TRUE)
+ return;
+
+ default_device = connman_network_get_device(default_service->network);
+ if (default_connecting_device == default_device) {
+ DBG("Device is connecting (%p)", default_connecting_device);
+ return;
+ }
+
+ default_connecting_device = default_device;
+ default_service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
+
+ err = __connman_network_connect(default_service->network);
+ DBG("Connecting default service %p %s [%d]",
+ default_service, default_service->path, err);
+ DBG("Connecting device %p %s", default_connecting_device,
+ connman_device_get_string(default_connecting_device, "Name"));
+ if (err < 0 && err != -EINPROGRESS) {
+ default_connecting_device = NULL;
+ } else
+ break;
+ }
+ }
+}
+#endif
+
static void single_connected_tech(struct connman_service *allowed)
{
struct connman_service *service;
for (iter = service_list; iter; iter = iter->next) {
service = iter->data;
+#if defined TIZEN_EXT
+ if (service != allowed && service->type != allowed->type &&
+ __connman_service_can_drop(service) == TRUE)
+#else
if (!is_connected(service))
break;
if (service == allowed)
continue;
-
+#endif
services = g_slist_prepend(services, service);
}
service = list->data;
DBG("disconnecting %p %s", service, service->path);
+#if defined TIZEN_EXT
+ __connman_service_disconnect_default(service);
+#endif
__connman_service_disconnect(service);
}
__connman_wpad_stop(service);
+#if defined TIZEN_EXT
+ /**
+ * Skip the functions if there is any connected profiles
+ * that use same interface
+ */
+ if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
+ __connman_service_get_connected_count_of_iface(
+ service) <= 0) {
+#endif
dns_changed(service);
domain_changed(service);
proxy_changed(service);
+#if defined TIZEN_EXT
+ }
+#endif
/*
* Previous services which are connected and which states
service_list_sort();
+#if defined TIZEN_EXT
+ __connman_service_connect_default(service);
+#endif
+
__connman_connection_update_gateway();
if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
if (*old_state == new_state)
return -EALREADY;
+#if defined TIZEN_EXT
+ __sync_synchronize();
+ if (service->user_pdn_connection_refcount > 0 &&
+ service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ if (new_state == CONNMAN_SERVICE_STATE_FAILURE ||
+ new_state == CONNMAN_SERVICE_STATE_DISCONNECT ||
+ new_state == CONNMAN_SERVICE_STATE_IDLE) {
+ service->user_pdn_connection_refcount = 0;
+ __sync_synchronize();
+ }
+#endif
+
DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
service, service ? service->identifier : NULL,
*old_state, state2string(*old_state),
__connman_ipconfig_enable(ipconfig);
break;
case CONNMAN_SERVICE_STATE_READY:
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_is_internet_profile(service) != TRUE) {
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ service_rp_filter(service, TRUE);
+
+ break;
+ }
+#endif
if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
check_proxy_setup(service);
service_rp_filter(service, true);
__connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
NULL);
+#if defined TIZEN_EXT
+ /**
+ * Skip the functions If there is any connected profiles
+ * that use same interface
+ */
+ if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
+ __connman_service_get_connected_count_of_iface(service) <= 0) {
+#endif
__connman_ipconfig_address_remove(service->ipconfig_ipv4);
settings_changed(service, service->ipconfig_ipv4);
__connman_ipconfig_disable(service->ipconfig_ipv4);
__connman_ipconfig_disable(service->ipconfig_ipv6);
+#if defined TIZEN_EXT
+ }
+#endif
__connman_stats_service_unregister(service);
if (!service->favorite)
return 0;
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
+ service->do_split_routing == FALSE)
+ order = 10;
+ else if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
+ if (service->order < 5)
+ order = 5;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
+ order = 4;
+ else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
+ order = 3;
+ else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_is_internet_profile(service) == TRUE)
+ order = 1;
+ else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_is_tethering_profile(service) == TRUE)
+ order = 0;
+ else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ order = 0;
+ else
+ order = 2;
+#else
if (service == service_list->data)
order = 1;
service->order = 10;
order = 10;
}
-
+#endif
DBG("service %p name %s order %d split %d", service, service->name,
order, service->do_split_routing);