X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftechnology.c;h=c2c82b98bc98f7e25d0f231f6173d3984e614ee2;hb=9c394d387dc4dc546972dcae50a227dc6a9989ae;hp=f210859d0d4545aca3865ab4a252ca29136c01fe;hpb=bbb09e3b7378daf4f2d0d63bdc2e943c0f84c808;p=platform%2Fupstream%2Fconnman.git diff --git a/src/technology.c b/src/technology.c index f210859..c2c82b9 100644 --- a/src/technology.c +++ b/src/technology.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2013 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 @@ -25,6 +25,11 @@ #include #include +#if defined TIZEN_EXT +#include +#include +#include +#endif #include @@ -41,13 +46,26 @@ static GSList *technology_list = NULL; static GSList *techless_device_list = NULL; static GHashTable *rfkill_list; -static connman_bool_t global_offlinemode; +static bool global_offlinemode; + +#if defined TIZEN_EXT +struct connman_scan_pending { + char *ifname; + connman_scan_type_e scan_type; + DBusMessage *msg; +}; + +struct connman_bssid_pending { + char *ifname; + unsigned char bssid[6]; +}; +#endif struct connman_rfkill { unsigned int index; enum connman_service_type type; - connman_bool_t softblock; - connman_bool_t hardblock; + bool softblock; + bool hardblock; }; struct connman_technology { @@ -55,19 +73,19 @@ struct connman_technology { enum connman_service_type type; char *path; GSList *device_list; - connman_bool_t enabled; + bool enabled; char *regdom; - connman_bool_t connected; + bool connected; - connman_bool_t tethering; - connman_bool_t tethering_persistent; /* Tells the save status, needed + bool tethering; + bool tethering_persistent; /* Tells the save status, needed * as offline mode might set * tethering OFF. */ char *tethering_ident; char *tethering_passphrase; - connman_bool_t enable_persistent; /* Save the tech state */ + bool enable_persistent; /* Save the tech state */ GSList *driver_list; @@ -76,14 +94,26 @@ struct connman_technology { GSList *scan_pending; - connman_bool_t rfkill_driven; - connman_bool_t softblocked; - connman_bool_t hardblocked; - connman_bool_t dbus_registered; + bool rfkill_driven; + bool softblocked; + bool hardblocked; + bool dbus_registered; +#if defined TIZEN_EXT + char **enabled_devices; + unsigned int mac_policy; + unsigned int preassoc_mac_policy; + unsigned int random_mac_lifetime; +#endif +#if defined TIZEN_EXT_WIFI_MESH + DBusMessage *mesh_dbus_msg; +#endif }; static GSList *driver_list = NULL; +static int technology_enabled(struct connman_technology *technology); +static int technology_disabled(struct connman_technology *technology); + static gint compare_priority(gconstpointer a, gconstpointer b) { const struct connman_technology_driver *driver1 = a; @@ -97,13 +127,13 @@ static void rfkill_check(gpointer key, gpointer value, gpointer user_data) struct connman_rfkill *rfkill = value; enum connman_service_type type = GPOINTER_TO_INT(user_data); - /* Calling _technology_rfkill_add will update the tech. */ + /* Calling _technology_add_rfkill will update the tech. */ if (rfkill->type == type) __connman_technology_add_rfkill(rfkill->index, type, rfkill->softblock, rfkill->hardblock); } -connman_bool_t +bool connman_technology_is_tethering_allowed(enum connman_service_type type) { static char *allowed_default[] = { "wifi", "bluetooth", "gadget", @@ -112,100 +142,19 @@ connman_technology_is_tethering_allowed(enum connman_service_type type) char **allowed; int i; - if (type_str == NULL) - return FALSE; + if (!type_str) + return false; allowed = connman_setting_get_string_list("TetheringTechnologies"); - if (allowed == NULL) + if (!allowed) allowed = allowed_default; - for (i = 0; allowed[i] != NULL; i++) { + for (i = 0; allowed[i]; i++) { if (g_strcmp0(allowed[i], type_str) == 0) - return TRUE; - } - - return FALSE; -} - -/** - * connman_technology_driver_register: - * @driver: Technology driver definition - * - * Register a new technology driver - * - * Returns: %0 on success - */ -int connman_technology_driver_register(struct connman_technology_driver *driver) -{ - GSList *list; - struct connman_device *device; - enum connman_service_type type; - - DBG("Registering %s driver", driver->name); - - driver_list = g_slist_insert_sorted(driver_list, driver, - compare_priority); - - /* - * Check for technology less devices if this driver - * can service any of them. - */ - for (list = techless_device_list; list != NULL; list = list->next) { - device = list->data; - - type = __connman_device_get_service_type(device); - if (type != driver->type) - continue; - - techless_device_list = g_slist_remove(techless_device_list, - device); - - __connman_technology_add_device(device); - } - - /* Check for orphaned rfkill switches. */ - g_hash_table_foreach(rfkill_list, rfkill_check, - GINT_TO_POINTER(driver->type)); - - return 0; -} - -/** - * connman_technology_driver_unregister: - * @driver: Technology driver definition - * - * Remove a previously registered technology driver - */ -void connman_technology_driver_unregister(struct connman_technology_driver *driver) -{ - GSList *list, *tech_drivers; - struct connman_technology *technology; - struct connman_technology_driver *current; - - DBG("Unregistering driver %p name %s", driver, driver->name); - - for (list = technology_list; list; list = list->next) { - technology = list->data; - - for (tech_drivers = technology->driver_list; - tech_drivers != NULL; - tech_drivers = g_slist_next(tech_drivers)) { - - current = tech_drivers->data; - if (driver != current) - continue; - - if (driver->remove != NULL) - driver->remove(technology); - - technology->driver_list = - g_slist_remove(technology->driver_list, driver); - - break; - } + return true; } - driver_list = g_slist_remove(driver_list, driver); + return false; } static const char *get_name(enum connman_service_type type) @@ -215,8 +164,9 @@ static const char *get_name(enum connman_service_type type) case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: - case CONNMAN_SERVICE_TYPE_GADGET: break; + case CONNMAN_SERVICE_TYPE_GADGET: + return "Gadget"; case CONNMAN_SERVICE_TYPE_ETHERNET: return "Wired"; case CONNMAN_SERVICE_TYPE_WIFI: @@ -225,6 +175,12 @@ static const char *get_name(enum connman_service_type type) return "Bluetooth"; case CONNMAN_SERVICE_TYPE_CELLULAR: return "Cellular"; + case CONNMAN_SERVICE_TYPE_P2P: + return "P2P"; +#if defined TIZEN_EXT_WIFI_MESH + case CONNMAN_SERVICE_TYPE_MESH: + return "Mesh"; +#endif } return NULL; @@ -234,15 +190,19 @@ static void technology_save(struct connman_technology *technology) { GKeyFile *keyfile; gchar *identifier; + const char *name = get_name(technology->type); - DBG("technology %p", technology); + DBG("technology %p type %d name %s", technology, technology->type, + name); + if (!name) + return; keyfile = __connman_storage_load_global(); - if (keyfile == NULL) + if (!keyfile) keyfile = g_key_file_new(); - identifier = g_strdup_printf("%s", get_name(technology->type)); - if (identifier == NULL) + identifier = g_strdup_printf("%s", name); + if (!identifier) goto done; g_key_file_set_boolean(keyfile, identifier, "Enable", @@ -251,29 +211,40 @@ static void technology_save(struct connman_technology *technology) g_key_file_set_boolean(keyfile, identifier, "Tethering", technology->tethering_persistent); - if (technology->tethering_ident != NULL) + if (technology->tethering_ident) g_key_file_set_string(keyfile, identifier, "Tethering.Identifier", technology->tethering_ident); - if (technology->tethering_passphrase != NULL) + if (technology->tethering_passphrase) g_key_file_set_string(keyfile, identifier, "Tethering.Passphrase", technology->tethering_passphrase); +#ifdef TIZEN_EXT + if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) { + g_key_file_set_uint64(keyfile, identifier, "MacPolicy", + technology->mac_policy); + + g_key_file_set_uint64(keyfile, identifier, "PreassocMacPolicy", + technology->preassoc_mac_policy); + + g_key_file_set_uint64(keyfile, identifier, "RandomMacLifetime", + technology->random_mac_lifetime); + } +#endif /* TIZEN_EXT */ + done: g_free(identifier); __connman_storage_save_global(keyfile); g_key_file_free(keyfile); - - return; } static void tethering_changed(struct connman_technology *technology) { - connman_bool_t tethering = technology->tethering; + dbus_bool_t tethering = technology->tethering; connman_dbus_property_changed_basic(technology->path, CONNMAN_TECHNOLOGY_INTERFACE, "Tethering", @@ -282,35 +253,31 @@ static void tethering_changed(struct connman_technology *technology) technology_save(technology); } -void connman_technology_tethering_notify(struct connman_technology *technology, - connman_bool_t enabled) +int connman_technology_tethering_notify(struct connman_technology *technology, + bool enabled) { - GSList *list; + int err; DBG("technology %p enabled %u", technology, enabled); if (technology->tethering == enabled) - return; + return -EALREADY; - technology->tethering = enabled; + if (enabled) { + err = __connman_tethering_set_enabled(); + if (err < 0) + return err; + } else + __connman_tethering_set_disabled(); + technology->tethering = enabled; tethering_changed(technology); - if (enabled == TRUE) - __connman_tethering_set_enabled(); - else { - for (list = technology_list; list; list = list->next) { - struct connman_technology *other_tech = list->data; - if (other_tech->tethering == TRUE) - break; - } - if (list == NULL) - __connman_tethering_set_disabled(); - } + return 0; } static int set_tethering(struct connman_technology *technology, - connman_bool_t enabled) + bool enabled) { int result = -EOPNOTSUPP; int err; @@ -321,22 +288,22 @@ static int set_tethering(struct connman_technology *technology, passphrase = technology->tethering_passphrase; __sync_synchronize(); - if (technology->enabled == FALSE) + if (!technology->enabled) return -EACCES; bridge = __connman_tethering_get_bridge(); - if (bridge == NULL) + if (!bridge) return -EOPNOTSUPP; if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && - (ident == NULL || passphrase == NULL)) + (!ident || !passphrase)) return -EINVAL; - for (tech_drivers = technology->driver_list; tech_drivers != NULL; + for (tech_drivers = technology->driver_list; tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { struct connman_technology_driver *driver = tech_drivers->data; - if (driver == NULL || driver->set_tethering == NULL) + if (!driver || !driver->set_tethering) continue; err = driver->set_tethering(technology, ident, passphrase, @@ -345,10 +312,8 @@ static int set_tethering(struct connman_technology *technology, if (result == -EINPROGRESS) continue; - if (err == -EINPROGRESS || err == 0) { + if (err == -EINPROGRESS || err == 0) result = err; - continue; - } } return result; @@ -359,7 +324,7 @@ void connman_technology_regdom_notify(struct connman_technology *technology, { DBG(""); - if (alpha2 == NULL) + if (!alpha2) connman_error("Failed to set regulatory domain"); else DBG("Regulatory domain set to %s", alpha2); @@ -393,13 +358,13 @@ int connman_technology_set_regdom(const char *alpha2) if (set_regdom_by_device(technology, alpha2) != 0) { for (tech_drivers = technology->driver_list; - tech_drivers != NULL; + tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { struct connman_technology_driver *driver = tech_drivers->data; - if (driver->set_regdom != NULL) + if (driver->set_regdom) driver->set_regdom(technology, alpha2); } } @@ -424,28 +389,49 @@ static struct connman_technology *technology_find(enum connman_service_type type return NULL; } -connman_bool_t connman_technology_get_wifi_tethering(const char **ssid, +enum connman_service_type connman_technology_get_type + (struct connman_technology *technology) +{ + if (!technology) + return CONNMAN_SERVICE_TYPE_UNKNOWN; + + return technology->type; +} + +bool connman_technology_get_wifi_tethering(const char **ssid, const char **psk) { struct connman_technology *technology; - if (ssid == NULL || psk == NULL) - return FALSE; + if (!ssid || !psk) + return false; *ssid = *psk = NULL; technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI); - if (technology == NULL) - return FALSE; + if (!technology) + return false; - if (technology->tethering == FALSE) - return FALSE; + if (!technology->tethering) + return false; *ssid = technology->tethering_ident; *psk = technology->tethering_passphrase; - return TRUE; + return true; +} + +#if defined TIZEN_EXT +const char *connman_techonology_get_path(enum connman_service_type type) +{ + struct connman_technology *technology = technology_find(type); + + if (!technology) + return NULL; + + return technology->path; } +#endif static void free_rfkill(gpointer data) { @@ -459,48 +445,58 @@ static void technology_load(struct connman_technology *technology) GKeyFile *keyfile; gchar *identifier; GError *error = NULL; - connman_bool_t enable, need_saving = FALSE; + bool enable, need_saving = false; DBG("technology %p", technology); keyfile = __connman_storage_load_global(); /* Fallback on disabling technology if file not found. */ - if (keyfile == NULL) { + if (!keyfile) { if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET) /* We enable ethernet by default */ - technology->enable_persistent = TRUE; + technology->enable_persistent = true; else - technology->enable_persistent = FALSE; + technology->enable_persistent = false; return; } identifier = g_strdup_printf("%s", get_name(technology->type)); - if (identifier == NULL) + if (!identifier) goto done; +#ifdef TIZEN_EXT + gsize length; + technology->enabled_devices = g_key_file_get_string_list(keyfile, + identifier, "Enable.Devices", &length, NULL); + if (technology->enabled_devices && length == 0) { + g_strfreev(technology->enabled_devices); + technology->enabled_devices = NULL; + } +#endif + enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error); - if (error == NULL) + if (!error) technology->enable_persistent = enable; else { if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET) - technology->enable_persistent = TRUE; + technology->enable_persistent = true; else - technology->enable_persistent = FALSE; + technology->enable_persistent = false; - need_saving = TRUE; + need_saving = true; g_clear_error(&error); } enable = g_key_file_get_boolean(keyfile, identifier, "Tethering", &error); - if (error == NULL) + if (!error) technology->tethering_persistent = enable; else { - need_saving = TRUE; + need_saving = true; g_clear_error(&error); } - if (need_saving == TRUE) + if (need_saving) technology_save(technology); technology->tethering_ident = g_key_file_get_string(keyfile, @@ -508,52 +504,92 @@ static void technology_load(struct connman_technology *technology) technology->tethering_passphrase = g_key_file_get_string(keyfile, identifier, "Tethering.Passphrase", NULL); + +#ifdef TIZEN_EXT + if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) { + unsigned int val = 0; + + val = g_key_file_get_uint64(keyfile, + identifier, "MacPolicy", NULL); + if (val <= 2) + technology->mac_policy = val; + else + technology->mac_policy = 0; + + val = g_key_file_get_uint64(keyfile, + identifier, "PreassocMacPolicy", NULL); + if (val <= 2) + technology->preassoc_mac_policy = val; + else + technology->preassoc_mac_policy = 0; + + val = g_key_file_get_uint64(keyfile, + identifier, "RandomMacLifetime", NULL); + if (val > 0) + technology->random_mac_lifetime = val; + else + technology->random_mac_lifetime = 60; + } +#endif /* TIZEN_EXT */ + done: g_free(identifier); g_key_file_free(keyfile); - - return; } -connman_bool_t __connman_technology_get_offlinemode(void) +bool __connman_technology_get_offlinemode(void) { return global_offlinemode; } -static void connman_technology_save_offlinemode() +static void connman_technology_save_offlinemode(void) { GKeyFile *keyfile; + GError *error = NULL; + bool offlinemode; keyfile = __connman_storage_load_global(); - if (keyfile == NULL) + + if (!keyfile) { keyfile = g_key_file_new(); + g_key_file_set_boolean(keyfile, "global", + "OfflineMode", global_offlinemode); + + __connman_storage_save_global(keyfile); + } + else { + offlinemode = g_key_file_get_boolean(keyfile, "global", + "OfflineMode", &error); - g_key_file_set_boolean(keyfile, "global", + if (error || offlinemode != global_offlinemode) { + g_key_file_set_boolean(keyfile, "global", "OfflineMode", global_offlinemode); + if (error) + g_clear_error(&error); - __connman_storage_save_global(keyfile); + __connman_storage_save_global(keyfile); + } + } g_key_file_free(keyfile); - - return; } -static connman_bool_t connman_technology_load_offlinemode() +static bool connman_technology_load_offlinemode(void) { GKeyFile *keyfile; GError *error = NULL; - connman_bool_t offlinemode; + bool offlinemode; /* If there is a error, we enable offlinemode */ keyfile = __connman_storage_load_global(); - if (keyfile == NULL) - return FALSE; + if (!keyfile) + return false; offlinemode = g_key_file_get_boolean(keyfile, "global", "OfflineMode", &error); - if (error != NULL) { - offlinemode = FALSE; + if (error) { + offlinemode = false; g_clear_error(&error); } @@ -562,47 +598,140 @@ static connman_bool_t connman_technology_load_offlinemode() return offlinemode; } +#if defined TIZEN_EXT +static void append_devices(DBusMessageIter *iter, void *user_data) +{ + GSList *list; + dbus_bool_t val; + struct connman_technology *technology = user_data; + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + const char *str = connman_device_get_string(device, "Interface"); + struct connman_network *network = connman_device_get_default_network(device); + struct connman_service *service = connman_service_lookup_from_network(network); + + connman_dbus_dict_append_basic(iter, "Ifname", + DBUS_TYPE_STRING, &str); + + val = connman_device_get_powered(device); + connman_dbus_dict_append_basic(iter, "Powered", + DBUS_TYPE_BOOLEAN, &val); + + if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) || + __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6)) + val = TRUE; + else + val = FALSE; + + connman_dbus_dict_append_basic(iter, "Connected", + DBUS_TYPE_BOOLEAN, &val); + + str = connman_device_get_string(device, "Address"); + connman_dbus_dict_append_basic(iter, "MAC.Address", + DBUS_TYPE_STRING, &str); + } +} + +void __connman_technology_append_interfaces(DBusMessageIter *array, + enum connman_service_type type, const char *ifname) +{ + GSList *list; + struct connman_technology *technology = NULL; + + for (list = technology_list; list; list = list->next) { + struct connman_technology *local_tech = list->data; + + if (local_tech->type != type) + continue; + + technology = local_tech; + break; + } + + if (!technology) + return; + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + const char *str = connman_device_get_string(device, "Interface"); + + if (g_strcmp0(ifname, str) == 0) + continue; + + dbus_message_iter_append_basic(array, + DBUS_TYPE_STRING, &str); + } +} +#endif + static void append_properties(DBusMessageIter *iter, struct connman_technology *technology) { DBusMessageIter dict; + dbus_bool_t val; const char *str; connman_dbus_dict_open(iter, &dict); str = get_name(technology->type); - if (str != NULL) + if (str) connman_dbus_dict_append_basic(&dict, "Name", DBUS_TYPE_STRING, &str); str = __connman_service_type2string(technology->type); - if (str != NULL) + if (str) connman_dbus_dict_append_basic(&dict, "Type", DBUS_TYPE_STRING, &str); __sync_synchronize(); + val = technology->enabled; connman_dbus_dict_append_basic(&dict, "Powered", DBUS_TYPE_BOOLEAN, - &technology->enabled); + &val); + val = technology->connected; connman_dbus_dict_append_basic(&dict, "Connected", DBUS_TYPE_BOOLEAN, - &technology->connected); + &val); + val = technology->tethering; connman_dbus_dict_append_basic(&dict, "Tethering", DBUS_TYPE_BOOLEAN, - &technology->tethering); + &val); - if (technology->tethering_ident != NULL) + if (technology->tethering_ident) connman_dbus_dict_append_basic(&dict, "TetheringIdentifier", DBUS_TYPE_STRING, &technology->tethering_ident); - if (technology->tethering_passphrase != NULL) + if (technology->tethering_passphrase) connman_dbus_dict_append_basic(&dict, "TetheringPassphrase", DBUS_TYPE_STRING, &technology->tethering_passphrase); +#if defined TIZEN_EXT + connman_dbus_dict_append_basic(&dict, "MacPolicy", + DBUS_TYPE_UINT32, + &(technology->mac_policy)); + + connman_dbus_dict_append_basic(&dict, "PreassocMacPolicy", + DBUS_TYPE_UINT32, + &(technology->preassoc_mac_policy)); + + connman_dbus_dict_append_basic(&dict, "RandomMacLifetime", + DBUS_TYPE_UINT32, + &(technology->random_mac_lifetime)); + + if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) + connman_dbus_dict_append_dict(&dict, "Device.List", + append_devices, technology); + if (technology->regdom) + connman_dbus_dict_append_basic(&dict, "CountryCode", + DBUS_TYPE_STRING, + &technology->regdom); +#endif connman_dbus_dict_close(iter, &dict); } @@ -613,7 +742,7 @@ static void technology_added_signal(struct connman_technology *technology) signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, "TechnologyAdded"); - if (signal == NULL) + if (!signal) return; dbus_message_iter_init_append(signal, &iter); @@ -641,7 +770,7 @@ static DBusMessage *get_properties(DBusConnection *conn, DBusMessageIter iter; reply = dbus_message_new_method_return(message); - if (reply == NULL) + if (!reply) return NULL; dbus_message_iter_init_append(reply, &iter); @@ -658,9 +787,9 @@ void __connman_technology_list_struct(DBusMessageIter *array) for (list = technology_list; list; list = list->next) { struct connman_technology *technology = list->data; - if (technology->path == NULL || - (technology->rfkill_driven == TRUE && - technology->hardblocked == TRUE)) + if (!technology->path || + (technology->rfkill_driven && + technology->hardblocked)) continue; dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT, @@ -677,10 +806,10 @@ static gboolean technology_pending_reply(gpointer user_data) struct connman_technology *technology = user_data; DBusMessage *reply; - /* Power request timedout, send ETIMEDOUT. */ - if (technology->pending_reply != NULL) { + /* Power request timed out, send ETIMEDOUT. */ + if (technology->pending_reply) { reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT); - if (reply != NULL) + if (reply) g_dbus_send_message(connection, reply); dbus_message_unref(technology->pending_reply); @@ -692,88 +821,209 @@ static gboolean technology_pending_reply(gpointer user_data) } static int technology_affect_devices(struct connman_technology *technology, - connman_bool_t enable_device) + bool enable_device) { + int err = 0, err_dev; GSList *list; - int err = 0; + + if (technology->type == CONNMAN_SERVICE_TYPE_P2P) { + if (enable_device) + __connman_technology_enabled(technology->type); + else + __connman_technology_disabled(technology->type); + return 0; + } + +#if defined TIZEN_EXT_WIFI_MESH + if (technology->type == CONNMAN_SERVICE_TYPE_MESH) + return 0; +#endif for (list = technology->device_list; list; list = list->next) { struct connman_device *device = list->data; - if (enable_device == TRUE) - err = __connman_device_enable(device); + if (enable_device) + err_dev = __connman_device_enable(device); else - err = __connman_device_disable(device); + err_dev = __connman_device_disable(device); + + if (err_dev < 0 && err_dev != -EALREADY) + err = err_dev; } return err; } -static int technology_enable(struct connman_technology *technology) +static void powered_changed(struct connman_technology *technology) { - int err = 0; - int err_dev; + dbus_bool_t enabled; - DBG("technology %p enable", technology); + if (!technology->dbus_registered) + return; + + if (technology->pending_reply) { + g_dbus_send_reply(connection, + technology->pending_reply, DBUS_TYPE_INVALID); + dbus_message_unref(technology->pending_reply); + technology->pending_reply = NULL; + + g_source_remove(technology->pending_timeout); + technology->pending_timeout = 0; + } + + __sync_synchronize(); + enabled = technology->enabled; +#if defined TIZEN_EXT + DBG("ConnMan, Powered : %s, %s", + enabled ? "TRUE" : "FALSE",technology->path); +#endif + connman_dbus_property_changed_basic(technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, "Powered", + DBUS_TYPE_BOOLEAN, &enabled); +} + +static void enable_tethering(struct connman_technology *technology) +{ + int ret; + + if (!connman_setting_get_bool("PersistentTetheringMode")) + return; + + ret = set_tethering(technology, true); + if (ret < 0 && ret != -EALREADY) + DBG("Cannot enable tethering yet for %s (%d/%s)", + get_name(technology->type), + -ret, strerror(-ret)); +} +static int technology_enabled(struct connman_technology *technology) +{ __sync_synchronize(); - if (technology->enabled == TRUE) + if (technology->enabled) return -EALREADY; - if (technology->pending_reply != NULL) - return -EBUSY; + technology->enabled = true; - if (connman_setting_get_bool("PersistentTetheringMode") == TRUE && - technology->tethering == TRUE) - set_tethering(technology, TRUE); + if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) { + struct connman_technology *p2p; - if (technology->rfkill_driven == TRUE) - err = __connman_rfkill_block(technology->type, FALSE); + p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P); + if (p2p && !p2p->enabled && p2p->enable_persistent) + technology_enabled(p2p); + } - err_dev = technology_affect_devices(technology, TRUE); + if (technology->tethering_persistent) + enable_tethering(technology); - if (technology->rfkill_driven == FALSE) - err = err_dev; + powered_changed(technology); - return err; + return 0; } -static int technology_disable(struct connman_technology *technology) +static int technology_enable(struct connman_technology *technology) { - int err; + int err = 0; + int err_dev; - DBG("technology %p disable", technology); + DBG("technology %p enable", technology); __sync_synchronize(); - if (technology->enabled == FALSE) + + if (technology->type == CONNMAN_SERVICE_TYPE_P2P) { + struct connman_technology *wifi; + + wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI); + if (wifi && wifi->enabled) + return technology_enabled(technology); + return 0; + } + + if (technology->enabled) return -EALREADY; - if (technology->pending_reply != NULL) + if (technology->pending_reply) return -EBUSY; - if (technology->tethering == TRUE) - set_tethering(technology, FALSE); + if (connman_setting_get_bool("PersistentTetheringMode") && + technology->tethering) + set_tethering(technology, true); - err = technology_affect_devices(technology, FALSE); + if (technology->rfkill_driven) + err = __connman_rfkill_block(technology->type, false); - if (technology->rfkill_driven == TRUE) - err = __connman_rfkill_block(technology->type, TRUE); + err_dev = technology_affect_devices(technology, true); + + if (!technology->rfkill_driven) + err = err_dev; return err; } -static DBusMessage *set_powered(struct connman_technology *technology, - DBusMessage *msg, connman_bool_t powered) +static int technology_disabled(struct connman_technology *technology) { - DBusMessage *reply = NULL; - int err = 0; + __sync_synchronize(); + if (!technology->enabled) + return -EALREADY; - if (technology->rfkill_driven && technology->hardblocked == TRUE) { + technology->enabled = false; + + powered_changed(technology); + + return 0; +} + +static int technology_disable(struct connman_technology *technology) +{ + int err; + + DBG("technology %p disable", technology); + + __sync_synchronize(); + + if (technology->type == CONNMAN_SERVICE_TYPE_P2P) { + technology->enable_persistent = false; + __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P); + __connman_peer_disconnect_all(); + return technology_disabled(technology); + } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) { + struct connman_technology *p2p; + + p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P); + if (p2p && p2p->enabled) { + p2p->enable_persistent = true; + technology_disabled(p2p); + } + } + + if (!technology->enabled) + return -EALREADY; + + if (technology->pending_reply) + return -EBUSY; + + if (technology->tethering) + set_tethering(technology, false); + + err = technology_affect_devices(technology, false); + + if (technology->rfkill_driven) + err = __connman_rfkill_block(technology->type, true); + + return err; +} + +static DBusMessage *set_powered(struct connman_technology *technology, + DBusMessage *msg, bool powered) +{ + DBusMessage *reply = NULL; + int err = 0; + + if (technology->rfkill_driven && technology->hardblocked) { err = -EACCES; goto make_reply; } - if (powered == TRUE) + if (powered) err = technology_enable(technology); else err = technology_disable(technology); @@ -789,7 +1039,7 @@ make_reply: technology->pending_timeout = g_timeout_add_seconds(10, technology_pending_reply, technology); } else if (err == -EALREADY) { - if (powered == TRUE) + if (powered) reply = __connman_error_already_enabled(msg); else reply = __connman_error_already_disabled(msg); @@ -801,17 +1051,291 @@ make_reply: return reply; } +#if defined TIZEN_EXT +int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname) +{ + static int bssid_len; + static const char *def_ifname = "default"; + static GSList *bssid_list = NULL; + GSList *list; + const char *local_ifname = ifname; + bool found = false; + struct connman_bssid_pending *bssid_info; + + DBG("mode: %d, ifname: %s", mode, ifname); + + if (!ifname) + local_ifname = def_ifname; + + for (list = bssid_list; list; list = list->next) { + bssid_info = list->data; + + if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) { + found = true; + break; + } + } + + if (mode == CHECK_BSSID) { + if (found) + return 6; + + return 0; + } + + if (mode == GET_BSSID && bssid) { + if (found) { + memcpy(bssid, bssid_info->bssid, 6); + return 6; + } + return 0; + } + + if (mode == RESET_BSSID) { + if (found) { + bssid_list = g_slist_remove(bssid_list, bssid_info); + g_free(bssid_info->ifname); + g_free(bssid_info); + } + return 0; + } + + if (mode != SET_BSSID || !bssid) { + DBG("Invalid parameter"); + return 0; + } + + if (found) { + bssid_list = g_slist_remove(bssid_list, bssid_info); + g_free(bssid_info->ifname); + g_free(bssid_info); + } + + bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending)); + if (!bssid_info) { + DBG("Failed to allocate memory"); + return 0; + } + + unsigned char *bssid_data = bssid_info->bssid; + + bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + &bssid_data[0], &bssid_data[1], &bssid_data[2], + &bssid_data[3], &bssid_data[4], &bssid_data[5]); + if (bssid_len != 6) { + DBG("Incorrect BSSID format. bssid_len = %d", bssid_len); + g_free(bssid_info); + return 0; + } + + DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s", + bssid_len, + bssid_data[0], bssid_data[1], bssid_data[2], + bssid_data[3], bssid_data[4], bssid_data[5], + ifname); + + bssid_info->ifname = g_strdup(ifname); + bssid_list = g_slist_prepend(bssid_list, bssid_info); + + return bssid_len; +} + +void connman_technology_mac_policy_notify(struct connman_technology *technology, + unsigned int policy) +{ + DBG("Mac polict set to %u", policy); + + technology->mac_policy = policy; + technology_save(technology); +} + +void __connman_technology_notify_mac_policy_by_device(struct connman_device *device, + int result, unsigned int policy) +{ + struct connman_technology *technology; + enum connman_service_type type; + + type = __connman_device_get_service_type(device); + technology = technology_find(type); + + if (!technology) + return; + + connman_technology_mac_policy_notify(technology, policy); +} + +static DBusMessage *set_mac_policy(struct connman_technology *technology, + DBusMessage *msg, unsigned int policy) +{ + DBusMessage *reply = NULL; + int err = 0; + unsigned int last_policy = technology->mac_policy; + + if (technology->rfkill_driven && technology->hardblocked) { + err = -EACCES; + goto make_reply; + } + + for (GSList *list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + err = connman_device_set_mac_policy(device, policy); + if (err < 0) + break; + } + +make_reply: + if (err < 0) { + if (err != -EACCES && err != -EOPNOTSUPP) { + for (GSList *list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + connman_device_set_mac_policy(device, last_policy); + } + } + + reply = __connman_error_failed(msg, -err); + } else { + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + } + + return reply; +} + +void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology, + unsigned int policy) +{ + DBG("Preassoc mac polict set to %u", policy); + + technology->preassoc_mac_policy = policy; + technology_save(technology); +} + +void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device, + int result, unsigned int policy) +{ + struct connman_technology *technology; + enum connman_service_type type; + + type = __connman_device_get_service_type(device); + technology = technology_find(type); + + if (!technology) + return; + + connman_technology_preassoc_mac_policy_notify(technology, policy); +} + +static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology, + DBusMessage *msg, unsigned int policy) +{ + DBusMessage *reply = NULL; + int err = 0; + unsigned int last_policy = technology->preassoc_mac_policy; + + if (technology->rfkill_driven && technology->hardblocked) { + err = -EACCES; + goto make_reply; + } + + for (GSList *list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + err = connman_device_set_preassoc_mac_policy(device, policy); + if (err < 0) + break; + } + +make_reply: + if (err < 0) { + if (err != -EACCES && err != -EOPNOTSUPP) { + for (GSList *list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + connman_device_set_preassoc_mac_policy(device, last_policy); + } + } + + reply = __connman_error_failed(msg, -err); + } else { + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + } + + return reply; +} + +void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology, + unsigned int lifetime) +{ + DBG("Random mac lifetime set to %u", lifetime); + + technology->random_mac_lifetime = lifetime; + technology_save(technology); +} + +void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device, + int result, unsigned int lifetime) +{ + struct connman_technology *technology; + enum connman_service_type type; + + type = __connman_device_get_service_type(device); + technology = technology_find(type); + + if (!technology) + return; + + connman_technology_random_mac_lifetime_notify(technology, lifetime); +} + +static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology, + DBusMessage *msg, unsigned int lifetime) +{ + DBusMessage *reply = NULL; + int err = 0; + unsigned int last_lifetime = technology->random_mac_lifetime; + + if (technology->rfkill_driven && technology->hardblocked) { + err = -EACCES; + goto make_reply; + } + + for (GSList *list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + err = connman_device_set_random_mac_lifetime(device, lifetime); + } + +make_reply: + if (err < 0) { + if (err != -EACCES && err != -EOPNOTSUPP) { + for (GSList *list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + connman_device_set_random_mac_lifetime(device, last_lifetime); + } + } + + reply = __connman_error_failed(msg, -err); + } else { + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + } + + return reply; +} +#endif + static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_technology *technology = data; DBusMessageIter iter, value; const char *name; - int type; + int type, err; DBG("conn %p", conn); - if (dbus_message_iter_init(msg, &iter) == FALSE) + if (!dbus_message_iter_init(msg, &iter)) return __connman_error_invalid_arguments(msg); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) @@ -829,15 +1353,14 @@ static DBusMessage *set_property(DBusConnection *conn, DBG("property %s", name); - if (g_str_equal(name, "Tethering") == TRUE) { + if (g_str_equal(name, "Tethering")) { + dbus_bool_t tethering; int err; - connman_bool_t tethering; if (type != DBUS_TYPE_BOOLEAN) return __connman_error_invalid_arguments(msg); - if (connman_technology_is_tethering_allowed(technology->type) - == FALSE) { + if (!connman_technology_is_tethering_allowed(technology->type)) { DBG("%s tethering not allowed by config file", __connman_service_type2string(technology->type)); return __connman_error_not_supported(msg); @@ -846,7 +1369,7 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &tethering); if (technology->tethering == tethering) { - if (tethering == FALSE) + if (!tethering) return __connman_error_already_disabled(msg); else return __connman_error_already_enabled(msg); @@ -860,7 +1383,7 @@ static DBusMessage *set_property(DBusConnection *conn, technology_save(technology); - } else if (g_str_equal(name, "TetheringIdentifier") == TRUE) { + } else if (g_str_equal(name, "TetheringIdentifier")) { const char *str; dbus_message_iter_get_basic(&value, &str); @@ -882,7 +1405,7 @@ static DBusMessage *set_property(DBusConnection *conn, DBUS_TYPE_STRING, &technology->tethering_ident); } - } else if (g_str_equal(name, "TetheringPassphrase") == TRUE) { + } else if (g_str_equal(name, "TetheringPassphrase")) { const char *str; dbus_message_iter_get_basic(&value, &str); @@ -890,7 +1413,9 @@ static DBusMessage *set_property(DBusConnection *conn, if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) return __connman_error_not_supported(msg); - if (strlen(str) < 8 || strlen(str) > 63) + err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK, + str); + if (err < 0) return __connman_error_passphrase_required(msg); if (g_strcmp0(technology->tethering_passphrase, str) != 0) { @@ -904,8 +1429,8 @@ static DBusMessage *set_property(DBusConnection *conn, DBUS_TYPE_STRING, &technology->tethering_passphrase); } - } else if (g_str_equal(name, "Powered") == TRUE) { - connman_bool_t enable; + } else if (g_str_equal(name, "Powered")) { + dbus_bool_t enable; if (type != DBUS_TYPE_BOOLEAN) return __connman_error_invalid_arguments(msg); @@ -913,6 +1438,71 @@ static DBusMessage *set_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &enable); return set_powered(technology, msg, enable); +#if defined TIZEN_EXT + } else if (g_str_equal(name, "SetBSSID")) { + char *key; + + if (type != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value, &key); + DBG("BSSID %s", key); + set_connman_bssid(SET_BSSID, key, NULL); + } else if (g_str_equal(name, "MacPolicy")) { + dbus_uint32_t mac_policy; + + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) + return __connman_error_not_supported(msg); + + if (type != DBUS_TYPE_UINT32) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value, &mac_policy); + + if (mac_policy <= 2) + return set_mac_policy(technology, msg, mac_policy); + else + return __connman_error_invalid_arguments(msg); + + } else if (g_str_equal(name, "PreassocMacPolicy")) { + dbus_uint32_t preassoc_mac_policy; + + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) + return __connman_error_not_supported(msg); + + if (type != DBUS_TYPE_UINT32) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value, &preassoc_mac_policy); + + if (preassoc_mac_policy <= 2) + return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy); + else + return __connman_error_invalid_arguments(msg); + + } else if (g_str_equal(name, "RandomMacLifetime")) { + dbus_uint32_t random_mac_lifetime; + + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) + return __connman_error_not_supported(msg); + + if (type != DBUS_TYPE_UINT32) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value, &random_mac_lifetime); + + if (random_mac_lifetime > 0) + return set_random_mac_lifetime(technology, msg, random_mac_lifetime); + else + return __connman_error_invalid_arguments(msg); + + } else if (g_str_equal(name, "CountryCode")) { + const char *str; + + dbus_message_iter_get_basic(&value, &str); + DBG("country code %s", str); + connman_technology_set_regdom(str); +#endif } else return __connman_error_invalid_property(msg); @@ -925,9 +1515,13 @@ static void reply_scan_pending(struct connman_technology *technology, int err) DBG("technology %p err %d", technology, err); - while (technology->scan_pending != NULL) { + while (technology->scan_pending) { +#if defined TIZEN_EXT + struct connman_scan_pending *pending_data = technology->scan_pending->data; + DBusMessage *msg = pending_data->msg; +#else DBusMessage *msg = technology->scan_pending->data; - +#endif DBG("reply to %s", dbus_message_get_sender(msg)); if (err == 0) @@ -940,50 +1534,187 @@ static void reply_scan_pending(struct connman_technology *technology, int err) technology->scan_pending = g_slist_delete_link(technology->scan_pending, technology->scan_pending); +#if defined TIZEN_EXT + g_free(pending_data->ifname); + g_free(pending_data); +#endif } } -void __connman_technology_scan_started(struct connman_device *device) -{ - DBG("device %p", device); -} - -void __connman_technology_scan_stopped(struct connman_device *device) +#if defined TIZEN_EXT +dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val) { - int count = 0; - struct connman_technology *technology; - enum connman_service_type type; - GSList *list; + DBG("key %s", key); + DBusMessage *signal; + DBusMessageIter iter; + dbus_bool_t result = FALSE; - type = __connman_device_get_service_type(device); - technology = technology_find(type); + signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE, "ScanChanged"); + if (!signal) + return result; - DBG("technology %p device %p", technology, device); + dbus_message_iter_init_append(signal, &iter); + if (key) + connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val); + else + connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val); - if (technology == NULL) - return; + result = dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); - for (list = technology->device_list; list != NULL; list = list->next) { - struct connman_device *other_device = list->data; + DBG("Successfuly sent signal"); - if (device == other_device) + return result; +} + +void __connman_technology_notify_scan_done(const char *ifname, int val) +{ + DBG(""); + DBusMessage *signal; + DBusMessageIter iter; + + signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE, "ScanDone"); + if (!signal) + return; + + dbus_message_iter_init_append(signal, &iter); + if (ifname) + connman_dbus_property_append_basic(&iter, ifname, + DBUS_TYPE_INT32, &val); + else + connman_dbus_property_append_basic(&iter, "", + DBUS_TYPE_INT32, &val); + + dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); + + DBG("Successfuly sent ScanDone signal"); +} + +static void reply_scan_pending_device( + struct connman_technology *technology, const char *ifname, int count) +{ + DBusMessage *reply; + GSList *list; + dbus_bool_t status = 0; + connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN; + + DBG("technology %p ifname %s count %d", technology, ifname, count); + + list = technology->scan_pending; + + while (list) { + struct connman_scan_pending *pending_data = list->data; + DBusMessage *msg = pending_data->msg; + list = list->next; + + if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN) + scan_type = pending_data->scan_type; + + if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0) continue; - if (__connman_device_get_service_type(other_device) != type) + scan_type = pending_data->scan_type; + + DBG("reply to %s", dbus_message_get_sender(msg)); + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + + g_dbus_send_message(connection, reply); + dbus_message_unref(msg); + + technology->scan_pending = + g_slist_remove(technology->scan_pending, pending_data); + + g_free(pending_data->ifname); + g_free(pending_data); + } + + if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN) + scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL; + + __connman_technology_notify_scan_changed(ifname, &status); + __connman_technology_notify_scan_done(ifname, scan_type); +} + +static void __connman_technology_notify_device_detected( + struct connman_technology *technology, const char *ifname, bool val) +{ + DBG(""); + DBusMessage *signal; + DBusMessageIter iter; + dbus_bool_t detected = val; + + if (!ifname) + return; + + signal = dbus_message_new_signal(technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected"); + if (!signal) + return; + + dbus_message_iter_init_append(signal, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected); + + dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); + + DBG("Successfuly sent DeviceDetected signal"); +} +#endif + +void __connman_technology_scan_started(struct connman_device *device) +{ + DBG("device %p", device); +#if defined TIZEN_EXT + dbus_bool_t status = 1; + const char *ifname = connman_device_get_string(device, "Interface"); + + __connman_technology_notify_scan_changed(ifname, &status); +#endif +} + +void __connman_technology_scan_stopped(struct connman_device *device, + enum connman_service_type type) +{ + int count = 0; + struct connman_technology *technology; + GSList *list; + + technology = technology_find(type); + + DBG("technology %p device %p", technology, device); + + if (!technology) + return; + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *other_device = list->data; + + if (device == other_device) continue; - if (connman_device_get_scanning(other_device) == TRUE) + if (connman_device_get_scanning(other_device, type)) count += 1; } +#if defined TIZEN_EXT + const char *ifname = connman_device_get_string(device, "Interface"); + reply_scan_pending_device(technology, ifname, count); + + return; +#else if (count == 0) reply_scan_pending(technology, 0); +#endif } void __connman_technology_notify_regdom_by_device(struct connman_device *device, int result, const char *alpha2) { - connman_bool_t regdom_set = FALSE; + bool regdom_set = false; struct connman_technology *technology; enum connman_service_type type; GSList *tech_drivers; @@ -991,49 +1722,1053 @@ void __connman_technology_notify_regdom_by_device(struct connman_device *device, type = __connman_device_get_service_type(device); technology = technology_find(type); - if (technology == NULL) + if (!technology) return; if (result < 0) { for (tech_drivers = technology->driver_list; - tech_drivers != NULL; + tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { struct connman_technology_driver *driver = tech_drivers->data; - if (driver->set_regdom != NULL) { + if (driver->set_regdom) { driver->set_regdom(technology, alpha2); - regdom_set = TRUE; + regdom_set = true; } } - if (regdom_set == FALSE) + if (!regdom_set) alpha2 = NULL; } connman_technology_regdom_notify(technology, alpha2); } -static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) -{ - struct connman_technology *technology = data; - int err; +static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) +{ + struct connman_technology *technology = data; + int err; + + DBG("technology %p request from %s", technology, + dbus_message_get_sender(msg)); + + if (technology->type == CONNMAN_SERVICE_TYPE_P2P && + !technology->enabled) + return __connman_error_permission_denied(msg); + +#if !defined TIZEN_EXT + dbus_message_ref(msg); + technology->scan_pending = + g_slist_prepend(technology->scan_pending, msg); +#endif + + err = __connman_device_request_scan_full(technology->type); + if (err < 0) +#if defined TIZEN_EXT + return __connman_error_failed(msg, -err); +#else + reply_scan_pending(technology, err); +#endif + +#if defined TIZEN_EXT + struct connman_scan_pending *pending_data = + g_try_malloc0(sizeof(struct connman_scan_pending)); + if (!pending_data) + return __connman_error_failed(msg, ENOMEM); + + pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL; + DBG("scan_type %d", pending_data->scan_type); + + pending_data->msg = dbus_message_ref(msg); + + technology->scan_pending = + g_slist_prepend(technology->scan_pending, pending_data); +#endif + return NULL; +} + +#if defined TIZEN_EXT +static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data) +{ + struct connman_technology *technology = data; + DBusMessageIter iter; + const char *ifname; + int err; + + DBG("technology %p request from %s", technology, + dbus_message_get_sender(msg)); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &ifname); + DBG("Interface name %s", ifname); + + if (!ifname || strlen(ifname) == 0) + return __connman_error_invalid_arguments(msg); + + err = connman_device_request_device_scan(technology->type, ifname, true); + if (err < 0) + return __connman_error_failed(msg, -err); + + struct connman_scan_pending *pending_data = + g_try_malloc0(sizeof(struct connman_scan_pending)); + if (!pending_data) + return __connman_error_failed(msg, ENOMEM); + + pending_data->ifname = g_strdup(ifname); + if (pending_data->ifname == NULL) { + g_free(pending_data); + return __connman_error_failed(msg, ENOMEM); + } + + pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL; + DBG("scan_type %d", pending_data->scan_type); + + pending_data->msg = dbus_message_ref(msg); + + technology->scan_pending = + g_slist_prepend(technology->scan_pending, pending_data); + + return NULL; +} + +static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data) +{ + struct connman_technology *technology = data; + GSList *specific_scan_list = NULL; + int scan_type = 0; + const char *name = NULL; + const char *freq = NULL; + const char *ifname = NULL; + DBusMessageIter iter, dict; + int err; + + DBG("technology %p request from %s", technology, + dbus_message_get_sender(msg)); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&iter, &dict); + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict, &entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + dbus_message_iter_recurse(&entry, &value2); + type = dbus_message_iter_get_arg_type(&value2); + if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) { + + dbus_message_iter_get_basic(&value2, &ifname); + DBG("ifname %s", ifname); + } else if (g_str_equal(key, "SSID")) { + if (type != DBUS_TYPE_STRING) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */ + dbus_message_iter_get_basic(&value2, &name); + DBG("name %s", name); + specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name)); + } else if (g_str_equal(key, "Frequency")) { + if (type != DBUS_TYPE_STRING) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */ + dbus_message_iter_get_basic(&value2, &freq); + DBG("freq %s", freq); + specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq))); + } else if (g_str_equal(key, "SSID_Mixed")) { + if (type != DBUS_TYPE_STRING) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */ + dbus_message_iter_get_basic(&value2, &name); + + connman_multi_scan_ap_s *ap = + (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s)); + if (ap) { + g_strlcpy(ap->str, name, strlen(name) + 1); + ap->flag = true; + specific_scan_list = g_slist_append(specific_scan_list, ap); + } else + DBG("Failed to allocate memory"); + + } else if (g_str_equal(key, "Frequency_Mixed")) { + if (type != DBUS_TYPE_STRING) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */ + dbus_message_iter_get_basic(&value2, &freq); + + connman_multi_scan_ap_s *ap = + (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s)); + if (ap) { + g_strlcpy(ap->str, freq, strlen(freq) + 1); + ap->flag = false; + specific_scan_list = g_slist_append(specific_scan_list, ap); + } else + DBG("Failed to allocate memory"); + } + dbus_message_iter_next(&dict); + } + + err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list); + if (err < 0) + return __connman_error_failed(msg, -err); + + guint list_size = g_slist_length(specific_scan_list); + + if (scan_type == CONNMAN_MULTI_SCAN_SSID || + scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) + g_slist_free_full(specific_scan_list, g_free); + + struct connman_scan_pending *pending_data = + g_try_malloc0(sizeof(struct connman_scan_pending)); + if (!pending_data) + return __connman_error_failed(msg, ENOMEM); + + if (ifname) { + pending_data->ifname = g_strdup(ifname); + if (pending_data->ifname == NULL) { + g_free(pending_data); + return __connman_error_failed(msg, ENOMEM); + } + } + + if (list_size == 1) + pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP; + else + pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP; + DBG("list_size %u scan_type %d", list_size, pending_data->scan_type); + + pending_data->msg = dbus_message_ref(msg); + + technology->scan_pending = + g_slist_prepend(technology->scan_pending, pending_data); + + return NULL; +} + +static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data) +{ + DBusMessage *reply; + DBusMessageIter iter, dict; + GSList *list; + struct connman_technology *technology = data; + dbus_bool_t supported = false; + const char *ifname = NULL; + + DBG("technology %p", technology); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + connman_dbus_dict_open(&iter, &dict); + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + supported = connman_device_get_wifi_5ghz_supported(device); + ifname = connman_device_get_string(device, "Interface"); + + DBG("ifname %s supported : %d", ifname, supported); + connman_dbus_dict_append_basic(&dict, ifname, + DBUS_TYPE_BOOLEAN, + &supported); + } + + connman_dbus_dict_close(&iter, &dict); + + return reply; +} + +static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data) +{ + DBusMessage *reply; + DBusMessageIter iter, dict; + GSList *list; + struct connman_technology *technology = data; + dbus_bool_t scanning = false; + const char *ifname = NULL; + + DBG("technology %p", technology); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + connman_dbus_dict_open(&iter, &dict); + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + scanning = connman_device_get_scanning(device, technology->type); + ifname = connman_device_get_string(device, "Interface"); + + DBG("ifname %s scanning : %d", ifname, scanning); + connman_dbus_dict_append_basic(&dict, ifname, + DBUS_TYPE_BOOLEAN, + &scanning); + } + + connman_dbus_dict_close(&iter, &dict); + + return reply; +} + +static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data) +{ + DBusMessage *reply; + DBusMessageIter iter, dict; + GSList *list; + struct connman_technology *technology = data; + dbus_int32_t max_scan_ssids = 0; + const char *ifname = NULL; + + DBG("technology %p", technology); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + connman_dbus_dict_open(&iter, &dict); + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + max_scan_ssids = connman_device_get_max_scan_ssids(device); + ifname = connman_device_get_string(device, "Interface"); + + DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids); + connman_dbus_dict_append_basic(&dict, ifname, + DBUS_TYPE_INT32, + &max_scan_ssids); + } + + connman_dbus_dict_close(&iter, &dict); + + return reply; +} + +static int technology_enable_device(struct connman_technology *technology, + bool enable_device, const char *ifname, struct connman_device **device_out) +{ + int err = 0; + GSList *list; + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + const char *str = connman_device_get_string(device, "Interface"); + + if (g_strcmp0(str, ifname) != 0) + continue; + + if (enable_device) + err = __connman_device_enable(device); + else + err = __connman_device_disable(device); + + *device_out = device; + return err; + } + + return -ENXIO; +} + +static DBusMessage *technology_set_device_powered(struct connman_technology *technology, + DBusMessage *msg, bool powered, const char *ifname) +{ + DBusMessage *reply = NULL; + struct connman_device *device = NULL; + int err = 0; + + err = technology_enable_device(technology, powered, ifname, &device); + + if (err == -EINPROGRESS) { + if (device) + connman_device_set_pending_reply(device, msg); + return reply; + } else if (err == -EALREADY) { + if (powered) + reply = __connman_error_already_enabled(msg); + else + reply = __connman_error_already_disabled(msg); + } else if (err < 0) + reply = __connman_error_failed(msg, -err); + else + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + + return reply; +} + +static DBusMessage *set_device_power(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_technology *technology = data; + DBusMessageIter iter; + const char *name; + int len; + dbus_bool_t enable; + + DBG("conn %p", conn); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &name); + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) + return __connman_error_invalid_arguments(msg); + + DBG("interface name %s", name); + + len = strlen(name); + + if (len + 1 > IFNAMSIZ) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &enable); + DBG("powered %s", enable ? "TRUE" : "FALSE"); + + return technology_set_device_powered(technology, msg, enable, name); +} + +static DBusMessage *set_bssid(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + DBusMessageIter iter; + char *name, *bssid; + int len; + + DBG("conn %p", conn); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &name); + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &bssid); + + DBG("interface name %s bssid %s", name, bssid); + + len = strlen(name); + + if (len + 1 > IFNAMSIZ) + return __connman_error_invalid_arguments(msg); + + set_connman_bssid(SET_BSSID, bssid, name); + + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); +} +static struct connman_technology *technology_get(enum connman_service_type type); + +void technology_save_device(struct connman_device *device) +{ + struct connman_technology *technology; + enum connman_service_type type; + + type = __connman_device_get_service_type(device); + technology = technology_get(type); + if (!technology) + return; + + GKeyFile *keyfile; + gchar *identifier; + const char *name = get_name(technology->type); + + DBG("technology %p type %d name %s", technology, technology->type, + name); + if (!name) + return; + + keyfile = __connman_storage_load_global(); + if (!keyfile) + keyfile = g_key_file_new(); + + identifier = g_strdup_printf("%s", name); + if (!identifier) + goto done; + + GSList *list = NULL; + gchar **ifname_list = NULL; + guint dev_count = g_slist_length(technology->device_list); + + if (dev_count > 1) { + GString *ifname_str = g_string_new(NULL); + + if (ifname_str) { + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + + if (connman_device_get_powered(device)) { + const char *ifname = connman_device_get_string(device, "Interface"); + + if (ifname_str->len > 0) + g_string_append_printf(ifname_str, " %s", ifname); + else + g_string_append(ifname_str, ifname); + } + } + + if (ifname_str->len > 0) { + ifname_list = g_strsplit_set(ifname_str->str, " ", 0); + dev_count = g_strv_length(ifname_list); + g_key_file_set_string_list(keyfile, identifier, "Enable.Devices", + (const gchar **) ifname_list, dev_count); + + technology->enable_persistent = true; + } else { + g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL); + technology->enable_persistent = false; + } + + g_strfreev(ifname_list); + g_string_free(ifname_str, TRUE); + } + } + + g_key_file_set_boolean(keyfile, identifier, "Enable", + technology->enable_persistent); + + g_key_file_set_boolean(keyfile, identifier, "Tethering", + technology->tethering_persistent); + + if (technology->tethering_ident) + g_key_file_set_string(keyfile, identifier, + "Tethering.Identifier", + technology->tethering_ident); + + if (technology->tethering_passphrase) + g_key_file_set_string(keyfile, identifier, + "Tethering.Passphrase", + technology->tethering_passphrase); + +done: + g_free(identifier); + + __connman_storage_save_global(keyfile); + + g_key_file_free(keyfile); +} +#endif + +#if defined TIZEN_EXT_WIFI_MESH +bool __connman_technology_get_connected(enum connman_service_type type) +{ + struct connman_technology *technology; + + technology = technology_find(type); + + if (!technology) + return false; + + return technology->connected; +} + +void __connman_technology_mesh_interface_create_finished( + enum connman_service_type type, bool success, + const char *error) +{ + DBusMessage *reply; + struct connman_technology *technology; + DBusMessage *msg; + technology = technology_find(type); + + DBG("technology %p success %d", technology, success); + + if (!technology) + return; + + msg = technology->mesh_dbus_msg; + if (!msg) { + DBG("No pending dbus message"); + return; + } + + if (success) { + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + __connman_device_request_scan(technology->type); + } else + reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE + ".MeshInterfaceAddFailed", "%s", error); + g_dbus_send_message(connection, reply); + dbus_message_unref(msg); + technology->mesh_dbus_msg = NULL; +} + +void __connman_technology_mesh_interface_remove_finished( + enum connman_service_type type, bool success) +{ + DBusMessage *reply; + struct connman_technology *technology; + DBusMessage *msg; + technology = technology_find(type); + + DBG("technology %p success %d", technology, success); + + if (!technology || !technology->mesh_dbus_msg) + return; + + msg = technology->mesh_dbus_msg; + if (!msg) { + DBG("No pending dbus message"); + return; + } + + if (success) + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + else + reply = __connman_error_failed(msg, EINVAL); + g_dbus_send_message(connection, reply); + dbus_message_unref(msg); + technology->mesh_dbus_msg = NULL; +} + +void __connman_technology_notify_abort_scan(enum connman_service_type type, + int result) +{ + DBusMessage *reply; + struct connman_technology *technology; + DBusMessage *msg; + technology = technology_find(type); + + DBG("technology %p result %d", technology, result); + + if (!technology || !technology->mesh_dbus_msg) + return; + + msg = technology->mesh_dbus_msg; + if (!msg) { + DBG("No pending dbus message"); + return; + } + + if (result < 0) + reply = __connman_error_scan_abort_failed(msg); + else + reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + + g_dbus_send_message(connection, reply); + dbus_message_unref(msg); + technology->mesh_dbus_msg = NULL; +} + +static DBusMessage *mesh_commands(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_technology *technology = data; + DBusMessageIter iter, value, dict; + const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL; + int err; + + DBG("conn %p", conn); + + if (technology->type != CONNMAN_SERVICE_TYPE_MESH) + return __connman_error_invalid_arguments(msg); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&iter, &cmd); + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&iter, &value); + + if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY) + return __connman_error_invalid_arguments(msg); + + DBG("Mesh Command %s", cmd); + if (g_str_equal(cmd, "MeshInterfaceAdd")) { + dbus_message_iter_recurse(&value, &dict); + const char *bridge_ifname = NULL; + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict, &entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&entry, &value2); + + type = dbus_message_iter_get_arg_type(&value2); + + if (g_str_equal(key, "Ifname")) { + if (type != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &ifname); + } else if (g_str_equal(key, "ParentIfname")) { + if (type != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &parent_ifname); + } else if (g_str_equal(key, "BridgeIfname")) { + if (type != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &bridge_ifname); + } + dbus_message_iter_next(&dict); + } + DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname, + bridge_ifname ? bridge_ifname : "NULL"); + err = __connman_mesh_add_virtual_interface(ifname, parent_ifname, + bridge_ifname); + + if (err != 0) { + DBG("Failed to add virtual mesh interface"); + return __connman_error_failed(msg, -err); + } + + DBG("Successfully added virtual mesh interface"); + + dbus_message_ref(msg); + technology->mesh_dbus_msg = msg; + + } else if (g_str_equal(cmd, "MeshInterfaceRemove")) { + dbus_message_iter_recurse(&value, &dict); + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict, &entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&entry, &value2); + + type = dbus_message_iter_get_arg_type(&value2); + + if (g_str_equal(key, "Ifname")) { + if (type != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &ifname); + } + dbus_message_iter_next(&dict); + } + DBG("Mesh Ifname %s", ifname); + err = __connman_mesh_remove_virtual_interface(ifname); + + if (err != 0) { + DBG("Failed to remove virtual mesh interface"); + return __connman_error_failed(msg, -err); + } + + DBG("Successfully removed virtual mesh interface"); + + dbus_message_ref(msg); + technology->mesh_dbus_msg = msg; + + } else if (g_str_equal(cmd, "MeshCreateNetwork")) { + struct connman_mesh *connman_mesh; + const char *name = NULL; + const char *sec_type = NULL; + const char *mesh_ifname = NULL; + char *identifier, *group, *address; + unsigned int freq = 0; + unsigned int ieee80211w = 0; + GString *str; + int i; + dbus_message_iter_recurse(&value, &dict); + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict, &entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&entry, &value2); + + type = dbus_message_iter_get_arg_type(&value2); + + if (g_str_equal(key, "Name")) { + if (type != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &name); + } else if (g_str_equal(key, "Frequency")) { + if (type != DBUS_TYPE_UINT16) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &freq); + } else if (g_str_equal(key, "Security")) { + if (type != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &sec_type); + } else if (g_str_equal(key, "Pmf")) { + if (type != DBUS_TYPE_UINT16) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &ieee80211w); + } + dbus_message_iter_next(&dict); + } + + if (name == NULL || sec_type == NULL || freq == 0) + return __connman_error_invalid_arguments(msg); + + DBG("Name %s Frequency %d Security type %s Pmf %u", + name, freq, sec_type, ieee80211w); + + if (g_strcmp0(sec_type, "none") != 0 && + g_strcmp0(sec_type, "sae") != 0) { + DBG("Unsupported security"); + return __connman_error_invalid_arguments(msg); + } + + mesh_ifname = connman_mesh_get_interface_name(); + + if (!connman_mesh_is_interface_created()) { + DBG("Mesh interface doesn't exists"); + return __connman_error_invalid_command(msg); + } + + str = g_string_sized_new((strlen(name) * 2) + 24); + + for (i = 0; name[i]; i++) + g_string_append_printf(str, "%02x", name[i]); + + g_string_append_printf(str, "_mesh"); + + if (g_strcmp0(sec_type, "none") == 0) + g_string_append_printf(str, "_none"); + else if (g_strcmp0(sec_type, "sae") == 0) + g_string_append_printf(str, "_sae"); + + group = g_string_free(str, FALSE); + + identifier = connman_inet_ifaddr(mesh_ifname); + address = connman_inet_ifname2addr(mesh_ifname); + + connman_mesh = connman_mesh_create(identifier, group); + connman_mesh_set_name(connman_mesh, name); + connman_mesh_set_address(connman_mesh, address); + connman_mesh_set_security(connman_mesh, sec_type); + connman_mesh_set_frequency(connman_mesh, freq); + connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname)); + connman_mesh_set_peer_type(connman_mesh, + CONNMAN_MESH_PEER_TYPE_CREATED); + connman_mesh_set_ieee80211w(connman_mesh, ieee80211w); + + connman_mesh_register(connman_mesh); + g_free(group); + g_free(identifier); + g_free(address); + DBG("Successfully Created Mesh Network"); + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + + } else if (g_str_equal(cmd, "AbortScan")) { + DBG("Abort Scan method"); + err = __connman_device_abort_scan(technology->type); + if (err != 0) { + DBG("Failed to abort scan"); + return __connman_error_failed(msg, -err); + } + + DBG("Successfully requested to abort scan"); + dbus_message_ref(msg); + technology->mesh_dbus_msg = msg; + + } else if (g_str_equal(cmd, "MeshSpecificScan")) { + const char *name = NULL; + unsigned int freq = 0; + dbus_message_iter_recurse(&value, &dict); + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict, &entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&entry, &value2); + + type = dbus_message_iter_get_arg_type(&value2); + + if (g_str_equal(key, "Name")) { + if (type != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &name); + } else if (g_str_equal(key, "Frequency")) { + if (type != DBUS_TYPE_UINT16) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &freq); + } + dbus_message_iter_next(&dict); + } + + DBG("MeshID %s Frequency %d sender %s", name, freq, + dbus_message_get_sender(msg)); + + struct connman_scan_pending *pending_data = + g_try_malloc0(sizeof(struct connman_scan_pending)); + if (!pending_data) + return __connman_error_failed(msg, ENOMEM); + + pending_data->msg = dbus_message_ref(msg); + + technology->scan_pending = + g_slist_prepend(technology->scan_pending, pending_data); + + err = __connman_device_request_mesh_specific_scan(technology->type, + name, freq); + if (err < 0) + reply_scan_pending(technology, err); + else + DBG("Successfully requested to scan specific Mesh Network"); + + } else if (g_str_equal(cmd, "SetMeshGate")) { + unsigned int hwmp_rootmode = 0; + bool gate_announce = false; + unsigned int stp = 0; + int err; + dbus_message_iter_recurse(&value, &dict); + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict, &entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&entry, &value2); + + type = dbus_message_iter_get_arg_type(&value2); + + if (g_str_equal(key, "GateAnnounce")) { + if (type != DBUS_TYPE_BOOLEAN) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &gate_announce); + } else if (g_str_equal(key, "HWMPRootMode")) { + if (type != DBUS_TYPE_UINT16) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value2, &hwmp_rootmode); + } else if (g_str_equal(key, "STP")) { + if (type != DBUS_TYPE_UINT16) + return __connman_error_invalid_arguments(msg); - DBG ("technology %p request from %s", technology, - dbus_message_get_sender(msg)); + dbus_message_iter_get_basic(&value2, &stp); + } + dbus_message_iter_next(&dict); + } - dbus_message_ref(msg); - technology->scan_pending = - g_slist_prepend(technology->scan_pending, msg); + DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s", + gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg)); - err = __connman_device_request_scan(technology->type); - if (err < 0) - reply_scan_pending(technology, err); + err = __connman_mesh_set_stp_gate_announce(gate_announce, + hwmp_rootmode, + stp); + if (err < 0) + return __connman_error_failed(msg, -err); + + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + } else + return __connman_error_invalid_command(msg); return NULL; } +#endif static const GDBusMethodTable technology_methods[] = { { GDBUS_DEPRECATED_METHOD("GetProperties", @@ -1043,34 +2778,119 @@ static const GDBusMethodTable technology_methods[] = { GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL, set_property) }, { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) }, +#if defined TIZEN_EXT + { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }), + NULL, scan_device) }, + { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }), + NULL, specific_scan) }, + { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }), + get_scan_state) }, + { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }), + get_5ghz_supported) }, + { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }), + get_max_scan_ssid) }, + { GDBUS_ASYNC_METHOD("SetDevicePower", + GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }), + NULL, set_device_power) }, + { GDBUS_ASYNC_METHOD("SetBSSID", + GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }), + NULL, set_bssid) }, +#endif +#if defined TIZEN_EXT_WIFI_MESH + { GDBUS_ASYNC_METHOD("MeshCommands", + GDBUS_ARGS({ "name", "s" }, { "value", "v" }), + NULL, mesh_commands) }, +#endif { }, }; static const GDBusSignalTable technology_signals[] = { { GDBUS_SIGNAL("PropertyChanged", GDBUS_ARGS({ "name", "s" }, { "value", "v" })) }, +#if defined TIZEN_EXT + { GDBUS_SIGNAL("DeviceChanged", + GDBUS_ARGS({ "device_property", "a{sv}" })) }, + { GDBUS_SIGNAL("DeviceDetected", + GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) }, +#endif { }, }; -static gboolean technology_dbus_register(struct connman_technology *technology) +static bool technology_dbus_register(struct connman_technology *technology) { - if (technology->dbus_registered == TRUE || - (technology->rfkill_driven == TRUE && - technology->hardblocked == TRUE)) - return TRUE; + if (technology->dbus_registered || + (technology->rfkill_driven && + technology->hardblocked)) + return true; - if (g_dbus_register_interface(connection, technology->path, - CONNMAN_TECHNOLOGY_INTERFACE, - technology_methods, technology_signals, - NULL, technology, NULL) == FALSE) { + if (!g_dbus_register_interface(connection, technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, + technology_methods, technology_signals, + NULL, technology, NULL)) { connman_error("Failed to register %s", technology->path); - return FALSE; + return false; } technology_added_signal(technology); - technology->dbus_registered = TRUE; + technology->dbus_registered = true; + + return true; +} + +static void technology_dbus_unregister(struct connman_technology *technology) +{ + if (!technology->dbus_registered) + return; + + technology_removed_signal(technology); + g_dbus_unregister_interface(connection, technology->path, + CONNMAN_TECHNOLOGY_INTERFACE); - return TRUE; + technology->dbus_registered = false; +} + +static void technology_put(struct connman_technology *technology) +{ + DBG("technology %p", technology); + + if (__sync_sub_and_fetch(&technology->refcount, 1) > 0) + return; + + reply_scan_pending(technology, -EINTR); + + while (technology->driver_list) { + struct connman_technology_driver *driver; + + driver = technology->driver_list->data; + + if (driver->remove) + driver->remove(technology); + + technology->driver_list = + g_slist_delete_link(technology->driver_list, + technology->driver_list); + } + + technology_list = g_slist_remove(technology_list, technology); + + technology_dbus_unregister(technology); + + g_slist_free(technology->device_list); + + if (technology->pending_reply) { + dbus_message_unref(technology->pending_reply); + technology->pending_reply = NULL; + g_source_remove(technology->pending_timeout); + technology->pending_timeout = 0; + } +#ifdef TIZEN_EXT + g_strfreev(technology->enabled_devices); +#endif + g_free(technology->path); + g_free(technology->regdom); + g_free(technology->tethering_ident); + g_free(technology->tethering_passphrase); + g_free(technology); } static struct connman_technology *technology_get(enum connman_service_type type) @@ -1084,12 +2904,18 @@ static struct connman_technology *technology_get(enum connman_service_type type) DBG("type %d", type); str = __connman_service_type2string(type); - if (str == NULL) + if (!str) return NULL; technology = technology_find(type); - if (technology != NULL) { - __sync_fetch_and_add(&technology->refcount, 1); + if (technology) { +#if defined TIZEN_EXT_WIFI_MESH + if (type != CONNMAN_SERVICE_TYPE_P2P && + type != CONNMAN_SERVICE_TYPE_MESH) +#else + if (type != CONNMAN_SERVICE_TYPE_P2P) +#endif + __sync_fetch_and_add(&technology->refcount, 1); return technology; } @@ -1103,121 +2929,169 @@ static struct connman_technology *technology_get(enum connman_service_type type) } } - if (tech_drivers == NULL) { + if (!tech_drivers) { DBG("No matching drivers found for %s.", __connman_service_type2string(type)); return NULL; } technology = g_try_new0(struct connman_technology, 1); - if (technology == NULL) + if (!technology) return NULL; technology->refcount = 1; - - technology->rfkill_driven = FALSE; - technology->softblocked = FALSE; - technology->hardblocked = FALSE; - technology->type = type; technology->path = g_strdup_printf("%s/technology/%s", CONNMAN_PATH, str); - technology->device_list = NULL; - - technology->pending_reply = NULL; - - technology_load(technology); +#if defined TIZEN_EXT_WIFI_MESH + if (type == CONNMAN_SERVICE_TYPE_MESH) { + struct connman_technology *wifi; - if (technology_dbus_register(technology) == FALSE) { - g_free(technology); - return NULL; + wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI); + if (wifi) + technology->enabled = wifi->enabled; } +#endif + technology_load(technology); technology_list = g_slist_prepend(technology_list, technology); - technology->driver_list = tech_drivers; - for (list = tech_drivers; list != NULL; list = g_slist_next(list)) { + for (list = tech_drivers; list; list = list->next) { driver = list->data; - if (driver->probe != NULL && driver->probe(technology) < 0) + if (driver->probe && driver->probe(technology) < 0) DBG("Driver probe failed for technology %p", technology); } - DBG("technology %p", technology); + if (!technology_dbus_register(technology)) { + technology_put(technology); + return NULL; + } - return technology; -} + if (type == CONNMAN_SERVICE_TYPE_P2P) { + struct connman_technology *wifi; + bool enable; -static void technology_dbus_unregister(struct connman_technology *technology) -{ - if (technology->dbus_registered == FALSE) - return; + enable = technology->enable_persistent; - technology_removed_signal(technology); - g_dbus_unregister_interface(connection, technology->path, - CONNMAN_TECHNOLOGY_INTERFACE); + wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI); + if (enable && wifi) + enable = wifi->enabled; + + technology_affect_devices(technology, enable); + } + + DBG("technology %p %s", technology, get_name(technology->type)); - technology->dbus_registered = FALSE; + return technology; } -static void technology_put(struct connman_technology *technology) +int connman_technology_driver_register(struct connman_technology_driver *driver) { - DBG("technology %p", technology); + GSList *list; + struct connman_device *device; + enum connman_service_type type; - if (__sync_sub_and_fetch(&technology->refcount, 1) > 0) - return; + for (list = driver_list; list; list = list->next) { + if (list->data == driver) + goto exist; + } - reply_scan_pending(technology, -EINTR); + DBG("Registering %s driver", driver->name); - while (technology->driver_list != NULL) { - struct connman_technology_driver *driver; + driver_list = g_slist_insert_sorted(driver_list, driver, + compare_priority); - driver = technology->driver_list->data; + /* + * Check for technology less devices if this driver + * can service any of them. + */ + for (list = techless_device_list; list; list = list->next) { + device = list->data; - if (driver->remove != NULL) - driver->remove(technology); + type = __connman_device_get_service_type(device); + if (type != driver->type) + continue; - technology->driver_list = - g_slist_delete_link(technology->driver_list, - technology->driver_list); + techless_device_list = g_slist_remove(techless_device_list, + device); + + __connman_technology_add_device(device); } - technology_list = g_slist_remove(technology_list, technology); + /* Check for orphaned rfkill switches. */ + g_hash_table_foreach(rfkill_list, rfkill_check, + GINT_TO_POINTER(driver->type)); - technology_dbus_unregister(technology); +exist: + if (driver->type == CONNMAN_SERVICE_TYPE_P2P) { + if (!technology_get(CONNMAN_SERVICE_TYPE_P2P)) + return -ENOMEM; + } - g_slist_free(technology->device_list); +#if defined TIZEN_EXT_WIFI_MESH + if (driver->type == CONNMAN_SERVICE_TYPE_MESH) { + if (!technology_get(CONNMAN_SERVICE_TYPE_MESH)) + return -ENOMEM; + } +#endif - g_free(technology->path); - g_free(technology->regdom); - g_free(technology->tethering_ident); - g_free(technology->tethering_passphrase); - g_free(technology); + return 0; } -static void enable_tethering(struct connman_technology *technology) +void connman_technology_driver_unregister(struct connman_technology_driver *driver) { - int ret; + GSList *list, *tech_drivers; + struct connman_technology *technology; + struct connman_technology_driver *current; - if (connman_setting_get_bool("PersistentTetheringMode") == FALSE) - return; + DBG("Unregistering driver %p name %s", driver, driver->name); - ret = set_tethering(technology, TRUE); - if (ret < 0 && ret != -EALREADY) - DBG("Cannot enable tethering yet for %s (%d/%s)", - get_name(technology->type), - -ret, strerror(-ret)); + for (list = technology_list; list; list = list->next) { + technology = list->data; + + for (tech_drivers = technology->driver_list; tech_drivers; + tech_drivers = g_slist_next(tech_drivers)) { + current = tech_drivers->data; + if (driver != current) + continue; + + if (driver->remove) + driver->remove(technology); + + technology->driver_list = + g_slist_remove(technology->driver_list, + driver); + break; + } + } + + driver_list = g_slist_remove(driver_list, driver); + + if (driver->type == CONNMAN_SERVICE_TYPE_P2P) { + technology = technology_find(CONNMAN_SERVICE_TYPE_P2P); + if (technology) + technology_put(technology); + } +#if defined TIZEN_EXT_WIFI_MESH + if (driver->type == CONNMAN_SERVICE_TYPE_MESH) { + technology = technology_find(CONNMAN_SERVICE_TYPE_MESH); + if (technology) + technology_put(technology); + } +#endif } void __connman_technology_add_interface(enum connman_service_type type, - int index, const char *name, const char *ident) + int index, const char *ident) { struct connman_technology *technology; GSList *tech_drivers; struct connman_technology_driver *driver; + char *name; switch (type) { case CONNMAN_SERVICE_TYPE_UNKNOWN: @@ -1230,22 +3104,27 @@ void __connman_technology_add_interface(enum connman_service_type type, case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: +#if defined TIZEN_EXT_WIFI_MESH + case CONNMAN_SERVICE_TYPE_MESH: +#endif break; } + name = connman_inet_ifname(index); connman_info("Adding interface %s [ %s ]", name, __connman_service_type2string(type)); technology = technology_find(type); - if (technology == NULL) - return; + if (!technology) + goto out; - for (tech_drivers = technology->driver_list; tech_drivers != NULL; + for (tech_drivers = technology->driver_list; tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { driver = tech_drivers->data; - if(driver->add_interface != NULL) + if (driver->add_interface) driver->add_interface(technology, index, name, ident); } @@ -1253,16 +3132,20 @@ void __connman_technology_add_interface(enum connman_service_type type, * At this point we can try to enable tethering automatically as * now the interfaces are set properly. */ - if (technology->tethering_persistent == TRUE) + if (technology->tethering_persistent) enable_tethering(technology); + +out: + g_free(name); } void __connman_technology_remove_interface(enum connman_service_type type, - int index, const char *name, const char *ident) + int index, const char *ident) { struct connman_technology *technology; GSList *tech_drivers; struct connman_technology_driver *driver; + char *name; switch (type) { case CONNMAN_SERVICE_TYPE_UNKNOWN: @@ -1275,22 +3158,28 @@ void __connman_technology_remove_interface(enum connman_service_type type, case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: case CONNMAN_SERVICE_TYPE_GADGET: + case CONNMAN_SERVICE_TYPE_P2P: +#if defined TIZEN_EXT_WIFI_MESH + case CONNMAN_SERVICE_TYPE_MESH: +#endif break; } + name = connman_inet_ifname(index); connman_info("Remove interface %s [ %s ]", name, __connman_service_type2string(type)); + g_free(name); technology = technology_find(type); - if (technology == NULL) + if (!technology) return; - for (tech_drivers = technology->driver_list; tech_drivers != NULL; + for (tech_drivers = technology->driver_list; tech_drivers; tech_drivers = g_slist_next(tech_drivers)) { driver = tech_drivers->data; - if(driver->remove_interface != NULL) + if (driver->remove_interface) driver->remove_interface(technology, index); } } @@ -1305,7 +3194,7 @@ int __connman_technology_add_device(struct connman_device *device) DBG("device %p type %s", device, get_name(type)); technology = technology_get(type); - if (technology == NULL) { + if (!technology) { /* * Since no driver can be found for this device at the moment we * add it to the techless device list. @@ -1317,8 +3206,8 @@ int __connman_technology_add_device(struct connman_device *device) } __sync_synchronize(); - if (technology->rfkill_driven == TRUE) { - if (technology->enabled == TRUE) + if (technology->rfkill_driven) { + if (technology->enabled) __connman_device_enable(device); else __connman_device_disable(device); @@ -1326,12 +3215,33 @@ int __connman_technology_add_device(struct connman_device *device) goto done; } - if (technology->enable_persistent == TRUE && - global_offlinemode == FALSE) { + if (technology->enable_persistent && + !global_offlinemode) { +#if defined TIZEN_EXT + bool found = true; + int err = 0; + if (technology->enabled_devices) { + int i = 0; + found = false; + const char *ifname = connman_device_get_string(device, "Interface"); + + while (technology->enabled_devices[i]) { + if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) { + found = true; + break; + } + i++; + } + } + + if (found) + err = __connman_device_enable(device); +#else int err = __connman_device_enable(device); +#endif /* * connman_technology_add_device() calls __connman_device_enable() - * but since the device is already enabled, the calls does not + * but since the device is already enabled, the call does not * propagate through to connman_technology_enabled via * connman_device_set_powered. */ @@ -1339,13 +3249,21 @@ int __connman_technology_add_device(struct connman_device *device) __connman_technology_enabled(type); } /* if technology persistent state is offline */ - if (technology->enable_persistent == FALSE) + if (!technology->enable_persistent) __connman_device_disable(device); done: technology->device_list = g_slist_prepend(technology->device_list, device); +#if defined TIZEN_EXT + const char *ifname = connman_device_get_string(device, "Interface"); + __connman_technology_notify_device_detected(technology, ifname, true); + + connman_device_set_mac_policy(device, technology->mac_policy); + connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy); + connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime); +#endif return 0; } @@ -1359,7 +3277,7 @@ int __connman_technology_remove_device(struct connman_device *device) type = __connman_device_get_service_type(device); technology = technology_find(type); - if (technology == NULL) { + if (!technology) { techless_device_list = g_slist_remove(techless_device_list, device); return -ENXIO; @@ -1368,47 +3286,15 @@ int __connman_technology_remove_device(struct connman_device *device) technology->device_list = g_slist_remove(technology->device_list, device); - if (technology->tethering == TRUE) - set_tethering(technology, FALSE); - - technology_put(technology); - - return 0; -} - -static void powered_changed(struct connman_technology *technology) -{ - if (technology->dbus_registered == FALSE) - return; - - if (technology->pending_reply != NULL) { - g_dbus_send_reply(connection, - technology->pending_reply, DBUS_TYPE_INVALID); - dbus_message_unref(technology->pending_reply); - technology->pending_reply = NULL; - - g_source_remove(technology->pending_timeout); - technology->pending_timeout = 0; - } - - __sync_synchronize(); - connman_dbus_property_changed_basic(technology->path, - CONNMAN_TECHNOLOGY_INTERFACE, "Powered", - DBUS_TYPE_BOOLEAN, &technology->enabled); -} - -static int technology_enabled(struct connman_technology *technology) -{ - __sync_synchronize(); - if (technology->enabled == TRUE) - return -EALREADY; - - technology->enabled = TRUE; +#if defined TIZEN_EXT + const char *ifname = connman_device_get_string(device, "Interface"); + __connman_technology_notify_device_detected(technology, ifname, false); +#endif - if (technology->tethering_persistent == TRUE) - enable_tethering(technology); + if (technology->tethering) + set_tethering(technology, false); - powered_changed(technology); + technology_put(technology); return 0; } @@ -1418,61 +3304,52 @@ int __connman_technology_enabled(enum connman_service_type type) struct connman_technology *technology; technology = technology_find(type); - if (technology == NULL) + if (!technology) return -ENXIO; DBG("technology %p type %s rfkill %d enabled %d", technology, get_name(type), technology->rfkill_driven, technology->enabled); - if (technology->rfkill_driven == TRUE) { - if (technology->tethering_persistent == TRUE) +#if !defined TIZEN_EXT + if (technology->rfkill_driven) { + if (technology->tethering_persistent) enable_tethering(technology); return 0; } +#endif return technology_enabled(technology); } -static int technology_disabled(struct connman_technology *technology) -{ - __sync_synchronize(); - if (technology->enabled == FALSE) - return -EALREADY; - - technology->enabled = FALSE; - - powered_changed(technology); - - return 0; -} - int __connman_technology_disabled(enum connman_service_type type) { struct connman_technology *technology; GSList *list; technology = technology_find(type); - if (technology == NULL) + if (!technology) return -ENXIO; - if (technology->rfkill_driven == TRUE) +#if !defined TIZEN_EXT + if (technology->rfkill_driven) return 0; - for (list = technology->device_list; list != NULL; list = list->next) { +#endif + for (list = technology->device_list; list; list = list->next) { struct connman_device *device = list->data; - if (connman_device_get_powered(device) == TRUE) + if (connman_device_get_powered(device)) return 0; } return technology_disabled(technology); } -int __connman_technology_set_offlinemode(connman_bool_t offlinemode) +int __connman_technology_set_offlinemode(bool offlinemode) { GSList *list; - int err = -EINVAL; + int err = -EINVAL, enabled_tech_count = 0; if (global_offlinemode == offlinemode) return 0; @@ -1485,7 +3362,7 @@ int __connman_technology_set_offlinemode(connman_bool_t offlinemode) * resuming offlinemode from last saved profile. We need that * information in rfkill_update, otherwise it falls back on the * technology's persistent state. Hence we set the offline mode here - * but save it & call the notifier only if its successful. + * but save it & call the notifier only if it is successful. */ global_offlinemode = offlinemode; @@ -1496,12 +3373,19 @@ int __connman_technology_set_offlinemode(connman_bool_t offlinemode) if (offlinemode) err = technology_disable(technology); + else { + if (technology->hardblocked) + continue; - if (!offlinemode && technology->enable_persistent) - err = technology_enable(technology); + if (technology->enable_persistent) { + err = technology_enable(technology); + enabled_tech_count++; + } + } } - if (err == 0 || err == -EINPROGRESS || err == -EALREADY) { + if (err == 0 || err == -EINPROGRESS || err == -EALREADY || + (err == -EINVAL && enabled_tech_count == 0)) { connman_technology_save_offlinemode(); __connman_notifier_offlinemode(offlinemode); } else @@ -1510,31 +3394,47 @@ int __connman_technology_set_offlinemode(connman_bool_t offlinemode) return err; } +#if defined TIZEN_EXT_WIFI_MESH +static gboolean __add_ethernet_to_bridge(gpointer data) +{ + DBG(""); + __connman_mesh_add_ethernet_to_bridge(); + return FALSE; +} +#endif + void __connman_technology_set_connected(enum connman_service_type type, - connman_bool_t connected) + bool connected) { struct connman_technology *technology; + dbus_bool_t val; technology = technology_find(type); - if (technology == NULL) + if (!technology) return; DBG("technology %p connected %d", technology, connected); technology->connected = connected; +#if defined TIZEN_EXT_WIFI_MESH + if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected) + g_idle_add(__add_ethernet_to_bridge, NULL); +#endif + + val = connected; connman_dbus_property_changed_basic(technology->path, CONNMAN_TECHNOLOGY_INTERFACE, "Connected", - DBUS_TYPE_BOOLEAN, &connected); + DBUS_TYPE_BOOLEAN, &val); } -static connman_bool_t technology_apply_rfkill_change(struct connman_technology *technology, - connman_bool_t softblock, - connman_bool_t hardblock, - connman_bool_t new_rfkill) +static bool technology_apply_rfkill_change(struct connman_technology *technology, + bool softblock, + bool hardblock, + bool new_rfkill) { - gboolean hardblock_changed = FALSE; - gboolean apply = TRUE; + bool hardblock_changed = false; + bool apply = true; GList *start, *list; DBG("technology %p --> %d/%d vs %d/%d", @@ -1544,53 +3444,58 @@ static connman_bool_t technology_apply_rfkill_change(struct connman_technology * if (technology->hardblocked == hardblock) goto softblock_change; - if (!(new_rfkill == TRUE && hardblock == FALSE)) { + if (!(new_rfkill && !hardblock)) { start = g_hash_table_get_values(rfkill_list); - for (list = start; list != NULL; list = list->next) { + for (list = start; list; list = list->next) { struct connman_rfkill *rfkill = list->data; if (rfkill->type != technology->type) continue; if (rfkill->hardblock != hardblock) - apply = FALSE; + apply = false; } g_list_free(start); } - if (apply == FALSE) + if (!apply) goto softblock_change; technology->hardblocked = hardblock; - hardblock_changed = TRUE; + hardblock_changed = true; softblock_change: - if (apply == FALSE && technology->softblocked != softblock) - apply = TRUE; + if (!apply && technology->softblocked != softblock) + apply = true; - if (apply == FALSE) + if (!apply) return technology->hardblocked; technology->softblocked = softblock; - if (technology->hardblocked == TRUE || - technology->softblocked == TRUE) { + if (technology->hardblocked || + technology->softblocked) { if (technology_disabled(technology) != -EALREADY) - technology_affect_devices(technology, FALSE); - } else if (technology->hardblocked == FALSE && - technology->softblocked == FALSE) { + technology_affect_devices(technology, false); + } else if (!technology->hardblocked && + !technology->softblocked) { if (technology_enabled(technology) != -EALREADY) - technology_affect_devices(technology, TRUE); + technology_affect_devices(technology, true); } - if (hardblock_changed == TRUE) { - if (technology->hardblocked == TRUE) { + if (hardblock_changed) { + if (technology->hardblocked) { DBG("%s is switched off.", get_name(technology->type)); technology_dbus_unregister(technology); - } else + } else { + DBG("%s is switched on.", get_name(technology->type)); technology_dbus_register(technology); + + if (global_offlinemode) + __connman_rfkill_block(technology->type, true); + } } return technology->hardblocked; @@ -1598,8 +3503,8 @@ softblock_change: int __connman_technology_add_rfkill(unsigned int index, enum connman_service_type type, - connman_bool_t softblock, - connman_bool_t hardblock) + bool softblock, + bool hardblock) { struct connman_technology *technology; struct connman_rfkill *rfkill; @@ -1608,11 +3513,11 @@ int __connman_technology_add_rfkill(unsigned int index, softblock, hardblock); rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index)); - if (rfkill != NULL) + if (rfkill) goto done; rfkill = g_try_new0(struct connman_rfkill, 1); - if (rfkill == NULL) + if (!rfkill) return -ENOMEM; rfkill->index = index; @@ -1623,38 +3528,45 @@ int __connman_technology_add_rfkill(unsigned int index, g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill); done: +#if defined TIZEN_EXT + /* Fix Svace Issue [WGID: 1348]. */ + g_free(rfkill); +#endif technology = technology_get(type); /* If there is no driver for this type, ignore it. */ - if (technology == NULL) + if (!technology) return -ENXIO; - technology->rfkill_driven = TRUE; + technology->rfkill_driven = true; +#if !defined TIZEN_EXT /* If hardblocked, there is no need to handle softblocked state */ if (technology_apply_rfkill_change(technology, - softblock, hardblock, TRUE) == TRUE) + softblock, hardblock, true)) + return 0; +#endif + + if (global_offlinemode) return 0; /* * Depending on softblocked state we unblock/block according to * offlinemode and persistente state. */ - if (technology->softblocked == TRUE && - global_offlinemode == FALSE && - technology->enable_persistent == TRUE) - return __connman_rfkill_block(type, FALSE); - else if (technology->softblocked == FALSE && - (global_offlinemode == TRUE || - technology->enable_persistent == FALSE)) - return __connman_rfkill_block(type, TRUE); + if (technology->softblocked && + technology->enable_persistent) + return __connman_rfkill_block(type, false); + else if (!technology->softblocked && + !technology->enable_persistent) + return __connman_rfkill_block(type, true); return 0; } int __connman_technology_update_rfkill(unsigned int index, enum connman_service_type type, - connman_bool_t softblock, - connman_bool_t hardblock) + bool softblock, + bool hardblock) { struct connman_technology *technology; struct connman_rfkill *rfkill; @@ -1662,7 +3574,7 @@ int __connman_technology_update_rfkill(unsigned int index, DBG("index %u soft %u hard %u", index, softblock, hardblock); rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index)); - if (rfkill == NULL) + if (!rfkill) return -ENXIO; if (rfkill->softblock == softblock && @@ -1674,27 +3586,17 @@ int __connman_technology_update_rfkill(unsigned int index, technology = technology_find(type); /* If there is no driver for this type, ignore it. */ - if (technology == NULL) + if (!technology) return -ENXIO; - /* If hardblocked, there is no need to handle softblocked state */ - if (technology_apply_rfkill_change(technology, - softblock, hardblock, FALSE) == TRUE) - return 0; - - if (global_offlinemode == TRUE) - return 0; + technology_apply_rfkill_change(technology, softblock, hardblock, + false); - /* - * Depending on softblocked state we unblock/block according to - * persistent state. - */ - if (technology->softblocked == TRUE && - technology->enable_persistent == TRUE) - return __connman_rfkill_block(type, FALSE); - else if (technology->softblocked == FALSE && - technology->enable_persistent == FALSE) - return __connman_rfkill_block(type, TRUE); + if (technology->hardblocked) + DBG("%s hardblocked", get_name(technology->type)); + else + DBG("%s is%s softblocked", get_name(technology->type), + technology->softblocked ? "" : " not"); return 0; } @@ -1708,17 +3610,17 @@ int __connman_technology_remove_rfkill(unsigned int index, DBG("index %u", index); rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index)); - if (rfkill == NULL) + if (!rfkill) return -ENXIO; g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index)); technology = technology_find(type); - if (technology == NULL) + if (!technology) return -ENXIO; technology_apply_rfkill_change(technology, - technology->softblocked, !technology->hardblocked, FALSE); + technology->softblocked, !technology->hardblocked, false); technology_put(technology); @@ -1746,6 +3648,12 @@ void __connman_technology_cleanup(void) { DBG(""); + while (technology_list) { + struct connman_technology *technology = technology_list->data; + technology_list = g_slist_remove(technology_list, technology); + technology_put(technology); + } + g_hash_table_destroy(rfkill_list); dbus_connection_unref(connection);