diff options
Diffstat (limited to 'plugins')
-rwxr-xr-x[-rw-r--r--] | plugins/bluetooth.c | 36 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/connman-nmcompat.conf | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/dundee.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/ethernet.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/gadget.c | 87 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/hh2serial-gps.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/iospm.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/loopback.c | 53 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/mcc.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/neard.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/nmcompat.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/ofono.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/pacrunner.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/polkit.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/polkit.policy | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/session_policy_local.c | 0 | ||||
-rwxr-xr-x | plugins/telephony.c | 1934 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/tist.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/vpn.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/wifi.c | 902 |
20 files changed, 2994 insertions, 24 deletions
diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c index f759a902..f89edfa0 100644..100755 --- a/plugins/bluetooth.c +++ b/plugins/bluetooth.c @@ -192,8 +192,14 @@ static bool pan_connect(struct bluetooth_pan *pan, return false; } +#if defined TIZEN_EXT + if (pan->network) { +#endif connman_network_set_index(pan->network, index); connman_network_set_connected(pan->network, true); +#if defined TIZEN_EXT + } +#endif return true; } @@ -211,6 +217,18 @@ static void pan_connect_cb(DBusMessage *message, void *user_data) return; } +#ifdef TIZEN_EXT + /* + * Network could be removed because of BT adapter power off + * This is to handle the scenario where network is removed + * before the connect_cb is called + */ + if (!pan->network) { + DBG("network already removed"); + return; + } +#endif + if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) { const char *dbus_error = dbus_message_get_error_name(message); @@ -262,6 +280,9 @@ static int bluetooth_pan_connect(struct connman_network *network) g_strdup(path), g_free)) return -EIO; +#if defined TIZEN_EXT + if (pan->network) +#endif connman_network_set_associating(pan->network, true); return -EINPROGRESS; @@ -286,6 +307,9 @@ static void pan_disconnect_cb(DBusMessage *message, void *user_data) DBG("network %p", pan->network); +#if defined TIZEN_EXT + if (pan->network) +#endif connman_network_set_connected(pan->network, false); } @@ -299,6 +323,11 @@ static int bluetooth_pan_disconnect(struct connman_network *network) if (!pan) return -EINVAL; +#if defined TIZEN_EXT + if (connman_network_get_associating(network) == TRUE) + connman_network_clear_associating(network); +#endif + path = g_dbus_proxy_get_path(pan->btnetwork_proxy); if (!g_dbus_proxy_method_call(pan->btnetwork_proxy, "Disconnect", @@ -524,7 +553,10 @@ static void device_enable_cb(const DBusError *error, void *user_data) goto out; } +#if !defined TIZEN_EXT enable_device(device, path); +#endif + out: g_free(path); } @@ -591,7 +623,9 @@ static void device_disable_cb(const DBusError *error, void *user_data) goto out; } +#if !defined TIZEN_EXT disable_device(device, path); +#endif out: g_free(path); @@ -883,7 +917,7 @@ static void bluetooth_tech_remove(struct connman_technology *technology) static int bluetooth_tech_set_tethering(struct connman_technology *technology, const char *identifier, const char *passphrase, - const char *bridge, bool enabled) + const char *bridge, bool enabled, bool hidden) { GHashTableIter hash_iter; gpointer key, value; diff --git a/plugins/connman-nmcompat.conf b/plugins/connman-nmcompat.conf index 5887a345..a051d927 100644..100755 --- a/plugins/connman-nmcompat.conf +++ b/plugins/connman-nmcompat.conf @@ -5,6 +5,10 @@ <allow own="org.freedesktop.NetworkManager"/> <allow send_destination="org.freedesktop.NetworkManager"/> </policy> + <policy user="network_fw"> + <allow own="org.freedesktop.NetworkManager"/> + <allow send_destination="org.freedesktop.NetworkManager"/> + </policy> <policy at_console="true"> <allow send_destination="org.freedesktop.NetworkManager"/> </policy> diff --git a/plugins/dundee.c b/plugins/dundee.c index b5420acf..b5420acf 100644..100755 --- a/plugins/dundee.c +++ b/plugins/dundee.c diff --git a/plugins/ethernet.c b/plugins/ethernet.c index 9a4d7413..9a4d7413 100644..100755 --- a/plugins/ethernet.c +++ b/plugins/ethernet.c diff --git a/plugins/gadget.c b/plugins/gadget.c index 94f66487..cce51e26 100644..100755 --- a/plugins/gadget.c +++ b/plugins/gadget.c @@ -25,6 +25,8 @@ #include <errno.h> #include <net/if.h> +#include <stdio.h> +#include <string.h> #ifndef IFF_LOWER_UP #define IFF_LOWER_UP 0x10000 @@ -226,6 +228,71 @@ static struct connman_device_driver gadget_dev_driver = { }; static GList *cdc_interface_list = NULL; +static GHashTable *cdc_mac_hash = NULL; + +static void add_station(int index) +{ + char *path, line[128] = {'\0'}; + char *ifname = connman_inet_ifname(index); + char *mac; + FILE *f; + + if (ifname == NULL) + return; + + path = g_strdup_printf("/sys/class/usb_mode/%s/f_rndis/ethaddr", + ifname); + + f = fopen(path, "re"); + + g_free(ifname); + g_free(path); + + if (f == NULL) + return; + + if (fgets(line, sizeof(line), f) == NULL) { + fclose(f); + return; + } + + fclose(f); + + mac = g_ascii_strdown(line, strlen(line) - 1); + DBG("Add station %s in Technology %d", mac, + CONNMAN_SERVICE_TYPE_GADGET); + + g_hash_table_insert(cdc_mac_hash, GINT_TO_POINTER(index), + mac); + + connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_GADGET, + mac); +} + +static void remove_station(int index) +{ + char *mac; + mac = g_hash_table_lookup(cdc_mac_hash, GINT_TO_POINTER(index)); + if (mac == NULL) + return; + + connman_technology_tethering_remove_station(mac); + + g_hash_table_remove(cdc_mac_hash, GINT_TO_POINTER(index)); +} + +static gboolean remove_all_station(gpointer key, gpointer value, gpointer user_data) +{ + char *mac; + mac = value; + if (mac == NULL) + return TRUE; + + connman_technology_tethering_remove_station(mac); + + return TRUE; +} + static void gadget_tech_add_interface(struct connman_technology *technology, int index, const char *name, const char *ident) @@ -246,6 +313,8 @@ static void gadget_tech_remove_interface(struct connman_technology *technology, cdc_interface_list = g_list_remove(cdc_interface_list, GINT_TO_POINTER((int) index)); + + remove_station(index); } static void gadget_tech_enable_tethering(struct connman_technology *technology, @@ -270,6 +339,8 @@ static void gadget_tech_enable_tethering(struct connman_technology *technology, connman_inet_ifup(index); connman_inet_add_to_bridge(index, bridge); + + add_station(index); } } @@ -283,6 +354,8 @@ static void gadget_tech_disable_tethering(struct connman_technology *technology, connman_inet_remove_from_bridge(index, bridge); + remove_station(index); + connman_inet_ifdown(index); connman_technology_tethering_notify(technology, false); @@ -305,14 +378,28 @@ static int gadget_tech_set_tethering(struct connman_technology *technology, static int gadget_tech_probe(struct connman_technology *technology) { + DBG("tech probe %p", technology); + + cdc_mac_hash = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, g_free); + return 0; } static void gadget_tech_remove(struct connman_technology *technology) { + DBG("tech remove %p", technology); + g_list_free(cdc_interface_list); cdc_interface_list = NULL; + + if (cdc_mac_hash) { + g_hash_table_foreach_remove(cdc_mac_hash, remove_all_station, + NULL); + g_hash_table_destroy(cdc_mac_hash); + cdc_mac_hash = NULL; + } } static struct connman_technology_driver gadget_tech_driver = { diff --git a/plugins/hh2serial-gps.c b/plugins/hh2serial-gps.c index 99394e1c..99394e1c 100644..100755 --- a/plugins/hh2serial-gps.c +++ b/plugins/hh2serial-gps.c diff --git a/plugins/iospm.c b/plugins/iospm.c index fcb4cea1..fcb4cea1 100644..100755 --- a/plugins/iospm.c +++ b/plugins/iospm.c diff --git a/plugins/loopback.c b/plugins/loopback.c index e113887d..44100c64 100644..100755 --- a/plugins/loopback.c +++ b/plugins/loopback.c @@ -23,6 +23,8 @@ #include <config.h> #endif +#include <stdio.h> + #include <errno.h> #include <unistd.h> #include <limits.h> @@ -34,6 +36,8 @@ #include <net/if.h> #include <glib.h> +#include <glib/gprintf.h> + #define CONNMAN_API_SUBJECT_TO_CHANGE #include <connman/plugin.h> @@ -62,16 +66,47 @@ static int setup_hostname(void) memset(system_hostname, 0, sizeof(system_hostname)); - if (gethostname(system_hostname, HOST_NAME_MAX) < 0) { - connman_error("Failed to get current hostname"); - return -EIO; - } +#if defined TIZEN_EXT + FILE *fp = NULL; +#define WIFI_MAC "/opt/etc/.mac.info" + { + char* rv = 0; + gchar* dev_id = "TIZEN"; + char wifi_mac[HOST_NAME_MAX + 1]; + + fp = fopen(WIFI_MAC, "r"); + if(!fp){ + connman_error("Failed to get current hostname"); + strncpy(system_hostname, dev_id, strlen(dev_id)); + goto host_name_end; + } + + rv = fgets(wifi_mac, HOST_NAME_MAX, fp); + if(!rv){ + connman_error("Failed to get current hostname"); + strncpy(system_hostname, dev_id, strlen(dev_id)); + fclose(fp); + goto host_name_end; + } + + dev_id = g_base64_encode((const guchar *)wifi_mac, strlen(wifi_mac)); + g_sprintf(system_hostname, "TIZEN-%s", dev_id); + g_free(dev_id); + fclose(fp); + } - if (strlen(system_hostname) > 0 && - strcmp(system_hostname, "(none)") != 0) - connman_info("System hostname is %s", system_hostname); - else - create_hostname(); + host_name_end : +#else + if (gethostname(system_hostname, HOST_NAME_MAX) < 0) { + connman_error("Failed to get current hostname"); + return -EIO; + } +#endif + if (strlen(system_hostname) > 0 && + strcmp(system_hostname, "(none)") != 0) + connman_info("System hostname is %s", system_hostname); + else + create_hostname(); memset(name, 0, sizeof(name)); diff --git a/plugins/mcc.h b/plugins/mcc.h index 0e0407c9..0e0407c9 100644..100755 --- a/plugins/mcc.h +++ b/plugins/mcc.h diff --git a/plugins/neard.c b/plugins/neard.c index 69586df6..69586df6 100644..100755 --- a/plugins/neard.c +++ b/plugins/neard.c diff --git a/plugins/nmcompat.c b/plugins/nmcompat.c index 883ce9bd..883ce9bd 100644..100755 --- a/plugins/nmcompat.c +++ b/plugins/nmcompat.c diff --git a/plugins/ofono.c b/plugins/ofono.c index 78f8f196..78f8f196 100644..100755 --- a/plugins/ofono.c +++ b/plugins/ofono.c diff --git a/plugins/pacrunner.c b/plugins/pacrunner.c index d2464a5e..d2464a5e 100644..100755 --- a/plugins/pacrunner.c +++ b/plugins/pacrunner.c diff --git a/plugins/polkit.c b/plugins/polkit.c index ae38364a..ae38364a 100644..100755 --- a/plugins/polkit.c +++ b/plugins/polkit.c diff --git a/plugins/polkit.policy b/plugins/polkit.policy index 0de152ce..0de152ce 100644..100755 --- a/plugins/polkit.policy +++ b/plugins/polkit.policy diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index f003c0e1..f003c0e1 100644..100755 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c diff --git a/plugins/telephony.c b/plugins/telephony.c new file mode 100755 index 00000000..2b4c5a4a --- /dev/null +++ b/plugins/telephony.c @@ -0,0 +1,1934 @@ +/* + * + * Connection Manager + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <errno.h> +#include <gdbus.h> +#include <stdlib.h> +#include <string.h> + +#define CONNMAN_API_SUBJECT_TO_CHANGE +#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.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_SERVICE_INTERFACE PS_DBUS_SERVICE ".service" +#define PS_CONTEXT_INTERFACE PS_DBUS_SERVICE ".context" + +/* methods */ +#define GET_MODEMS "GetModems" +#define GET_SERVICES "GetServices" +#define GET_CONTEXTS "GetContexts" +#define ACTIVATE_CONTEXT "Activate" +#define DEACTIVATE_CONTEXT "Deactivate" +#define GET_PROPERTIES "GetProperties" +#define SET_PROPERTY "SetProperties" + +/* signals */ +#define MODEM_ADDED "ModemAdded" +#define MODEM_REMOVED "ModemRemoved" +#define SERVICE_ADDED "ServiceAdded" +#define SERVICE_REMOVED "ServiceRemoved" +#define CONTEXT_ADDED "ContextAdded" +#define CONTEXT_REMOVED "ContextRemoved" +#define PROPERTY_CHANGED "PropertyChanged" + +#define TIMEOUT 130000 + +#define STRING2BOOL(a) (!(g_strcmp0(a, "TRUE")) ? (TRUE):(FALSE)) + +static DBusConnection *connection; +static GHashTable *modem_hash; +static GHashTable *service_hash; +static GHashTable *network_hash; + +struct telephony_service { + char *path; + + gpointer p_modem; + char *act; + gboolean roaming; /* global roaming state */ + gboolean ps_attached; /* packet service is available */ +}; + +struct telephony_modem { + char *path; + + char *operator; + gboolean powered; + gboolean sim_init; + gboolean flight_mode; + gboolean data_allowed; + gboolean roaming_allowed; + + struct connman_device *device; + struct telephony_service *s_service; +}; + +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 *ipv4_address; + + enum connman_ipconfig_method ipv6_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 __remove_modem(gpointer data); +static void __remove_service(gpointer data); +static void __remove_network(gpointer data); + +static int __modem_probe(struct connman_device *device); +static void __modem_remove(struct connman_device *device); +static int __modem_enable(struct connman_device *device); +static int __modem_disable(struct connman_device *device); + +static int __network_probe(struct connman_network *network); +static void __network_remove(struct connman_network *network); +static int __network_connect(struct connman_network *network); +static int __network_disconnect(struct connman_network *network); + + +/* dbus request and reply */ +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 __request_get_modems(void); +static void __response_get_modems(DBusPendingCall *call, void *user_data); +static int __request_get_services(const char *path); +static void __response_get_services(DBusPendingCall *call, void *user_data); +static int __request_get_contexts(struct telephony_modem *modem); +static void __response_get_contexts(DBusPendingCall *call, void *user_data); +static int __request_network_activate(struct connman_network *network); +static void __response_network_activate(DBusPendingCall *call, void *user_data); +static int __request_network_deactivate(struct connman_network *network); + +/* telephony internal function */ +static void __add_modem(const char *path, DBusMessageIter *prop); +static void __add_service(struct telephony_modem *modem, + const char *service_path, DBusMessageIter *prop); +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 int __add_context(struct connman_device *device, const char *path, + DBusMessageIter *prop); + +/* signal handler */ +static gboolean __changed_modem(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __added_modem(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __removed_modem(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __changed_service(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __added_service(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __removed_service(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __changed_context(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __added_context(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __removed_context(DBusConnection *connection, + DBusMessage *message, void *user_data); + +/* device driver */ +static struct connman_device_driver modem_driver = { + .name = "device", + .type = CONNMAN_DEVICE_TYPE_CELLULAR, + .probe = __modem_probe, + .remove = __modem_remove, + .enable = __modem_enable, + .disable = __modem_disable, +}; + +/* network driver */ +static struct connman_network_driver network_driver = { + .name = "network", + .type = CONNMAN_NETWORK_TYPE_CELLULAR, + .probe = __network_probe, + .remove = __network_remove, + .connect = __network_connect, + .disconnect = __network_disconnect, +}; + +static int tech_probe(struct connman_technology *technology) +{ + return 0; +} + +static void tech_remove(struct connman_technology *technology) +{ + return; +} + +static struct connman_technology_driver tech_driver = { + .name = "cellular", + .type = CONNMAN_SERVICE_TYPE_CELLULAR, + .probe = tech_probe, + .remove = tech_remove, +}; + +/* local function */ +static void telephony_connect(DBusConnection *connection, void *user_data) +{ + DBG("connection %p", connection); + modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, __remove_modem); + service_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, __remove_service); + network_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, __remove_network); + + __request_get_modems(); +} + +static void telephony_disconnect(DBusConnection *connection, void *user_data) +{ + DBG("connection %p", connection); + + if (modem_hash != NULL) { + g_hash_table_destroy(modem_hash); + modem_hash = NULL; + } + + if (network_hash != NULL) { + g_hash_table_destroy(network_hash); + network_hash = NULL; + } +} + +static void __remove_modem(gpointer data) +{ + struct telephony_modem *modem = data; + + __remove_connman_device(modem); + + g_free(modem->path); + g_free(modem->operator); + g_free(modem); +} + +static void __remove_service(gpointer data) +{ + struct telephony_service *service = data; + + g_free(service->path); + g_free(service->act); + g_free(service); +} + +static void __remove_network(gpointer data) +{ + struct telephony_network *info = data; + struct connman_device *device; + + device = connman_network_get_device(info->network); + if (device != NULL) + connman_device_remove_network(device, info->network); + + 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); + return 0; +} + +static void __modem_remove(struct connman_device *device) +{ + DBG("device %p", device); +} + +static int __modem_enable(struct connman_device *device) +{ + const char *path = connman_device_get_string(device, "Path"); + DBG("device %p, path, %s", device, path); + + return __check_device_powered(path, TRUE); +} + +static int __modem_disable(struct connman_device *device) +{ + const char *path = connman_device_get_string(device, "Path"); + DBG("device %p, path, %s", device, path); + + return __check_device_powered(path, FALSE); +} + +static int __network_probe(struct connman_network *network) +{ + DBG("network_prove network(%p)", network); + return 0; +} + +static int __network_connect(struct connman_network *network) +{ + DBG("network %p", network); + + return __request_network_activate(network); +} + +static int __network_disconnect(struct connman_network *network) +{ + DBG("network %p", network); + + if (connman_network_get_associating(network) == TRUE) + connman_network_clear_associating(network); + + connman_network_set_associating(network, FALSE); + + return __request_network_deactivate(network); +} + +static void __network_remove(struct connman_network *network) +{ + char const *path = connman_network_get_string(network, "Path"); + DBG("network %p path %s", network, path); + + g_hash_table_remove(network_hash, path); +} + +static int __dbus_request(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("path %s %s.%s", path, interface, method); + + if (path == NULL) + return -EINVAL; + + message = dbus_message_new_method_call(PS_DBUS_SERVICE, path, interface, method); + if (message == NULL) + return -ENOMEM; + + dbus_message_set_auto_start(message, FALSE); + + va_start(va, type); + ok = dbus_message_append_args_valist(message, type, va); + va_end(va); + + if (!ok) + return -ENOMEM; + + if (dbus_connection_send_with_reply(connection, message, + &call, TIMEOUT) == FALSE) { + connman_error("Failed to call %s.%s", interface, method); + dbus_message_unref(message); + return -EINVAL; + } + + if (call == NULL) { + connman_error("D-Bus connection not available"); + dbus_message_unref(message); + return -EINVAL; + } + + dbus_pending_call_set_notify(call, notify, user_data, free_function); + + dbus_message_unref(message); + + return -EINPROGRESS; +} + +static int __request_get_modems(void) +{ + DBG("request get modem"); + /* call connect master */ + return __dbus_request("/", PS_MASTER_INTERFACE, GET_MODEMS, + __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID); +} + +static void __response_get_modems(DBusPendingCall *call, void *user_data) +{ + DBusMessage *reply; + DBusError error; + DBusMessageIter args, dict; + + DBG(""); + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + + if (dbus_set_error_from_message(&error, reply)) { + connman_error("GetModems() %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_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; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &modem_path); + DBG("modem path (%s)", modem_path); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &property); + + __add_modem(modem_path, &property); + + dbus_message_iter_next(&dict); + } + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); +} + +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); +} + +static void __response_get_services(DBusPendingCall *call, void *user_data) +{ + DBusMessage *reply; + DBusError error; + DBusMessageIter args, dict; + + const char *path = user_data; + struct telephony_modem *modem; + + modem = g_hash_table_lookup(modem_hash, path); + if (modem == NULL) + return; + if (modem->device == NULL) + return; + + DBG(""); + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + + if (dbus_set_error_from_message(&error, reply)) { + connman_error("GetServices() %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_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; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &service_path); + DBG("service path (%s)", service_path); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &property); + + __add_service(modem, service_path, &property); + + dbus_message_iter_next(&dict); + } + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); +} + +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); +} + +static void __response_get_contexts(DBusPendingCall *call, void *user_data) +{ + DBusError error; + DBusMessage *reply; + DBusMessageIter args, dict; + + const char *path = user_data; + struct telephony_modem *modem; + + DBG(""); + + modem = g_hash_table_lookup(modem_hash, path); + if (modem == NULL) + return; + if (modem->s_service == NULL) + return; + if (modem->device == NULL) + return; + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + + if (dbus_set_error_from_message(&error, reply)) { + connman_error("GetContexts() %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_recurse(&args, &dict); + + while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry, property; + const char *context_path; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &context_path); + DBG("context path (%s)", context_path); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &property); + + __add_context(modem->device, context_path, &property); + + dbus_message_iter_next(&dict); + } + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); +} + +static int __request_network_activate(struct connman_network *network) +{ + int n_modems; + const char *path = NULL; + struct telephony_modem *modem = NULL; + + 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"); + + DBusError error; + DBusMessage *reply; + + struct telephony_network *info; + const char *path = user_data; + + info = g_hash_table_lookup(network_hash, path); + reply = dbus_pending_call_steal_reply(call); + + if (info == NULL) + goto done; + + if (__check_network_available(info->network) == FALSE) { + g_hash_table_remove(network_hash, path); + goto done; + } + + dbus_error_init(&error); + if (dbus_set_error_from_message(&error, reply)) { + 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); + + dbus_error_free(&error); + goto done; + } + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); +} + +static int __request_network_deactivate(struct connman_network *network) +{ + 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); +} + +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) +{ + struct telephony_modem *modem; + + modem = g_hash_table_lookup(modem_hash, path); + if (modem != NULL) + return; + + modem = g_try_new0(struct telephony_modem, 1); + if (modem == NULL) + return; + + modem->path = g_strdup(path); + modem->device = NULL; + modem->s_service = NULL; + + g_hash_table_insert(modem_hash, g_strdup(path), modem); + + while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *tmp; + + dbus_message_iter_recurse(prop, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &tmp); + + DBG("key (%s) value(%s)", key, tmp); + + if (g_strcmp0(key, "powered") == 0) { + modem->powered = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "operator") == 0) { + modem->operator = g_strdup(tmp); + } else if (g_strcmp0(key, "sim_init") == 0) { + modem->sim_init = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "flight_mode") == 0) { + modem->flight_mode = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "roaming_allowed") == 0) { + modem->roaming_allowed = STRING2BOOL(tmp); + } 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); +} + +static void __add_service(struct telephony_modem *modem, + const char *service_path, DBusMessageIter *prop) +{ + struct telephony_service *service; + + if (modem->s_service != NULL) + return; + + service = g_try_new0(struct telephony_service, 1); + if (service == NULL) + return; + + service->path = g_strdup(service_path); + service->p_modem = modem; + g_hash_table_insert(service_hash, g_strdup(service_path), service); + + while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *tmp; + + dbus_message_iter_recurse(prop, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &tmp); + + DBG("key (%s) value(%s)", key, tmp); + + if (g_strcmp0(key, "roaming") == 0) { + service->roaming = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "act") == 0) { + service->act = g_strdup(tmp); + } else if (g_strcmp0(key, "ps_attached") == 0) { + service->ps_attached = STRING2BOOL(tmp); + } + + dbus_message_iter_next(prop); + } + + modem->s_service = service; + __request_get_contexts(modem); +} + +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; + + DBG("path %s operator %s", modem_path, operator); + + if (modem_path == NULL) + return; + + if (operator == NULL) + return; + + modem = g_hash_table_lookup(modem_hash, modem_path); + if (modem == NULL) + return; + + if (modem->device) { + if (!g_strcmp0(operator, + connman_device_get_ident(modem->device))) + return; + + __remove_connman_device(modem); + } + + if (strlen(operator) == 0) + return; + + device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR); + if (device == NULL) + return; + + 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); + + if (connman_device_register(device) < 0) { + connman_error("Failed to register cellular device"); + connman_device_unref(device); + return; + } + + modem->device = device; +} + +static void __remove_connman_device(struct telephony_modem *modem) +{ + DBG("modem %p path %s device %p", modem, modem->path, modem->device); + + if (modem->device == NULL) + return; + + __remove_connman_networks(modem->device); + + connman_device_unregister(modem->device); + connman_device_unref(modem->device); + + modem->device = NULL; +} + +static void __remove_connman_networks(struct connman_device *device) +{ + GHashTableIter iter; + gpointer key, value; + GSList *info_list = NULL; + GSList *list; + + if (network_hash == NULL) + return; + + g_hash_table_iter_init(&iter, network_hash); + + while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + struct telephony_network *info = value; + + if (connman_network_get_device(info->network) != device) + continue; + + info_list = g_slist_append(info_list, info); + } + + for (list = info_list; list != NULL; list = list->next) { + struct telephony_network *info = list->data; + connman_device_remove_network(device, info->network); + } + + g_slist_free(info_list); +} + +static gboolean connman_ipaddress_updated(struct connman_ipaddress *ipaddress, + const char *address, const char *gateway) +{ + if (ipaddress == NULL || address == NULL) + return FALSE; + + if (g_strcmp0(ipaddress->local, address) != 0) + return TRUE; + + if (g_strcmp0(ipaddress->gateway, gateway) != 0) + return TRUE; + + return FALSE; +} + +static void __set_network_connected(struct telephony_network *network, + gboolean connected) +{ + gboolean setip = FALSE; + + DBG("network %p connected %d", network, connected); + + connman_network_set_index(network->network, network->if_index); + if (connman_network_get_connected(network->network) == connected) + return; + + 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; + } + + 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; + } + + if (setip == TRUE) + connman_network_set_connected(network->network, connected); +} + +static gboolean __set_network_context( + struct telephony_network *network, + DBusMessageIter *dict) +{ + int index = 0; + gboolean active = FALSE; + 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; + struct connman_service *service; + + while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *value; + + dbus_message_iter_recurse(dict, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + + if (g_strcmp0(key, "dev_name") == 0) { + dbus_message_iter_get_basic(&entry, &dev_name); + DBG("dev_name (%s)", dev_name); + } else if (g_strcmp0(key, "proxy") == 0) { + dbus_message_iter_get_basic(&entry, &proxy_addr); + DBG("proxy_addr (%s)", proxy_addr); + } else if (g_strcmp0(key, "ipv4_address") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_addr); + DBG("ipv4_addr (%s)", ipv4_addr); + } else if (g_strcmp0(key, "ipv4_gateway") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_gw); + DBG("ipv4_gw (%s)", ipv4_gw); + } else if (g_strcmp0(key, "ipv4_netmask") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_netmask); + DBG("ipv4_netmask (%s)", ipv4_netmask); + } else if (g_strcmp0(key, "ipv4_dns1") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_dns1); + DBG("ipv4_dns1 (%s)", ipv4_dns1); + } else if (g_strcmp0(key, "ipv4_dns2") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_dns2); + 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_strcmp0(key, "ipv6_gateway") == 0) { + dbus_message_iter_get_basic(&entry, &ipv6_gw); + DBG("ipv6_gw (%s)", ipv6_gw); + } else if (g_strcmp0(key, "ipv6_netmask") == 0) { + dbus_message_iter_get_basic(&entry, &ipv6_netmask); + DBG("ipv6_netmask (%s)", ipv6_netmask); + } else if (g_strcmp0(key, "ipv6_dns1") == 0) { + dbus_message_iter_get_basic(&entry, &ipv6_dns1); + DBG("ipv6_dns1 (%s)", ipv6_dns1); + } else if (g_strcmp0(key, "ipv6_dns2") == 0) { + dbus_message_iter_get_basic(&entry, &ipv6_dns2); + 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); + } + + 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; + } + } + + /* interface index set */ + if (dev_name != NULL) { + index = connman_inet_ifindex(dev_name); + network->if_index = index; + DBG("interface index %d", index); + } + + /* proxy set */ + if (active == TRUE && + connman_network_get_connected(network->network) == TRUE) + active_proxy = TRUE; + + 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 (network->ipv4_address == NULL) + network->ipv4_address = + connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4); + + if (network->ipv4_address == NULL) + return FALSE; + + if (ipv4_addr == NULL && active == TRUE) + network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF; + else + network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED; + + 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) +#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 (network->ipv6_address == NULL) + network->ipv6_address = + connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6); + + 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; + + if (ipv6_addr == NULL) + network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF; + + connman_network_set_ipv6_method(network->network, network->ipv6_method); + + 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 (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); + + __set_network_connected(network, FALSE); + } else { + DBG("Already connected"); + + return active; + } + } + + if (active == TRUE) + connman_network_set_associating(network->network, TRUE); + + return active; +} + +static int __add_context(struct connman_device *device, const char *path, + DBusMessageIter *prop) +{ + 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; + + g_hash_table_remove(network_hash, path); + } + + network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR); + if (network == NULL) + return -ENOMEM; + + info = g_try_new0(struct telephony_network, 1); + if (info == NULL) { + connman_network_unref(network); + return -ENOMEM; + } + + 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); + + connman_network_set_group(network, ident); + + 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) +{ + gboolean old_powered; + DBusMessageIter args, dict; + struct telephony_modem *modem; + const char *path = dbus_message_get_path(message); + + DBG("modem changed signal %s", path); + + modem = g_hash_table_lookup(modem_hash, path); + if (modem == NULL) { + DBG("modem object does not exists"); + return TRUE; + } + + old_powered = modem->powered; + + DBG("message signature (%s)", dbus_message_get_signature(message)); + + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + + while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *tmp; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &tmp); + + DBG("key(%s), value(%s)", key, tmp); + + if (g_strcmp0(key, "powered") == 0) { + modem->powered = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "operator") == 0) { + modem->operator = g_strdup(tmp); + } else if (g_strcmp0(key, "sim_init") == 0) { + modem->sim_init = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "flight_mode") == 0) { + modem->flight_mode = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "roaming_allowed") == 0) { + modem->roaming_allowed = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "data_allowed") == 0) { + modem->data_allowed = STRING2BOOL(tmp); + } + + dbus_message_iter_next(&dict); + } + + if (modem->device == NULL) + __add_connman_device(path, modem->operator); + + 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 == NULL) { + __request_get_services(modem->path); + return TRUE; + } + + DBG("modem(%s) flight mode(%d) data allowed(%d)", + modem->path, modem->flight_mode, modem->data_allowed); + + return TRUE; +} + +static gboolean __added_modem(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + const char *modem_path = NULL; + DBusMessageIter args, dict, tmp; + + 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; + } + + dbus_message_iter_recurse(&args, &dict); + memcpy(&tmp, &dict, sizeof(struct DBusMessageIter)); + + while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *value; + + dbus_message_iter_recurse(&tmp, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &value); + + DBG("key (%s) value(%s)", key, value); + + if (g_strcmp0(key, "path") == 0) + modem_path = g_strdup(value); + + dbus_message_iter_next(&tmp); + } + + if (modem_path != NULL) + __add_modem(modem_path, &dict); + + return TRUE; +} + +static gboolean __removed_modem(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + 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; + } + + dbus_message_iter_get_basic(&iter, &modem_path); + g_hash_table_remove(modem_hash, modem_path); + + return TRUE; +} + +static gboolean __changed_service(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + DBusMessageIter args, dict; + struct telephony_modem *modem; + gboolean roaming_option = TRUE; + struct telephony_service *s_service; + const char *service_path = dbus_message_get_path(message); + + DBG("service changed signal %s", service_path); + + s_service = g_hash_table_lookup(service_hash, service_path); + if (s_service == NULL) { + DBG("service object does not exists"); + return TRUE; + } + + modem = s_service->p_modem; + if (modem == NULL) { + DBG("modem object does not exists"); + return TRUE; + } + + DBG("message signature (%s)", dbus_message_get_signature(message)); + + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + + while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *tmp; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &tmp); + + DBG("key(%s), value(%s)", key, tmp); + + if (g_strcmp0(key, "roaming") == 0) { + s_service->roaming = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "act") == 0) { + s_service->act = g_strdup(tmp); + } else if (g_strcmp0(key, "ps_attached") == 0) { + s_service->ps_attached = STRING2BOOL(tmp); + } + + dbus_message_iter_next(&dict); + } + + roaming_option &= (!s_service->roaming && !modem->roaming_allowed) + || modem->roaming_allowed; + + return TRUE; +} + +static gboolean __added_service(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct telephony_modem *modem; + const char *service_path = NULL; + DBusMessageIter args, dict, tmp; + 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) + return TRUE; + + DBG("message signature (%s)", dbus_message_get_signature(message)); + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + memcpy(&tmp, &dict, sizeof(struct DBusMessageIter)); + + while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *value; + + dbus_message_iter_recurse(&tmp, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &value); + + DBG("key (%s) value(%s)", key, value); + + if (g_strcmp0(key, "path") == 0) + service_path = value; + + dbus_message_iter_next(&tmp); + } + + if (service_path != NULL) + __add_service(modem, service_path, &dict); + + return TRUE; +} + +static gboolean __removed_service(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + 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; + } + + dbus_message_iter_get_basic(&iter, &service_path); + g_hash_table_remove(service_hash, service_path); + + return TRUE; +} + +static gboolean __changed_context(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + gboolean active = FALSE; + DBusMessageIter args, dict; + struct telephony_network *info; + const char *path = dbus_message_get_path(message); + + DBG("network changed signal %s", path); + + info = g_hash_table_lookup(network_hash, path); + if (info == NULL) + return TRUE; + + if (__check_network_available(info->network) == FALSE) { + g_hash_table_remove(network_hash, path); + return TRUE; + } + + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &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) + 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) +{ + const char *network_path = 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) + return TRUE; + + modem = service->p_modem; + if (modem == NULL || modem->device == NULL) + return TRUE; + + DBG("message signature (%s)", dbus_message_get_signature(message)); + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + memcpy(&tmp, &dict, sizeof(struct DBusMessageIter)); + + while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *value; + + dbus_message_iter_recurse(&tmp, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &value); + + DBG("key (%s) value(%s)", key, value); + + if (g_strcmp0(key, "path") == 0) + network_path = g_strdup(value); + + dbus_message_iter_next(&tmp); + } + + if (network_path != NULL) + __add_context(modem->device, network_path, &dict); + + return TRUE; +} + +static gboolean __removed_context(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + DBusMessageIter iter; + 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; + + if (dbus_message_iter_init(message, &iter) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_get_basic(&iter, &network_path); + g_hash_table_remove(network_hash, network_path); + + 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 = 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) +{ + int err; + + DBG("telephony plugin"); + + connection = connman_dbus_get_connection(); + if (connection == NULL) + return -EIO; + + /* telephony watch */ + watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE, + telephony_connect, telephony_disconnect, + NULL, NULL); + + modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MODEM_INTERFACE, + PROPERTY_CHANGED, + __changed_modem, + NULL, NULL); + + modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MASTER_INTERFACE, + MODEM_ADDED, + __added_modem, + NULL, NULL); + + modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MASTER_INTERFACE, + MODEM_REMOVED, + __removed_modem, + NULL, NULL); + + service_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_SERVICE_INTERFACE, + PROPERTY_CHANGED, + __changed_service, + NULL, NULL); + + service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MODEM_INTERFACE, + SERVICE_ADDED, + __added_service, + NULL, NULL); + + service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MODEM_INTERFACE, + SERVICE_REMOVED, + __removed_service, + NULL, NULL); + + context_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_CONTEXT_INTERFACE, + PROPERTY_CHANGED, + __changed_context, + NULL, NULL); + + context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_SERVICE_INTERFACE, + CONTEXT_ADDED, + __added_context, + NULL, NULL); + + context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_SERVICE_INTERFACE, + CONTEXT_REMOVED, + __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 + || default_subscription_watch == 0) { + err = -EIO; + goto remove; + } + + err = connman_network_driver_register(&network_driver); + if (err < 0) + goto remove; + + err = connman_device_driver_register(&modem_driver); + if (err < 0) { + connman_network_driver_unregister(&network_driver); + goto remove; + } + + err = connman_technology_driver_register(&tech_driver); + if (err < 0) { + connman_device_driver_unregister(&modem_driver); + connman_network_driver_unregister(&network_driver); + goto remove; + } + + return 0; + +remove: + g_dbus_remove_watch(connection, watch); + g_dbus_remove_watch(connection, modem_watch); + g_dbus_remove_watch(connection, modem_added_watch); + g_dbus_remove_watch(connection, modem_removed_watch); + g_dbus_remove_watch(connection, service_watch); + g_dbus_remove_watch(connection, service_added_watch); + g_dbus_remove_watch(connection, service_removed_watch); + 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; +} + +static void telephony_exit(void) +{ + g_dbus_remove_watch(connection, watch); + g_dbus_remove_watch(connection, modem_watch); + g_dbus_remove_watch(connection, modem_added_watch); + g_dbus_remove_watch(connection, modem_removed_watch); + g_dbus_remove_watch(connection, service_watch); + g_dbus_remove_watch(connection, service_added_watch); + g_dbus_remove_watch(connection, service_removed_watch); + 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); + + connman_device_driver_unregister(&modem_driver); + connman_network_driver_unregister(&network_driver); + + dbus_connection_unref(connection); +} + +CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION, + CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit) diff --git a/plugins/tist.c b/plugins/tist.c index ad5ef79e..ad5ef79e 100644..100755 --- a/plugins/tist.c +++ b/plugins/tist.c diff --git a/plugins/vpn.c b/plugins/vpn.c index c2a332ba..d3d75b81 100644..100755 --- a/plugins/vpn.c +++ b/plugins/vpn.c @@ -1726,7 +1726,7 @@ static gboolean property_changed(DBusConnection *conn, struct connection_data *data = NULL; DBusMessageIter iter, value; bool ip_set = false; - int err; + int err = 0; char *str; const char *key; const char *signature = DBUS_TYPE_STRING_AS_STRING diff --git a/plugins/wifi.c b/plugins/wifi.c index 34c16dfd..8bc6307b 100644..100755 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -152,10 +152,27 @@ struct wifi_data { bool p2p_connecting; bool p2p_device; int servicing; +#if defined TIZEN_EXT + int assoc_retry_count; + struct connman_network *scan_pending_network; + bool allow_full_scan; +#endif int disconnect_code; int assoc_code; }; +#if defined TIZEN_EXT +#include "connman.h" +#include "dbus.h" + +#define TIZEN_ASSOC_RETRY_COUNT 4 + +static gboolean wifi_first_scan = false; +static gboolean found_with_first_scan = false; +static gboolean is_wifi_notifier_registered = false; +#endif + + static GList *iface_list = NULL; static GList *pending_wifi_device = NULL; @@ -163,10 +180,128 @@ static GList *p2p_iface_list = NULL; bool wfd_service_registered = false; static void start_autoscan(struct connman_device *device); + static int tech_set_tethering(struct connman_technology *technology, const char *identifier, const char *passphrase, const char *bridge, bool enabled); +#if defined TIZEN_EXT +#define NETCONFIG_SERVICE "net.netconfig" +#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi" +#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi" + +struct enc_method_call_data { + DBusConnection *connection; + struct connman_network *network; +}; + +static struct enc_method_call_data encrypt_request_data; + +static void encryption_request_reply(DBusPendingCall *call, + void *user_data) +{ + DBusMessage *reply; + DBusError error; + DBusMessageIter args; + char *out_data; + struct connman_service *service; + gchar* encrypted_value = NULL; + struct connman_network *network = encrypt_request_data.network; + + DBG(""); + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + if (dbus_set_error_from_message(&error, reply)) { + DBG("send_encryption_request() %s %s", error.name, error.message); + dbus_error_free(&error); + goto done; + } + + if (dbus_message_iter_init(reply, &args) == FALSE) + goto done; + + dbus_message_iter_get_basic(&args, &out_data); + + encrypted_value = g_strdup((const gchar *)out_data); + service = connman_service_lookup_from_network(network); + + if (!service) { + DBG("encryption result: no service"); + goto done; + } + + if (connman_service_get_favorite(service)) { + __connman_service_set_passphrase(service, encrypted_value); + __connman_service_save(service); + } else + connman_network_set_string(network, "WiFi.Passphrase", + encrypted_value); + + DBG("encryption result: succeeded"); + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); + dbus_connection_unref(encrypt_request_data.connection); + g_free(encrypted_value); + + encrypt_request_data.connection = NULL; + encrypt_request_data.network = NULL; +} + +static int send_encryption_request(const char *passphrase, + struct connman_network *network) +{ + DBusConnection *connection = NULL; + DBusMessage *msg = NULL; + DBusPendingCall *call; + + if (!passphrase) { + DBG("Invalid parameter"); + return -EINVAL; + } + + connection = connman_dbus_get_connection(); + if (!connection) { + DBG("dbus connection does not exist"); + return -EINVAL; + } + + msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH, + NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase"); + if (!msg) { + dbus_connection_unref(connection); + return -EINVAL; + } + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase, + DBUS_TYPE_INVALID); + + if (!dbus_connection_send_with_reply(connection, msg, + &call, DBUS_TIMEOUT_USE_DEFAULT)) { + dbus_message_unref(msg); + dbus_connection_unref(connection); + return -EIO; + } + + if (!call) { + dbus_message_unref(msg); + dbus_connection_unref(connection); + return -EIO; + } + + encrypt_request_data.connection = connection; + encrypt_request_data.network = network; + + dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL); + dbus_message_unref(msg); + + return 0; +} +#endif + static int p2p_tech_probe(struct connman_technology *technology) { p2p_technology = technology; @@ -545,6 +680,11 @@ static void register_peer_service_cb(int result, struct wifi_data *wifi = g_supplicant_interface_get_data(iface); struct peer_service_registration *reg_data = user_data; +#if defined TIZEN_EXT + if (!wifi) + return; +#endif + DBG(""); if (result == 0) @@ -1069,6 +1209,15 @@ static int get_hidden_connections(GSupplicantScanParams *scan_data) continue; } +#if defined TIZEN_EXT + value = g_key_file_get_boolean(keyfile, + services[i], "AutoConnect", NULL); + if (!value) { + g_key_file_free(keyfile); + continue; + } +#endif + ssid = g_key_file_get_string(keyfile, services[i], "SSID", NULL); @@ -1208,8 +1357,11 @@ static int throw_wifi_scan(struct connman_device *device, if (wifi->tethering) return -EBUSY; - +#if defined TIZEN_EXT + if (connman_device_get_scanning(device) && !wifi->allow_full_scan) +#else if (connman_device_get_scanning(device)) +#endif return -EALREADY; connman_device_ref(device); @@ -1238,6 +1390,45 @@ static void hidden_free(struct hidden_params *hidden) g_free(hidden); } +#if defined TIZEN_EXT +static void service_state_changed(struct connman_service *service, + enum connman_service_state state); + +static int network_connect(struct connman_network *network); + +static struct connman_notifier notifier = { + .name = "wifi", + .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT, + .service_state_changed = service_state_changed, +}; + +static void service_state_changed(struct connman_service *service, + enum connman_service_state state) +{ + enum connman_service_type type; + + type = connman_service_get_type(service); + if (type != CONNMAN_SERVICE_TYPE_WIFI) + return; + + DBG("service %p state %d", service, state); + + switch (state) { + case CONNMAN_SERVICE_STATE_READY: + case CONNMAN_SERVICE_STATE_ONLINE: + case CONNMAN_SERVICE_STATE_FAILURE: + connman_notifier_unregister(¬ifier); + is_wifi_notifier_registered = FALSE; + + __connman_device_request_scan(type); + break; + + default: + break; + } +} +#endif + static void scan_callback(int result, GSupplicantInterface *interface, void *user_data) { @@ -1283,14 +1474,31 @@ static void scan_callback(int result, GSupplicantInterface *interface, return scan_callback(ret, interface, user_data); } - scanning = connman_device_get_scanning(device); +#if defined TIZEN_EXT + if (wifi && wifi->allow_full_scan) { + int ret; + DBG("Trigger Full Channel Scan"); + wifi->allow_full_scan = FALSE; - if (scanning) { + ret = g_supplicant_interface_scan(wifi->interface, NULL, + scan_callback, device); + if (ret == 0) + return; + + /* On error, let's recall scan_callback, which will cleanup */ + return scan_callback(ret, interface, user_data); + } +#endif + + scanning = connman_device_get_scanning(device); + if (scanning) connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false); - } if (result != -ENOLINK) +#if defined TIZEN_EXT + if (result != -EIO) +#endif start_autoscan(device); /* @@ -1302,6 +1510,23 @@ static void scan_callback(int result, GSupplicantInterface *interface, if (scanning) connman_device_unref(device); + +#if defined TIZEN_EXT + if (wifi && wifi->scan_pending_network && result != -EIO) { + network_connect(wifi->scan_pending_network); + wifi->scan_pending_network = NULL; + connman_network_set_connecting(wifi->network); + } + + if (is_wifi_notifier_registered != true && + wifi_first_scan == true && found_with_first_scan == true) { + wifi_first_scan = false; + found_with_first_scan = false; + + connman_notifier_register(¬ifier); + is_wifi_notifier_registered = true; + } +#endif } static void scan_callback_hidden(int result, @@ -1358,7 +1583,11 @@ static gboolean autoscan_timeout(gpointer data) } else interval = autoscan->interval * autoscan->base; +#if defined TIZEN_EXT + if (autoscan->interval >= autoscan->limit) +#else if (interval > autoscan->limit) +#endif interval = autoscan->limit; throw_wifi_scan(wifi->device, scan_callback_hidden); @@ -1552,6 +1781,15 @@ static int wifi_disable(struct connman_device *device) remove_networks(device, wifi); remove_peers(wifi); +#if defined TIZEN_EXT + wifi->scan_pending_network = NULL; + + if (is_wifi_notifier_registered == true) { + connman_notifier_unregister(¬ifier); + is_wifi_notifier_registered = false; + } +#endif + ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL); if (ret < 0) return ret; @@ -1779,6 +2017,137 @@ static int p2p_find(struct connman_device *device) return ret; } +#if defined TIZEN_EXT +static void specific_scan_callback(int result, GSupplicantInterface *interface, + void *user_data) +{ + struct connman_device *device = user_data; + struct wifi_data *wifi = connman_device_get_data(device); + bool scanning; + + DBG("result %d wifi %p", result, wifi); + + if (wifi && wifi->scan_params) { + g_supplicant_free_scan_params(wifi->scan_params); + wifi->scan_params = NULL; + } + + scanning = connman_device_get_scanning(device); + if (scanning) { + connman_device_set_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI, false); + connman_device_unref(device); + } +} + +static int wifi_specific_scan(enum connman_service_type type, + struct connman_device *device, int scan_type, + GSList *specific_scan_list, void *user_data) +{ + GSList *list = NULL; + char *ssid = NULL; + struct wifi_data *wifi = connman_device_get_data(device); + GSupplicantScanParams *scan_params = NULL; + struct scan_ssid *scan_ssid = NULL; + bool scanning; + int ret; + int freq; + int count = 0; + + if (!wifi) + return -ENODEV; + + if (wifi->p2p_device) + return 0; + + if (type == CONNMAN_SERVICE_TYPE_P2P) + return p2p_find(device); + + if (wifi->tethering) + return 0; + + scanning = connman_device_get_scanning(device); + if (scanning) + return -EALREADY; + + DBG("scan_type: %d", scan_type); + if (scan_type == 1) { /* ssid based scan */ + scan_params = g_try_malloc0(sizeof(GSupplicantScanParams)); + if (!scan_params) { + DBG("Failed to allocate memory."); + return -ENOMEM; + } + + for (list = specific_scan_list; list; list = list->next) { + ssid = (char *)list->data; + int ssid_len = strlen(ssid); + + scan_ssid = g_try_new0(struct scan_ssid, 1); + if (!scan_ssid) { + DBG("Failed to allocate memory."); + g_supplicant_free_scan_params(scan_params); + return -ENOMEM; + } + + memcpy(scan_ssid->ssid, ssid, (ssid_len + 1)); + DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); + scan_ssid->ssid_len = ssid_len; + scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid); + count++; + } + scan_params->num_ssids = count; + + } else if (scan_type == 2) { /* frequency based scan */ + + scan_params = g_try_malloc0(sizeof(GSupplicantScanParams)); + if (!scan_params) { + DBG("Failed to allocate memory."); + return -ENOMEM; + } + + guint num_freqs = g_slist_length(specific_scan_list); + DBG("num_freqs: %d", num_freqs); + + scan_params->freqs = g_try_new0(uint16_t, num_freqs); + if (!scan_params->freqs) { + DBG("Failed to allocate memory."); + g_free(scan_params); + return -ENOMEM; + } + + count = 0; + for (list = specific_scan_list; list; list = list->next) { + freq = (int)list->data; + + scan_params->freqs[count] = freq; + DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]); + count++; + } + scan_params->num_freqs = count; + + } else { + DBG("Invalid scan"); + return -EINVAL; + } + + reset_autoscan(device); + connman_device_ref(device); + + ret = g_supplicant_interface_scan(wifi->interface, scan_params, + specific_scan_callback, device); + + if (ret == 0) { + connman_device_set_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI, true); + } else { + g_supplicant_free_scan_params(scan_params); + connman_device_unref(device); + } + + return ret; +} +#endif + /* * Note that the hidden scan is only used when connecting to this specific * hidden AP first time. It is not used when system autoconnects to hidden AP. @@ -1893,9 +2262,18 @@ static int wifi_scan(enum connman_service_type type, ret = g_supplicant_interface_scan(wifi->interface, scan_params, scan_callback, device); + if (ret == 0) { connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, true); +#if defined TIZEN_EXT + /*To allow the Full Scan after ssid based scan, set the flag here + It is required because Tizen does not use the ConnMan specific + backgroung Scan feature.Tizen has added the BG Scan feature in + net-config. To sync with up ConnMan, we need to issue the Full Scan + after SSID specific scan.*/ + wifi->allow_full_scan = TRUE; +#endif } else { g_supplicant_free_scan_params(scan_params); connman_device_unref(device); @@ -1949,6 +2327,9 @@ static struct connman_device_driver wifi_ng_driver = { .disable = wifi_disable, .scan = wifi_scan, .set_regdom = wifi_set_regdom, +#if defined TIZEN_EXT + .specific_scan = wifi_specific_scan, +#endif }; static void system_ready(void) @@ -1988,15 +2369,42 @@ static void network_remove(struct connman_network *network) return; wifi->network = NULL; + +#if defined TIZEN_EXT + wifi->disconnecting = false; + + if (wifi->pending_network == network) + wifi->pending_network = NULL; + + if (wifi->scan_pending_network == network) + wifi->scan_pending_network = NULL; +#endif } static void connect_callback(int result, GSupplicantInterface *interface, void *user_data) { +#if defined TIZEN_EXT + GList *list; + struct wifi_data *wifi; +#endif struct connman_network *network = user_data; DBG("network %p result %d", network, result); +#if defined TIZEN_EXT + for (list = iface_list; list; list = list->next) { + wifi = list->data; + + if (wifi && wifi->network == network) + goto found; + } + + /* wifi_data may be invalid because wifi is already disabled */ + return; + +found: +#endif if (result == -ENOKEY) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY); @@ -2022,6 +2430,12 @@ static GSupplicantSecurity network_security(const char *security) return G_SUPPLICANT_SECURITY_PSK; else if (g_str_equal(security, "ieee8021x")) return G_SUPPLICANT_SECURITY_IEEE8021X; +#if defined TIZEN_EXT + else if (g_str_equal(security, "ft_psk") == TRUE) + return G_SUPPLICANT_SECURITY_FT_PSK; + else if (g_str_equal(security, "ft_ieee8021x") == TRUE) + return G_SUPPLICANT_SECURITY_FT_IEEE8021X; +#endif return G_SUPPLICANT_SECURITY_UNKNOWN; } @@ -2039,7 +2453,6 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) ssid->security = network_security(security); ssid->passphrase = connman_network_get_string(network, "WiFi.Passphrase"); - ssid->eap = connman_network_get_string(network, "WiFi.EAP"); /* @@ -2083,6 +2496,13 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS"); ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS"); +#if defined TIZEN_EXT + ssid->bssid = connman_network_get_bssid(network); +#endif +#if defined TIZEN_EXT + ssid->freq = connman_network_get_frequency(network); +#endif + if (connman_setting_get_bool("BackgroundScanning")) ssid->bgscan = BGSCAN_DEFAULT; } @@ -2117,6 +2537,9 @@ static int network_connect(struct connman_network *network) } else { wifi->network = connman_network_ref(network); wifi->retries = 0; +#if defined TIZEN_EXT + wifi->scan_pending_network = NULL; +#endif return g_supplicant_interface_connect(interface, ssid, connect_callback, network); @@ -2128,7 +2551,30 @@ static int network_connect(struct connman_network *network) static void disconnect_callback(int result, GSupplicantInterface *interface, void *user_data) { +#if defined TIZEN_EXT + GList *list; + struct wifi_data *wifi; + struct connman_network *network = user_data; + + DBG("network %p result %d", network, result); + + for (list = iface_list; list; list = list->next) { + wifi = list->data; + + if (wifi->network == NULL && wifi->disconnecting == true) + wifi->disconnecting = false; + + if (wifi->network == network) + goto found; + } + + /* wifi_data may be invalid because wifi is already disabled */ + return; + +found: +#else struct wifi_data *wifi = user_data; +#endif DBG("result %d supplicant interface %p wifi %p", result, interface, wifi); @@ -2159,6 +2605,9 @@ static int network_disconnect(struct connman_network *network) struct connman_device *device = connman_network_get_device(network); struct wifi_data *wifi; int err; +#if defined TIZEN_EXT + struct connman_service *service; +#endif DBG("network %p", network); @@ -2166,6 +2615,29 @@ static int network_disconnect(struct connman_network *network) if (!wifi || !wifi->interface) return -ENODEV; +#if defined TIZEN_EXT + if (connman_network_get_associating(network) == true) { + connman_network_clear_associating(network); + connman_network_set_bool(network, "WiFi.UseWPS", false); + } else { + service = connman_service_lookup_from_network(network); + + if (service != NULL && + (__connman_service_is_connected_state(service, + CONNMAN_IPCONFIG_TYPE_IPV4) == false && + __connman_service_is_connected_state(service, + CONNMAN_IPCONFIG_TYPE_IPV6) == false) && + (connman_service_get_favorite(service) == false)) + __connman_service_set_passphrase(service, NULL); + } + + if (wifi->pending_network == network) + wifi->pending_network = NULL; + + if (wifi->scan_pending_network == network) + wifi->scan_pending_network = NULL; + +#endif connman_network_set_associating(network, false); if (wifi->disconnecting) @@ -2173,8 +2645,14 @@ static int network_disconnect(struct connman_network *network) wifi->disconnecting = true; +#if defined TIZEN_EXT + err = g_supplicant_interface_disconnect(wifi->interface, + disconnect_callback, network); +#else err = g_supplicant_interface_disconnect(wifi->interface, disconnect_callback, wifi); +#endif + if (err < 0) wifi->disconnecting = false; @@ -2297,16 +2775,49 @@ static bool handle_wps_completion(GSupplicantInterface *interface, if (!wps_ssid || wps_ssid_len != ssid_len || memcmp(ssid, wps_ssid, ssid_len) != 0) { connman_network_set_associating(network, false); +#if defined TIZEN_EXT + g_supplicant_interface_disconnect(wifi->interface, + disconnect_callback, wifi->network); + + connman_network_set_bool(network, "WiFi.UseWPS", false); + connman_network_set_string(network, "WiFi.PinWPS", NULL); +#else g_supplicant_interface_disconnect(wifi->interface, disconnect_callback, wifi); +#endif return false; } wps_key = g_supplicant_interface_get_wps_key(interface); +#if defined TIZEN_EXT + /* Check the passphrase and encrypt it + */ + int ret; + gchar *passphrase = g_strdup(wps_key); + + connman_network_set_string(network, "WiFi.PinWPS", NULL); + + if (check_passphrase_ext(network, passphrase) < 0) { + DBG("[WPS] Invalid passphrase"); + g_free(passphrase); + return true; + } + + ret = send_encryption_request(passphrase, passphrase); + + g_free(passphrase); + + if (!ret) + DBG("[WPS] Encryption request succeeded"); + else + DBG("[WPS] Encryption request failed %d", ret); + +#else connman_network_set_string(network, "WiFi.Passphrase", wps_key); connman_network_set_string(network, "WiFi.PinWPS", NULL); +#endif } return true; @@ -2329,6 +2840,26 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface, struct connman_network *network, struct wifi_data *wifi) { +#if defined TIZEN_EXT + const char *security; + struct connman_service *service; + + if (wifi->connected) + return false; + + security = connman_network_get_string(network, "WiFi.Security"); + + if (security && g_str_equal(security, "ieee8021x") == true && + wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) { + wifi->retries = 0; + connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY); + + return false; + } + + if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) + return false; +#else struct connman_service *service; if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) @@ -2336,6 +2867,7 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface, if (wifi->connected) return false; +#endif service = connman_service_lookup_from_network(network); if (!service) @@ -2354,6 +2886,47 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface, return false; } +#if defined TIZEN_EXT +static bool handle_wifi_assoc_retry(struct connman_network *network, + struct wifi_data *wifi) +{ + const char *security; + + if (!wifi->network || wifi->connected || wifi->disconnecting || + connman_network_get_connecting(network) != true) { + wifi->assoc_retry_count = 0; + return false; + } + + if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING && + wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) { + wifi->assoc_retry_count = 0; + return false; + } + + security = connman_network_get_string(network, "WiFi.Security"); + if (security && g_str_equal(security, "ieee8021x") == true && + wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) { + wifi->assoc_retry_count = 0; + return false; + } + + if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) { + wifi->assoc_retry_count = 0; + + /* Honestly it's not an invalid-key error, + * however QA team recommends that the invalid-key error + * might be better to display for user experience. + */ + connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); + + return false; + } + + return true; +} +#endif + static void interface_state(GSupplicantInterface *interface) { struct connman_network *network; @@ -2401,7 +2974,11 @@ static void interface_state(GSupplicantInterface *interface) case G_SUPPLICANT_STATE_AUTHENTICATING: case G_SUPPLICANT_STATE_ASSOCIATING: +#if defined TIZEN_EXT + reset_autoscan(device); +#else stop_autoscan(device); +#endif if (!wifi->connected) connman_network_set_associating(network, true); @@ -2409,8 +2986,25 @@ static void interface_state(GSupplicantInterface *interface) break; case G_SUPPLICANT_STATE_COMPLETED: +#if defined TIZEN_EXT + /* though it should be already reset: */ + reset_autoscan(device); + + wifi->assoc_retry_count = 0; + + wifi->scan_pending_network = NULL; + + /* should be cleared scanning flag */ + bool scanning = connman_device_get_scanning(device); + if (scanning){ + connman_device_set_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI, false); + connman_device_unref(device); + } +#else /* though it should be already stopped: */ stop_autoscan(device); +#endif if (!handle_wps_completion(interface, network, device, wifi)) break; @@ -2461,6 +3055,46 @@ static void interface_state(GSupplicantInterface *interface) default: break; } + +#if defined TIZEN_EXT + int err; + + err = g_supplicant_interface_remove_network(wifi->interface); + if (err < 0) + DBG("Failed to remove network(%d)", err); + + + /* Some of Wi-Fi networks are not comply Wi-Fi specification. + * Retry association until its retry count is expired */ + if (handle_wifi_assoc_retry(network, wifi) == true) { + throw_wifi_scan(wifi->device, scan_callback); + wifi->scan_pending_network = wifi->network; + break; + } + + if(wifi->disconnect_code > 0){ + DBG("Set disconnect reason code(%d)", wifi->disconnect_code); + connman_network_set_disconnect_reason(network, wifi->disconnect_code); + } + + /* To avoid unnecessary repeated association in wpa_supplicant, + * "RemoveNetwork" should be made when Wi-Fi is disconnected */ + if (wps != true && wifi->network && wifi->disconnecting == false) { + wifi->disconnecting = true; + err = g_supplicant_interface_disconnect(wifi->interface, + disconnect_callback, wifi->network); + if (err < 0) + wifi->disconnecting = false; + + connman_network_set_connected(network, false); + connman_network_set_associating(network, false); + + start_autoscan(device); + + break; + } +#endif + connman_network_set_connected(network, false); connman_network_set_associating(network, false); wifi->disconnecting = false; @@ -2470,6 +3104,10 @@ static void interface_state(GSupplicantInterface *interface) break; case G_SUPPLICANT_STATE_INACTIVE: +#if defined TIZEN_EXT + if (handle_wps_completion(interface, network, device, wifi) == false) + break; +#endif connman_network_set_associating(network, false); start_autoscan(device); @@ -2606,7 +3244,38 @@ static void scan_started(GSupplicantInterface *interface) static void scan_finished(GSupplicantInterface *interface) { +#if defined TIZEN_EXT + struct wifi_data *wifi; + bool is_associating = false; + static bool is_scanning = true; +#endif + DBG(""); + +#if defined TIZEN_EXT + wifi = g_supplicant_interface_get_data(interface); + if (wifi && wifi->scan_pending_network) { + network_connect(wifi->scan_pending_network); + wifi->scan_pending_network = NULL; + } + + //service state - associating + if(!wifi || !wifi->network) + return; + + is_associating = connman_network_get_associating(wifi->network); + if(is_associating && is_scanning){ + is_scanning = false; + DBG("send scan for connecting"); + throw_wifi_scan(wifi->device, scan_callback); + + return; + } + is_scanning = true; + + //go scan + +#endif } static void ap_create_fail(GSupplicantInterface *interface) @@ -2644,9 +3313,11 @@ static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network) unsigned char strength; strength = 120 + g_supplicant_network_get_signal(supplicant_network); + +#if !defined TIZEN_EXT if (strength > 100) strength = 100; - +#endif return strength; } @@ -2663,6 +3334,11 @@ static void network_added(GSupplicantNetwork *supplicant_network) bool wps_ready; bool wps_advertizing; +#if defined TIZEN_EXT + const char *wifi_vsie; + unsigned int wifi_vsie_len; +#endif + mode = g_supplicant_network_get_mode(supplicant_network); identifier = g_supplicant_network_get_identifier(supplicant_network); @@ -2687,6 +3363,9 @@ static void network_added(GSupplicantNetwork *supplicant_network) ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len); +#if defined TIZEN_EXT + wifi_vsie = g_supplicant_network_get_wifi_vsie(supplicant_network, &wifi_vsie_len); +#endif network = connman_device_get_network(wifi->device, identifier); if (!network) { @@ -2710,6 +3389,11 @@ static void network_added(GSupplicantNetwork *supplicant_network) connman_network_set_blob(network, "WiFi.SSID", ssid, ssid_len); +#if defined TIZEN_EXT + if(wifi_vsie_len > 0 && wifi_vsie) + connman_network_set_blob(network, "WiFi.Vsie", + wifi_vsie, wifi_vsie_len); +#endif connman_network_set_string(network, "WiFi.Security", security); connman_network_set_strength(network, calculate_strength(supplicant_network)); @@ -2719,21 +3403,53 @@ static void network_added(GSupplicantNetwork *supplicant_network) /* Is AP advertizing for WPS association? * If so, we decide to use WPS by default */ if (wps_ready && wps_pbc && - wps_advertizing) + wps_advertizing) { +#if !defined TIZEN_EXT connman_network_set_bool(network, "WiFi.UseWPS", true); +#else + DBG("wps is activating by ap but ignore it."); +#endif + } } connman_network_set_frequency(network, g_supplicant_network_get_frequency(supplicant_network)); - +#if defined TIZEN_EXT + connman_network_set_bssid(network, + g_supplicant_network_get_bssid(supplicant_network)); + connman_network_set_maxrate(network, + g_supplicant_network_get_maxrate(supplicant_network)); + connman_network_set_enc_mode(network, + g_supplicant_network_get_enc_mode(supplicant_network)); + connman_network_set_rsn_mode(network, + g_supplicant_network_get_rsn_mode(supplicant_network)); + connman_network_set_keymgmt(network, + g_supplicant_network_get_keymgmt(supplicant_network)); + connman_network_set_bool(network, "WiFi.HS20AP", + g_supplicant_network_is_hs20AP(supplicant_network)); +#endif connman_network_set_available(network, true); connman_network_set_string(network, "WiFi.Mode", mode); +#if defined TIZEN_EXT + if (group) +#else if (ssid) +#endif connman_network_set_group(network, group); +#if defined TIZEN_EXT + if (wifi_first_scan == true) + found_with_first_scan = true; +#endif + if (wifi->hidden && ssid) { +#if defined TIZEN_EXT + if (network_security(wifi->hidden->security) == + network_security(security) && +#else if (!g_strcmp0(wifi->hidden->security, security) && +#endif wifi->hidden->ssid_len == ssid_len && !memcmp(wifi->hidden->ssid, ssid, ssid_len)) { connman_network_connect_hidden(network, @@ -2768,6 +3484,18 @@ static void network_removed(GSupplicantNetwork *network) if (!connman_network) return; +#if defined TIZEN_EXT + if (connman_network == wifi->scan_pending_network) + wifi->scan_pending_network = NULL; + + if (connman_network == wifi->pending_network) + wifi->pending_network = NULL; + + if(connman_network_get_connecting(connman_network) == true){ + connman_network_set_connected(connman_network, false); + } +#endif + wifi->networks = g_slist_remove(wifi->networks, connman_network); connman_device_remove_network(wifi->device, connman_network); @@ -2781,6 +3509,13 @@ static void network_changed(GSupplicantNetwork *network, const char *property) const char *name, *identifier; struct connman_network *connman_network; +#if defined TIZEN_EXT + const unsigned char *bssid; + unsigned int maxrate; + uint16_t frequency; + bool wps; +#endif + interface = g_supplicant_network_get_interface(network); wifi = g_supplicant_interface_get_data(interface); identifier = g_supplicant_network_get_identifier(network); @@ -2800,6 +3535,18 @@ static void network_changed(GSupplicantNetwork *network, const char *property) calculate_strength(network)); connman_network_update(connman_network); } + +#if defined TIZEN_EXT + bssid = g_supplicant_network_get_bssid(network); + maxrate = g_supplicant_network_get_maxrate(network); + frequency = g_supplicant_network_get_frequency(network); + wps = g_supplicant_network_get_wps(network); + + connman_network_set_bssid(connman_network, bssid); + connman_network_set_maxrate(connman_network, maxrate); + connman_network_set_frequency(connman_network, frequency); + connman_network_set_bool(connman_network, "WiFi.WPS", wps); +#endif } static void network_associated(GSupplicantNetwork *network) @@ -2870,6 +3617,17 @@ static void apply_peer_services(GSupplicantPeer *peer, } } +static void add_station(const char *mac) +{ + connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI, + mac); +} + +static void remove_station(const char *mac) +{ + connman_technology_tethering_remove_station(mac); +} + static void peer_found(GSupplicantPeer *peer) { GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer); @@ -2877,7 +3635,10 @@ static void peer_found(GSupplicantPeer *peer) struct connman_peer *connman_peer; const char *identifier, *name; int ret; - +#if defined TIZEN_EXT + if (!wifi) + return; +#endif identifier = g_supplicant_peer_get_identifier(peer); name = g_supplicant_peer_get_name(peer); @@ -2934,6 +3695,11 @@ static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state) struct connman_peer *connman_peer; const char *identifier; +#if defined TIZEN_EXT + if (!wifi) + return; +#endif + identifier = g_supplicant_peer_get_identifier(peer); DBG("ident: %s", identifier); @@ -3023,6 +3789,11 @@ static void peer_request(GSupplicantPeer *peer) struct connman_peer *connman_peer; const char *identifier; +#if defined TIZEN_EXT + if (!wifi) + return; +#endif + identifier = g_supplicant_peer_get_identifier(peer); DBG("ident: %s", identifier); @@ -3034,6 +3805,100 @@ static void peer_request(GSupplicantPeer *peer) connman_peer_request_connection(connman_peer); } +#if defined TIZEN_EXT +static void system_power_off(void) +{ + GList *list; + struct wifi_data *wifi; + struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv4; + + if (connman_setting_get_bool("WiFiDHCPRelease") == true) { + for (list = iface_list; list; list = list->next) { + wifi = list->data; + + if (wifi->network != NULL) { + service = connman_service_lookup_from_network(wifi->network); + ipconfig_ipv4 = __connman_service_get_ip4config(service); + __connman_dhcp_stop(ipconfig_ipv4); + } + } + } +} + +static void network_merged(GSupplicantNetwork *network) +{ + GSupplicantInterface *interface; + GSupplicantState state; + struct wifi_data *wifi; + const char *identifier; + struct connman_network *connman_network; + bool ishs20AP = 0; + char *temp = NULL; + + interface = g_supplicant_network_get_interface(network); + if (!interface) + return; + + state = g_supplicant_interface_get_state(interface); + if (state < G_SUPPLICANT_STATE_AUTHENTICATING) + return; + + wifi = g_supplicant_interface_get_data(interface); + if (!wifi) + return; + + identifier = g_supplicant_network_get_identifier(network); + + connman_network = connman_device_get_network(wifi->device, identifier); + if (!connman_network) + return; + + DBG("merged identifier %s", identifier); + + if (wifi->connected == FALSE) { + switch (state) { + case G_SUPPLICANT_STATE_AUTHENTICATING: + case G_SUPPLICANT_STATE_ASSOCIATING: + case G_SUPPLICANT_STATE_ASSOCIATED: + case G_SUPPLICANT_STATE_4WAY_HANDSHAKE: + case G_SUPPLICANT_STATE_GROUP_HANDSHAKE: + connman_network_set_associating(connman_network, TRUE); + break; + case G_SUPPLICANT_STATE_COMPLETED: + connman_network_set_connected(connman_network, TRUE); + break; + default: + DBG("Not handled the state : %d", state); + break; + } + } + + ishs20AP = g_supplicant_network_is_hs20AP(network); + + if (ishs20AP && + g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) { + temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1); + connman_network_set_string(connman_network, "WiFi.EAP", + temp); + connman_network_set_string(connman_network, "WiFi.Identity", + g_supplicant_network_get_identity(network)); + connman_network_set_string(connman_network, "WiFi.Phase2", + g_supplicant_network_get_phase2(network)); + + g_free(temp); + } + + wifi->network = connman_network; +} + +static void assoc_failed(void *user_data) +{ + struct connman_network *network = user_data; + connman_network_set_associating(network, false); +} +#endif + static void debug(const char *str) { if (getenv("CONNMAN_SUPPLICANT_DEBUG")) @@ -3073,10 +3938,17 @@ static const GSupplicantCallbacks callbacks = { .network_removed = network_removed, .network_changed = network_changed, .network_associated = network_associated, + .add_station = add_station, + .remove_station = remove_station, .peer_found = peer_found, .peer_lost = peer_lost, .peer_changed = peer_changed, .peer_request = peer_request, +#if defined TIZEN_EXT + .system_power_off = system_power_off, + .network_merged = network_merged, + .assoc_failed = assoc_failed, +#endif .debug = debug, .disconnect_reasoncode = disconnect_reasoncode, .assoc_status_code = assoc_status_code, @@ -3095,7 +3967,8 @@ static void tech_remove(struct connman_technology *technology) wifi_technology = NULL; } -static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase) +static GSupplicantSSID *ssid_ap_init(const char *ssid, + const char *passphrase) { GSupplicantSSID *ap; @@ -3193,7 +4066,7 @@ static void sta_remove_callback(int result, DBG("ifname %s result %d ", info->ifname, result); - if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) { + if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) { info->wifi->tethering = false; connman_technology_tethering_notify(info->technology, false); @@ -3239,10 +4112,11 @@ static int enable_wifi_tethering(struct connman_technology *technology, if (!interface) continue; - ifname = g_supplicant_interface_get_ifname(wifi->interface); - if (!ifname) + if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) continue; + ifname = g_supplicant_interface_get_ifname(wifi->interface); + if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) { DBG("%s does not support AP mode (detected)", ifname); continue; @@ -3276,6 +4150,8 @@ static int enable_wifi_tethering(struct connman_technology *technology, goto failed; info->ifname = g_strdup(ifname); + if (!info->ifname) + goto failed; wifi->tethering_param->technology = technology; wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase); |