5 * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
38 static DBusConnection *connection;
40 static GSList *technology_list = NULL;
43 * List of devices with no technology associated with them either because of
44 * no compiled in support or the driver is not yet loaded.
46 static GSList *techless_device_list = NULL;
47 static GHashTable *rfkill_list;
49 static bool global_offlinemode;
52 struct connman_scan_pending {
54 connman_scan_type_e scan_type;
58 struct connman_bssid_pending {
60 unsigned char bssid[6];
64 struct connman_rfkill {
66 enum connman_service_type type;
71 struct connman_technology {
73 enum connman_service_type type;
81 bool tethering_persistent; /* Tells the save status, needed
82 * as offline mode might set
85 char *tethering_ident;
86 char *tethering_passphrase;
88 bool enable_persistent; /* Save the tech state */
92 DBusMessage *pending_reply;
93 guint pending_timeout;
100 bool dbus_registered;
101 #if defined TIZEN_EXT
102 char **enabled_devices;
103 unsigned int mac_policy;
104 unsigned int preassoc_mac_policy;
105 unsigned int random_mac_lifetime;
107 #if defined TIZEN_EXT_WIFI_MESH
108 DBusMessage *mesh_dbus_msg;
112 static GSList *driver_list = NULL;
114 static int technology_enabled(struct connman_technology *technology);
115 static int technology_disabled(struct connman_technology *technology);
117 static gint compare_priority(gconstpointer a, gconstpointer b)
119 const struct connman_technology_driver *driver1 = a;
120 const struct connman_technology_driver *driver2 = b;
122 return driver2->priority - driver1->priority;
125 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
127 struct connman_rfkill *rfkill = value;
128 enum connman_service_type type = GPOINTER_TO_INT(user_data);
130 /* Calling _technology_add_rfkill will update the tech. */
131 if (rfkill->type == type)
132 __connman_technology_add_rfkill(rfkill->index, type,
133 rfkill->softblock, rfkill->hardblock);
137 connman_technology_is_tethering_allowed(enum connman_service_type type)
139 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
141 const char *type_str = __connman_service_type2string(type);
148 allowed = connman_setting_get_string_list("TetheringTechnologies");
150 allowed = allowed_default;
152 for (i = 0; allowed[i]; i++) {
153 if (g_strcmp0(allowed[i], type_str) == 0)
160 static const char *get_name(enum connman_service_type type)
163 case CONNMAN_SERVICE_TYPE_UNKNOWN:
164 case CONNMAN_SERVICE_TYPE_SYSTEM:
165 case CONNMAN_SERVICE_TYPE_GPS:
166 case CONNMAN_SERVICE_TYPE_VPN:
168 case CONNMAN_SERVICE_TYPE_GADGET:
170 case CONNMAN_SERVICE_TYPE_ETHERNET:
172 case CONNMAN_SERVICE_TYPE_WIFI:
174 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
176 case CONNMAN_SERVICE_TYPE_CELLULAR:
178 case CONNMAN_SERVICE_TYPE_P2P:
180 #if defined TIZEN_EXT_WIFI_MESH
181 case CONNMAN_SERVICE_TYPE_MESH:
189 static void technology_save(struct connman_technology *technology)
193 const char *name = get_name(technology->type);
195 DBG("technology %p type %d name %s", technology, technology->type,
200 keyfile = __connman_storage_load_global();
202 keyfile = g_key_file_new();
204 identifier = g_strdup_printf("%s", name);
208 g_key_file_set_boolean(keyfile, identifier, "Enable",
209 technology->enable_persistent);
211 g_key_file_set_boolean(keyfile, identifier, "Tethering",
212 technology->tethering_persistent);
214 if (technology->tethering_ident)
215 g_key_file_set_string(keyfile, identifier,
216 "Tethering.Identifier",
217 technology->tethering_ident);
219 if (technology->tethering_passphrase) {
220 char *enc = g_strescape(technology->tethering_passphrase, NULL);
221 g_key_file_set_string(keyfile, identifier,
222 "Tethering.Passphrase", enc);
227 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
228 g_key_file_set_uint64(keyfile, identifier, "MacPolicy",
229 technology->mac_policy);
231 g_key_file_set_uint64(keyfile, identifier, "PreassocMacPolicy",
232 technology->preassoc_mac_policy);
234 g_key_file_set_uint64(keyfile, identifier, "RandomMacLifetime",
235 technology->random_mac_lifetime);
237 #endif /* TIZEN_EXT */
242 __connman_storage_save_global(keyfile);
244 g_key_file_free(keyfile);
247 static void tethering_changed(struct connman_technology *technology)
249 dbus_bool_t tethering = technology->tethering;
251 connman_dbus_property_changed_basic(technology->path,
252 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
253 DBUS_TYPE_BOOLEAN, &tethering);
255 technology_save(technology);
258 int connman_technology_tethering_notify(struct connman_technology *technology,
263 DBG("technology %p enabled %u", technology, enabled);
265 if (technology->tethering == enabled)
269 err = __connman_tethering_set_enabled();
273 __connman_tethering_set_disabled();
275 technology->tethering = enabled;
276 tethering_changed(technology);
281 static int set_tethering(struct connman_technology *technology,
284 int result = -EOPNOTSUPP;
286 const char *ident, *passphrase, *bridge;
287 GSList *tech_drivers;
289 ident = technology->tethering_ident;
290 passphrase = technology->tethering_passphrase;
292 __sync_synchronize();
293 if (!technology->enabled)
296 bridge = __connman_tethering_get_bridge();
300 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
301 (!ident || !passphrase))
304 for (tech_drivers = technology->driver_list; tech_drivers;
305 tech_drivers = g_slist_next(tech_drivers)) {
306 struct connman_technology_driver *driver = tech_drivers->data;
308 if (!driver || !driver->set_tethering)
311 err = driver->set_tethering(technology, ident, passphrase,
314 if (result == -EINPROGRESS)
317 if (err == -EINPROGRESS || err == 0)
324 void connman_technology_regdom_notify(struct connman_technology *technology,
330 connman_error("Failed to set regulatory domain");
332 DBG("Regulatory domain set to %s", alpha2);
334 g_free(technology->regdom);
335 technology->regdom = g_strdup(alpha2);
338 static int set_regdom_by_device(struct connman_technology *technology,
343 for (list = technology->device_list; list; list = list->next) {
344 struct connman_device *device = list->data;
346 if (connman_device_set_regdom(device, alpha2) != 0)
353 int connman_technology_set_regdom(const char *alpha2)
355 GSList *list, *tech_drivers;
357 for (list = technology_list; list; list = list->next) {
358 struct connman_technology *technology = list->data;
360 if (set_regdom_by_device(technology, alpha2) != 0) {
362 for (tech_drivers = technology->driver_list;
364 tech_drivers = g_slist_next(tech_drivers)) {
366 struct connman_technology_driver *driver =
369 if (driver->set_regdom)
370 driver->set_regdom(technology, alpha2);
378 static struct connman_technology *technology_find(enum connman_service_type type)
382 DBG("type %d", type);
384 for (list = technology_list; list; list = list->next) {
385 struct connman_technology *technology = list->data;
387 if (technology->type == type)
394 enum connman_service_type connman_technology_get_type
395 (struct connman_technology *technology)
398 return CONNMAN_SERVICE_TYPE_UNKNOWN;
400 return technology->type;
403 bool connman_technology_get_wifi_tethering(const char **ssid,
406 struct connman_technology *technology;
413 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
417 if (!technology->tethering)
420 *ssid = technology->tethering_ident;
421 *psk = technology->tethering_passphrase;
426 #if defined TIZEN_EXT
427 const char *connman_techonology_get_path(enum connman_service_type type)
429 struct connman_technology *technology = technology_find(type);
434 return technology->path;
438 static void free_rfkill(gpointer data)
440 struct connman_rfkill *rfkill = data;
445 static void technology_load(struct connman_technology *technology)
449 GError *error = NULL;
450 bool enable, need_saving = false;
457 DBG("technology %p", technology);
459 keyfile = __connman_storage_load_global();
460 /* Fallback on disabling technology if file not found. */
462 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
463 /* We enable ethernet by default */
464 technology->enable_persistent = true;
466 technology->enable_persistent = false;
470 identifier = g_strdup_printf("%s", get_name(technology->type));
476 technology->enabled_devices = g_key_file_get_string_list(keyfile,
477 identifier, "Enable.Devices", &length, NULL);
478 if (technology->enabled_devices && length == 0) {
479 g_strfreev(technology->enabled_devices);
480 technology->enabled_devices = NULL;
484 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
486 technology->enable_persistent = enable;
488 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
489 technology->enable_persistent = true;
491 technology->enable_persistent = false;
494 g_clear_error(&error);
497 enable = g_key_file_get_boolean(keyfile, identifier,
498 "Tethering", &error);
500 technology->tethering_persistent = enable;
503 g_clear_error(&error);
507 technology_save(technology);
509 technology->tethering_ident = g_key_file_get_string(keyfile,
510 identifier, "Tethering.Identifier", NULL);
512 enc = g_key_file_get_string(keyfile,
513 identifier, "Tethering.Passphrase", NULL);
515 technology->tethering_passphrase = g_strcompress(enc);
517 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
518 unsigned int val = 0;
520 val = g_key_file_get_uint64(keyfile,
521 identifier, "MacPolicy", NULL);
523 technology->mac_policy = val;
525 technology->mac_policy = 0;
527 val = g_key_file_get_uint64(keyfile,
528 identifier, "PreassocMacPolicy", NULL);
530 technology->preassoc_mac_policy = val;
532 technology->preassoc_mac_policy = 0;
534 val = g_key_file_get_uint64(keyfile,
535 identifier, "RandomMacLifetime", NULL);
537 technology->random_mac_lifetime = val;
539 technology->random_mac_lifetime = 60;
541 #endif /* TIZEN_EXT */
549 g_key_file_free(keyfile);
552 bool __connman_technology_get_offlinemode(void)
554 return global_offlinemode;
557 static void connman_technology_save_offlinemode(void)
560 GError *error = NULL;
563 keyfile = __connman_storage_load_global();
566 keyfile = g_key_file_new();
567 g_key_file_set_boolean(keyfile, "global",
568 "OfflineMode", global_offlinemode);
570 __connman_storage_save_global(keyfile);
573 offlinemode = g_key_file_get_boolean(keyfile, "global",
574 "OfflineMode", &error);
576 if (error || offlinemode != global_offlinemode) {
577 g_key_file_set_boolean(keyfile, "global",
578 "OfflineMode", global_offlinemode);
580 g_clear_error(&error);
582 __connman_storage_save_global(keyfile);
586 g_key_file_free(keyfile);
589 static bool connman_technology_load_offlinemode(void)
592 GError *error = NULL;
595 /* If there is a error, we enable offlinemode */
596 keyfile = __connman_storage_load_global();
600 offlinemode = g_key_file_get_boolean(keyfile, "global",
601 "OfflineMode", &error);
604 g_clear_error(&error);
607 g_key_file_free(keyfile);
612 #if defined TIZEN_EXT
613 static void append_devices(DBusMessageIter *iter, void *user_data)
617 struct connman_technology *technology = user_data;
619 for (list = technology->device_list; list; list = list->next) {
620 struct connman_device *device = list->data;
622 const char *str = connman_device_get_string(device, "Interface");
623 struct connman_network *network = connman_device_get_default_network(device);
624 struct connman_service *service = connman_service_lookup_from_network(network);
626 connman_dbus_dict_append_basic(iter, "Ifname",
627 DBUS_TYPE_STRING, &str);
629 val = connman_device_get_powered(device);
630 connman_dbus_dict_append_basic(iter, "Powered",
631 DBUS_TYPE_BOOLEAN, &val);
633 if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) ||
634 __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6))
639 connman_dbus_dict_append_basic(iter, "Connected",
640 DBUS_TYPE_BOOLEAN, &val);
642 str = connman_device_get_string(device, "Address");
643 connman_dbus_dict_append_basic(iter, "MAC.Address",
644 DBUS_TYPE_STRING, &str);
648 void __connman_technology_append_interfaces(DBusMessageIter *array,
649 enum connman_service_type type, const char *ifname)
652 struct connman_technology *technology = NULL;
654 for (list = technology_list; list; list = list->next) {
655 struct connman_technology *local_tech = list->data;
657 if (local_tech->type != type)
660 technology = local_tech;
667 for (list = technology->device_list; list; list = list->next) {
668 struct connman_device *device = list->data;
669 const char *str = connman_device_get_string(device, "Interface");
671 if (g_strcmp0(ifname, str) == 0)
674 dbus_message_iter_append_basic(array,
675 DBUS_TYPE_STRING, &str);
680 static void append_properties(DBusMessageIter *iter,
681 struct connman_technology *technology)
683 DBusMessageIter dict;
687 connman_dbus_dict_open(iter, &dict);
689 str = get_name(technology->type);
691 connman_dbus_dict_append_basic(&dict, "Name",
692 DBUS_TYPE_STRING, &str);
694 str = __connman_service_type2string(technology->type);
696 connman_dbus_dict_append_basic(&dict, "Type",
697 DBUS_TYPE_STRING, &str);
699 __sync_synchronize();
700 val = technology->enabled;
701 connman_dbus_dict_append_basic(&dict, "Powered",
705 val = technology->connected;
706 connman_dbus_dict_append_basic(&dict, "Connected",
710 val = technology->tethering;
711 connman_dbus_dict_append_basic(&dict, "Tethering",
715 if (technology->tethering_ident)
716 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
718 &technology->tethering_ident);
720 if (technology->tethering_passphrase)
721 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
723 &technology->tethering_passphrase);
725 #if defined TIZEN_EXT
726 connman_dbus_dict_append_basic(&dict, "MacPolicy",
728 &(technology->mac_policy));
730 connman_dbus_dict_append_basic(&dict, "PreassocMacPolicy",
732 &(technology->preassoc_mac_policy));
734 connman_dbus_dict_append_basic(&dict, "RandomMacLifetime",
736 &(technology->random_mac_lifetime));
738 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
739 connman_dbus_dict_append_dict(&dict, "Device.List",
740 append_devices, technology);
741 if (technology->regdom)
742 connman_dbus_dict_append_basic(&dict, "CountryCode",
744 &technology->regdom);
746 connman_dbus_dict_close(iter, &dict);
749 static void technology_added_signal(struct connman_technology *technology)
752 DBusMessageIter iter;
754 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
755 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
759 dbus_message_iter_init_append(signal, &iter);
760 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
762 append_properties(&iter, technology);
764 dbus_connection_send(connection, signal, NULL);
765 dbus_message_unref(signal);
768 static void technology_removed_signal(struct connman_technology *technology)
770 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
771 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
772 DBUS_TYPE_OBJECT_PATH, &technology->path,
776 static DBusMessage *get_properties(DBusConnection *conn,
777 DBusMessage *message, void *user_data)
779 struct connman_technology *technology = user_data;
781 DBusMessageIter iter;
783 reply = dbus_message_new_method_return(message);
787 dbus_message_iter_init_append(reply, &iter);
788 append_properties(&iter, technology);
793 void __connman_technology_list_struct(DBusMessageIter *array)
796 DBusMessageIter entry;
798 for (list = technology_list; list; list = list->next) {
799 struct connman_technology *technology = list->data;
801 if (!technology->path ||
802 (technology->rfkill_driven &&
803 technology->hardblocked))
806 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
808 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
810 append_properties(&entry, technology);
811 dbus_message_iter_close_container(array, &entry);
815 static gboolean technology_pending_reply(gpointer user_data)
817 struct connman_technology *technology = user_data;
820 /* Power request timed out, send ETIMEDOUT. */
821 if (technology->pending_reply) {
822 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
824 g_dbus_send_message(connection, reply);
826 dbus_message_unref(technology->pending_reply);
827 technology->pending_reply = NULL;
828 technology->pending_timeout = 0;
834 static int technology_affect_devices(struct connman_technology *technology,
837 int err = 0, err_dev;
840 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
842 __connman_technology_enabled(technology->type);
844 __connman_technology_disabled(technology->type);
848 #if defined TIZEN_EXT_WIFI_MESH
849 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
853 for (list = technology->device_list; list; list = list->next) {
854 struct connman_device *device = list->data;
857 err_dev = __connman_device_enable(device);
859 err_dev = __connman_device_disable(device);
861 if (err_dev < 0 && err_dev != -EALREADY)
868 static void powered_changed(struct connman_technology *technology)
872 if (!technology->dbus_registered)
875 if (technology->pending_reply) {
876 g_dbus_send_reply(connection,
877 technology->pending_reply, DBUS_TYPE_INVALID);
878 dbus_message_unref(technology->pending_reply);
879 technology->pending_reply = NULL;
881 g_source_remove(technology->pending_timeout);
882 technology->pending_timeout = 0;
885 __sync_synchronize();
886 enabled = technology->enabled;
887 #if defined TIZEN_EXT
888 DBG("ConnMan, Powered : %s, %s",
889 enabled ? "TRUE" : "FALSE",technology->path);
891 connman_dbus_property_changed_basic(technology->path,
892 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
893 DBUS_TYPE_BOOLEAN, &enabled);
896 static void enable_tethering(struct connman_technology *technology)
900 if (!connman_setting_get_bool("PersistentTetheringMode"))
903 ret = set_tethering(technology, true);
904 if (ret < 0 && ret != -EALREADY)
905 DBG("Cannot enable tethering yet for %s (%d/%s)",
906 get_name(technology->type),
907 -ret, strerror(-ret));
910 static int technology_enabled(struct connman_technology *technology)
912 __sync_synchronize();
913 if (technology->enabled)
916 technology->enabled = true;
918 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
919 struct connman_technology *p2p;
921 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
922 if (p2p && !p2p->enabled && p2p->enable_persistent)
923 technology_enabled(p2p);
926 if (technology->tethering_persistent)
927 enable_tethering(technology);
929 powered_changed(technology);
934 static int technology_enable(struct connman_technology *technology)
939 DBG("technology %p enable", technology);
941 __sync_synchronize();
943 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
944 struct connman_technology *wifi;
946 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
947 if (wifi && wifi->enabled)
948 return technology_enabled(technology);
952 if (technology->enabled)
955 if (technology->pending_reply)
958 if (connman_setting_get_bool("PersistentTetheringMode") &&
959 technology->tethering)
960 set_tethering(technology, true);
962 if (technology->rfkill_driven)
963 err = __connman_rfkill_block(technology->type, false);
965 err_dev = technology_affect_devices(technology, true);
967 if (!technology->rfkill_driven)
973 static int technology_disabled(struct connman_technology *technology)
975 __sync_synchronize();
976 if (!technology->enabled)
979 technology->enabled = false;
981 powered_changed(technology);
986 static int technology_disable(struct connman_technology *technology)
990 DBG("technology %p disable", technology);
992 __sync_synchronize();
994 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
995 technology->enable_persistent = false;
996 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
997 __connman_peer_disconnect_all();
998 return technology_disabled(technology);
999 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
1000 struct connman_technology *p2p;
1002 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1003 if (p2p && p2p->enabled) {
1004 p2p->enable_persistent = true;
1005 technology_disabled(p2p);
1009 if (!technology->enabled)
1012 if (technology->pending_reply)
1015 if (technology->tethering)
1016 set_tethering(technology, false);
1018 err = technology_affect_devices(technology, false);
1020 if (technology->rfkill_driven)
1021 err = __connman_rfkill_block(technology->type, true);
1026 static DBusMessage *set_powered(struct connman_technology *technology,
1027 DBusMessage *msg, bool powered)
1029 DBusMessage *reply = NULL;
1032 if (technology->rfkill_driven && technology->hardblocked) {
1038 err = technology_enable(technology);
1040 err = technology_disable(technology);
1042 if (err != -EBUSY) {
1043 technology->enable_persistent = powered;
1044 technology_save(technology);
1048 if (err == -EINPROGRESS) {
1049 technology->pending_reply = dbus_message_ref(msg);
1050 technology->pending_timeout = g_timeout_add_seconds(10,
1051 technology_pending_reply, technology);
1052 } else if (err == -EALREADY) {
1054 reply = __connman_error_already_enabled(msg);
1056 reply = __connman_error_already_disabled(msg);
1058 reply = __connman_error_failed(msg, -err);
1060 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1065 #if defined TIZEN_EXT
1066 int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
1068 static int bssid_len;
1069 static const char *def_ifname = "default";
1070 static GSList *bssid_list = NULL;
1072 const char *local_ifname = ifname;
1074 struct connman_bssid_pending *bssid_info;
1076 DBG("mode: %d, ifname: %s", mode, ifname);
1079 local_ifname = def_ifname;
1081 for (list = bssid_list; list; list = list->next) {
1082 bssid_info = list->data;
1084 if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
1090 if (mode == CHECK_BSSID) {
1097 if (mode == GET_BSSID && bssid) {
1099 memcpy(bssid, bssid_info->bssid, 6);
1105 if (mode == RESET_BSSID) {
1107 bssid_list = g_slist_remove(bssid_list, bssid_info);
1108 g_free(bssid_info->ifname);
1114 if (mode != SET_BSSID || !bssid) {
1115 DBG("Invalid parameter");
1120 bssid_list = g_slist_remove(bssid_list, bssid_info);
1121 g_free(bssid_info->ifname);
1125 bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
1127 DBG("Failed to allocate memory");
1131 unsigned char *bssid_data = bssid_info->bssid;
1133 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1134 &bssid_data[0], &bssid_data[1], &bssid_data[2],
1135 &bssid_data[3], &bssid_data[4], &bssid_data[5]);
1136 if (bssid_len != 6) {
1137 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
1142 DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
1144 bssid_data[0], bssid_data[1], bssid_data[2],
1145 bssid_data[3], bssid_data[4], bssid_data[5],
1148 bssid_info->ifname = g_strdup(ifname);
1149 bssid_list = g_slist_prepend(bssid_list, bssid_info);
1154 void connman_technology_mac_policy_notify(struct connman_technology *technology,
1155 unsigned int policy)
1157 DBG("Mac polict set to %u", policy);
1159 technology->mac_policy = policy;
1160 technology_save(technology);
1163 void __connman_technology_notify_mac_policy_by_device(struct connman_device *device,
1164 int result, unsigned int policy)
1166 struct connman_technology *technology;
1167 enum connman_service_type type;
1169 type = __connman_device_get_service_type(device);
1170 technology = technology_find(type);
1175 connman_technology_mac_policy_notify(technology, policy);
1178 static DBusMessage *set_mac_policy(struct connman_technology *technology,
1179 DBusMessage *msg, unsigned int policy)
1181 DBusMessage *reply = NULL;
1183 unsigned int last_policy = technology->mac_policy;
1185 if (technology->rfkill_driven && technology->hardblocked) {
1190 for (GSList *list = technology->device_list; list; list = list->next) {
1191 struct connman_device *device = list->data;
1193 err = connman_device_set_mac_policy(device, policy);
1200 if (err != -EACCES && err != -EOPNOTSUPP) {
1201 for (GSList *list = technology->device_list; list; list = list->next) {
1202 struct connman_device *device = list->data;
1204 connman_device_set_mac_policy(device, last_policy);
1208 reply = __connman_error_failed(msg, -err);
1210 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1216 void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology,
1217 unsigned int policy)
1219 DBG("Preassoc mac polict set to %u", policy);
1221 technology->preassoc_mac_policy = policy;
1222 technology_save(technology);
1225 void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device,
1226 int result, unsigned int policy)
1228 struct connman_technology *technology;
1229 enum connman_service_type type;
1231 type = __connman_device_get_service_type(device);
1232 technology = technology_find(type);
1237 connman_technology_preassoc_mac_policy_notify(technology, policy);
1240 static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology,
1241 DBusMessage *msg, unsigned int policy)
1243 DBusMessage *reply = NULL;
1245 unsigned int last_policy = technology->preassoc_mac_policy;
1247 if (technology->rfkill_driven && technology->hardblocked) {
1252 for (GSList *list = technology->device_list; list; list = list->next) {
1253 struct connman_device *device = list->data;
1255 err = connman_device_set_preassoc_mac_policy(device, policy);
1262 if (err != -EACCES && err != -EOPNOTSUPP) {
1263 for (GSList *list = technology->device_list; list; list = list->next) {
1264 struct connman_device *device = list->data;
1266 connman_device_set_preassoc_mac_policy(device, last_policy);
1270 reply = __connman_error_failed(msg, -err);
1272 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1278 void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology,
1279 unsigned int lifetime)
1281 DBG("Random mac lifetime set to %u", lifetime);
1283 technology->random_mac_lifetime = lifetime;
1284 technology_save(technology);
1287 void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device,
1288 int result, unsigned int lifetime)
1290 struct connman_technology *technology;
1291 enum connman_service_type type;
1293 type = __connman_device_get_service_type(device);
1294 technology = technology_find(type);
1299 connman_technology_random_mac_lifetime_notify(technology, lifetime);
1302 static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology,
1303 DBusMessage *msg, unsigned int lifetime)
1305 DBusMessage *reply = NULL;
1307 unsigned int last_lifetime = technology->random_mac_lifetime;
1309 if (technology->rfkill_driven && technology->hardblocked) {
1314 for (GSList *list = technology->device_list; list; list = list->next) {
1315 struct connman_device *device = list->data;
1317 err = connman_device_set_random_mac_lifetime(device, lifetime);
1322 if (err != -EACCES && err != -EOPNOTSUPP) {
1323 for (GSList *list = technology->device_list; list; list = list->next) {
1324 struct connman_device *device = list->data;
1326 connman_device_set_random_mac_lifetime(device, last_lifetime);
1330 reply = __connman_error_failed(msg, -err);
1332 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1339 static DBusMessage *set_property(DBusConnection *conn,
1340 DBusMessage *msg, void *data)
1342 struct connman_technology *technology = data;
1343 DBusMessageIter iter, value;
1347 DBG("conn %p", conn);
1349 if (!dbus_message_iter_init(msg, &iter))
1350 return __connman_error_invalid_arguments(msg);
1352 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1353 return __connman_error_invalid_arguments(msg);
1355 dbus_message_iter_get_basic(&iter, &name);
1356 dbus_message_iter_next(&iter);
1358 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1359 return __connman_error_invalid_arguments(msg);
1361 dbus_message_iter_recurse(&iter, &value);
1363 type = dbus_message_iter_get_arg_type(&value);
1365 DBG("property %s", name);
1367 if (g_str_equal(name, "Tethering")) {
1368 dbus_bool_t tethering;
1371 if (type != DBUS_TYPE_BOOLEAN)
1372 return __connman_error_invalid_arguments(msg);
1374 if (!connman_technology_is_tethering_allowed(technology->type)) {
1375 DBG("%s tethering not allowed by config file",
1376 __connman_service_type2string(technology->type));
1377 return __connman_error_not_supported(msg);
1380 dbus_message_iter_get_basic(&value, &tethering);
1382 if (technology->tethering == tethering) {
1384 return __connman_error_already_disabled(msg);
1386 return __connman_error_already_enabled(msg);
1389 err = set_tethering(technology, tethering);
1391 return __connman_error_failed(msg, -err);
1393 technology->tethering_persistent = tethering;
1395 technology_save(technology);
1397 } else if (g_str_equal(name, "TetheringIdentifier")) {
1400 dbus_message_iter_get_basic(&value, &str);
1402 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1403 return __connman_error_not_supported(msg);
1405 if (strlen(str) < 1 || strlen(str) > 32)
1406 return __connman_error_invalid_arguments(msg);
1408 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1409 g_free(technology->tethering_ident);
1410 technology->tethering_ident = g_strdup(str);
1411 technology_save(technology);
1413 connman_dbus_property_changed_basic(technology->path,
1414 CONNMAN_TECHNOLOGY_INTERFACE,
1415 "TetheringIdentifier",
1417 &technology->tethering_ident);
1419 } else if (g_str_equal(name, "TetheringPassphrase")) {
1422 dbus_message_iter_get_basic(&value, &str);
1424 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1425 return __connman_error_not_supported(msg);
1427 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1430 return __connman_error_passphrase_required(msg);
1432 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1433 g_free(technology->tethering_passphrase);
1434 technology->tethering_passphrase = g_strdup(str);
1435 technology_save(technology);
1437 connman_dbus_property_changed_basic(technology->path,
1438 CONNMAN_TECHNOLOGY_INTERFACE,
1439 "TetheringPassphrase",
1441 &technology->tethering_passphrase);
1443 } else if (g_str_equal(name, "Powered")) {
1446 if (type != DBUS_TYPE_BOOLEAN)
1447 return __connman_error_invalid_arguments(msg);
1449 dbus_message_iter_get_basic(&value, &enable);
1451 return set_powered(technology, msg, enable);
1452 #if defined TIZEN_EXT
1453 } else if (g_str_equal(name, "SetBSSID")) {
1456 if (type != DBUS_TYPE_STRING)
1457 return __connman_error_invalid_arguments(msg);
1459 dbus_message_iter_get_basic(&value, &key);
1460 DBG("BSSID %s", key);
1461 set_connman_bssid(SET_BSSID, key, NULL);
1462 } else if (g_str_equal(name, "MacPolicy")) {
1463 dbus_uint32_t mac_policy;
1465 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1466 return __connman_error_not_supported(msg);
1468 if (type != DBUS_TYPE_UINT32)
1469 return __connman_error_invalid_arguments(msg);
1471 dbus_message_iter_get_basic(&value, &mac_policy);
1473 if (mac_policy <= 2)
1474 return set_mac_policy(technology, msg, mac_policy);
1476 return __connman_error_invalid_arguments(msg);
1478 } else if (g_str_equal(name, "PreassocMacPolicy")) {
1479 dbus_uint32_t preassoc_mac_policy;
1481 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1482 return __connman_error_not_supported(msg);
1484 if (type != DBUS_TYPE_UINT32)
1485 return __connman_error_invalid_arguments(msg);
1487 dbus_message_iter_get_basic(&value, &preassoc_mac_policy);
1489 if (preassoc_mac_policy <= 2)
1490 return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy);
1492 return __connman_error_invalid_arguments(msg);
1494 } else if (g_str_equal(name, "RandomMacLifetime")) {
1495 dbus_uint32_t random_mac_lifetime;
1497 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1498 return __connman_error_not_supported(msg);
1500 if (type != DBUS_TYPE_UINT32)
1501 return __connman_error_invalid_arguments(msg);
1503 dbus_message_iter_get_basic(&value, &random_mac_lifetime);
1505 if (random_mac_lifetime > 0)
1506 return set_random_mac_lifetime(technology, msg, random_mac_lifetime);
1508 return __connman_error_invalid_arguments(msg);
1510 } else if (g_str_equal(name, "CountryCode")) {
1513 dbus_message_iter_get_basic(&value, &str);
1514 DBG("country code %s", str);
1515 connman_technology_set_regdom(str);
1518 return __connman_error_invalid_property(msg);
1520 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1523 static void reply_scan_pending(struct connman_technology *technology, int err)
1527 DBG("technology %p err %d", technology, err);
1529 while (technology->scan_pending) {
1530 #if defined TIZEN_EXT
1531 struct connman_scan_pending *pending_data = technology->scan_pending->data;
1532 DBusMessage *msg = pending_data->msg;
1534 DBusMessage *msg = technology->scan_pending->data;
1536 DBG("reply to %s", dbus_message_get_sender(msg));
1539 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1541 reply = __connman_error_failed(msg, -err);
1542 g_dbus_send_message(connection, reply);
1543 dbus_message_unref(msg);
1545 technology->scan_pending =
1546 g_slist_delete_link(technology->scan_pending,
1547 technology->scan_pending);
1548 #if defined TIZEN_EXT
1549 g_free(pending_data->ifname);
1550 g_free(pending_data);
1555 #if defined TIZEN_EXT
1556 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1559 DBusMessage *signal;
1560 DBusMessageIter iter;
1561 dbus_bool_t result = FALSE;
1563 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1564 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1568 dbus_message_iter_init_append(signal, &iter);
1570 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1572 connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
1574 result = dbus_connection_send(connection, signal, NULL);
1575 dbus_message_unref(signal);
1577 DBG("Successfuly sent signal");
1582 void __connman_technology_notify_scan_done(const char *ifname, int val)
1585 DBusMessage *signal;
1586 DBusMessageIter iter;
1588 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1589 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1593 dbus_message_iter_init_append(signal, &iter);
1595 connman_dbus_property_append_basic(&iter, ifname,
1596 DBUS_TYPE_INT32, &val);
1598 connman_dbus_property_append_basic(&iter, "",
1599 DBUS_TYPE_INT32, &val);
1601 dbus_connection_send(connection, signal, NULL);
1602 dbus_message_unref(signal);
1604 DBG("Successfuly sent ScanDone signal");
1607 static void reply_scan_pending_device(
1608 struct connman_technology *technology, const char *ifname, int count)
1612 dbus_bool_t status = 0;
1613 connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
1615 DBG("technology %p ifname %s count %d", technology, ifname, count);
1617 list = technology->scan_pending;
1620 struct connman_scan_pending *pending_data = list->data;
1621 DBusMessage *msg = pending_data->msg;
1624 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1625 scan_type = pending_data->scan_type;
1627 if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
1630 scan_type = pending_data->scan_type;
1632 DBG("reply to %s", dbus_message_get_sender(msg));
1633 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1635 g_dbus_send_message(connection, reply);
1636 dbus_message_unref(msg);
1638 technology->scan_pending =
1639 g_slist_remove(technology->scan_pending, pending_data);
1641 g_free(pending_data->ifname);
1642 g_free(pending_data);
1645 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1646 scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1648 __connman_technology_notify_scan_changed(ifname, &status);
1649 __connman_technology_notify_scan_done(ifname, scan_type);
1652 static void __connman_technology_notify_device_detected(
1653 struct connman_technology *technology, const char *ifname, bool val)
1656 DBusMessage *signal;
1657 DBusMessageIter iter;
1658 dbus_bool_t detected = val;
1663 signal = dbus_message_new_signal(technology->path,
1664 CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
1668 dbus_message_iter_init_append(signal, &iter);
1669 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
1670 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
1672 dbus_connection_send(connection, signal, NULL);
1673 dbus_message_unref(signal);
1675 DBG("Successfuly sent DeviceDetected signal");
1678 void __connman_technology_notify_roaming_state(const char *ifname,
1679 const char *state, const char *cur_bssid, const char *dst_bssid)
1682 DBusMessage *signal;
1683 DBusMessageIter array, dict;
1685 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1686 CONNMAN_MANAGER_INTERFACE, "RoamingStateChanged");
1690 dbus_message_iter_init_append(signal, &array);
1692 connman_dbus_dict_open(&array, &dict);
1695 connman_dbus_dict_append_basic(&dict, "Interface",
1696 DBUS_TYPE_STRING, &ifname);
1698 connman_dbus_dict_append_basic(&dict, "State",
1699 DBUS_TYPE_STRING, &state);
1701 connman_dbus_dict_append_basic(&dict, "ConnectedBSSID",
1702 DBUS_TYPE_STRING, &cur_bssid);
1704 connman_dbus_dict_append_basic(&dict, "TargetBSSID",
1705 DBUS_TYPE_STRING, &dst_bssid);
1707 connman_dbus_dict_close(&array, &dict);
1709 dbus_connection_send(connection, signal, NULL);
1710 dbus_message_unref(signal);
1712 DBG("Successfully sent Roaming State Changed signal");
1716 void __connman_technology_scan_started(struct connman_device *device)
1718 DBG("device %p", device);
1719 #if defined TIZEN_EXT
1720 dbus_bool_t status = 1;
1721 const char *ifname = connman_device_get_string(device, "Interface");
1723 __connman_technology_notify_scan_changed(ifname, &status);
1727 void __connman_technology_scan_stopped(struct connman_device *device,
1728 enum connman_service_type type)
1731 struct connman_technology *technology;
1734 technology = technology_find(type);
1736 DBG("technology %p device %p", technology, device);
1741 for (list = technology->device_list; list; list = list->next) {
1742 struct connman_device *other_device = list->data;
1744 if (device == other_device)
1747 if (connman_device_get_scanning(other_device, type))
1751 #if defined TIZEN_EXT
1752 const char *ifname = connman_device_get_string(device, "Interface");
1753 reply_scan_pending_device(technology, ifname, count);
1758 reply_scan_pending(technology, 0);
1762 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1763 int result, const char *alpha2)
1765 bool regdom_set = false;
1766 struct connman_technology *technology;
1767 enum connman_service_type type;
1768 GSList *tech_drivers;
1770 type = __connman_device_get_service_type(device);
1771 technology = technology_find(type);
1778 for (tech_drivers = technology->driver_list;
1780 tech_drivers = g_slist_next(tech_drivers)) {
1781 struct connman_technology_driver *driver =
1784 if (driver->set_regdom) {
1785 driver->set_regdom(technology, alpha2);
1795 connman_technology_regdom_notify(technology, alpha2);
1798 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1800 struct connman_technology *technology = data;
1803 DBG("technology %p request from %s", technology,
1804 dbus_message_get_sender(msg));
1806 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1807 !technology->enabled)
1808 return __connman_error_permission_denied(msg);
1810 #if !defined TIZEN_EXT
1811 dbus_message_ref(msg);
1812 technology->scan_pending =
1813 g_slist_prepend(technology->scan_pending, msg);
1816 err = __connman_device_request_scan_full(technology->type);
1818 #if defined TIZEN_EXT
1819 return __connman_error_failed(msg, -err);
1821 reply_scan_pending(technology, err);
1824 #if defined TIZEN_EXT
1825 struct connman_scan_pending *pending_data =
1826 g_try_malloc0(sizeof(struct connman_scan_pending));
1828 return __connman_error_failed(msg, ENOMEM);
1830 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1831 DBG("scan_type %d", pending_data->scan_type);
1833 pending_data->msg = dbus_message_ref(msg);
1835 technology->scan_pending =
1836 g_slist_prepend(technology->scan_pending, pending_data);
1841 #if defined TIZEN_EXT
1842 static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
1844 struct connman_technology *technology = data;
1845 DBusMessageIter iter;
1849 DBG("technology %p request from %s", technology,
1850 dbus_message_get_sender(msg));
1852 if (!dbus_message_iter_init(msg, &iter))
1853 return __connman_error_invalid_arguments(msg);
1855 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1856 return __connman_error_invalid_arguments(msg);
1858 dbus_message_iter_get_basic(&iter, &ifname);
1859 DBG("Interface name %s", ifname);
1861 if (!ifname || strlen(ifname) == 0)
1862 return __connman_error_invalid_arguments(msg);
1864 err = connman_device_request_device_scan(technology->type, ifname, true);
1866 return __connman_error_failed(msg, -err);
1868 struct connman_scan_pending *pending_data =
1869 g_try_malloc0(sizeof(struct connman_scan_pending));
1871 return __connman_error_failed(msg, ENOMEM);
1873 pending_data->ifname = g_strdup(ifname);
1874 if (pending_data->ifname == NULL) {
1875 g_free(pending_data);
1876 return __connman_error_failed(msg, ENOMEM);
1879 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1880 DBG("scan_type %d", pending_data->scan_type);
1882 pending_data->msg = dbus_message_ref(msg);
1884 technology->scan_pending =
1885 g_slist_prepend(technology->scan_pending, pending_data);
1890 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1892 struct connman_technology *technology = data;
1893 GSList *specific_scan_list = NULL;
1895 const char *name = NULL;
1896 const char *freq = NULL;
1897 const char *ifname = NULL;
1898 DBusMessageIter iter, dict;
1901 DBG("technology %p request from %s", technology,
1902 dbus_message_get_sender(msg));
1904 if (!dbus_message_iter_init(msg, &iter))
1905 return __connman_error_invalid_arguments(msg);
1907 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1908 return __connman_error_invalid_arguments(msg);
1910 dbus_message_iter_recurse(&iter, &dict);
1911 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1912 DBusMessageIter entry, value2;
1916 dbus_message_iter_recurse(&dict, &entry);
1917 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1918 g_slist_free_full(specific_scan_list, g_free);
1919 return __connman_error_invalid_arguments(msg);
1922 dbus_message_iter_get_basic(&entry, &key);
1923 dbus_message_iter_next(&entry);
1925 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1926 g_slist_free_full(specific_scan_list, g_free);
1927 return __connman_error_invalid_arguments(msg);
1930 dbus_message_iter_recurse(&entry, &value2);
1931 type = dbus_message_iter_get_arg_type(&value2);
1932 if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
1934 dbus_message_iter_get_basic(&value2, &ifname);
1935 DBG("ifname %s", ifname);
1936 } else if (g_str_equal(key, "SSID")) {
1937 if (type != DBUS_TYPE_STRING) {
1938 g_slist_free_full(specific_scan_list, g_free);
1939 return __connman_error_invalid_arguments(msg);
1942 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1943 dbus_message_iter_get_basic(&value2, &name);
1944 DBG("name %s", name);
1945 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1946 } else if (g_str_equal(key, "Frequency")) {
1947 if (type != DBUS_TYPE_STRING) {
1948 g_slist_free_full(specific_scan_list, g_free);
1949 return __connman_error_invalid_arguments(msg);
1952 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1953 dbus_message_iter_get_basic(&value2, &freq);
1954 DBG("freq %s", freq);
1955 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1956 } else if (g_str_equal(key, "SSID_Mixed")) {
1957 if (type != DBUS_TYPE_STRING) {
1958 g_slist_free_full(specific_scan_list, g_free);
1959 return __connman_error_invalid_arguments(msg);
1962 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1963 dbus_message_iter_get_basic(&value2, &name);
1965 connman_multi_scan_ap_s *ap =
1966 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1968 g_strlcpy(ap->str, name, strlen(name) + 1);
1970 specific_scan_list = g_slist_append(specific_scan_list, ap);
1972 DBG("Failed to allocate memory");
1974 } else if (g_str_equal(key, "Frequency_Mixed")) {
1975 if (type != DBUS_TYPE_STRING) {
1976 g_slist_free_full(specific_scan_list, g_free);
1977 return __connman_error_invalid_arguments(msg);
1980 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1981 dbus_message_iter_get_basic(&value2, &freq);
1983 connman_multi_scan_ap_s *ap =
1984 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1986 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1988 specific_scan_list = g_slist_append(specific_scan_list, ap);
1990 DBG("Failed to allocate memory");
1992 dbus_message_iter_next(&dict);
1995 err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
1997 return __connman_error_failed(msg, -err);
1999 guint list_size = g_slist_length(specific_scan_list);
2001 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
2002 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
2003 g_slist_free_full(specific_scan_list, g_free);
2005 struct connman_scan_pending *pending_data =
2006 g_try_malloc0(sizeof(struct connman_scan_pending));
2008 return __connman_error_failed(msg, ENOMEM);
2011 pending_data->ifname = g_strdup(ifname);
2012 if (pending_data->ifname == NULL) {
2013 g_free(pending_data);
2014 return __connman_error_failed(msg, ENOMEM);
2019 pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
2021 pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
2022 DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
2024 pending_data->msg = dbus_message_ref(msg);
2026 technology->scan_pending =
2027 g_slist_prepend(technology->scan_pending, pending_data);
2032 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
2035 DBusMessageIter iter, dict;
2037 struct connman_technology *technology = data;
2038 dbus_bool_t supported = false;
2039 const char *ifname = NULL;
2041 DBG("technology %p", technology);
2043 reply = dbus_message_new_method_return(msg);
2047 dbus_message_iter_init_append(reply, &iter);
2048 connman_dbus_dict_open(&iter, &dict);
2050 for (list = technology->device_list; list; list = list->next) {
2051 struct connman_device *device = list->data;
2053 supported = connman_device_get_wifi_5ghz_supported(device);
2054 ifname = connman_device_get_string(device, "Interface");
2056 DBG("ifname %s supported : %d", ifname, supported);
2057 connman_dbus_dict_append_basic(&dict, ifname,
2062 connman_dbus_dict_close(&iter, &dict);
2067 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
2070 DBusMessageIter iter, dict;
2072 struct connman_technology *technology = data;
2073 dbus_bool_t scanning = false;
2074 const char *ifname = NULL;
2076 DBG("technology %p", technology);
2078 reply = dbus_message_new_method_return(msg);
2082 dbus_message_iter_init_append(reply, &iter);
2083 connman_dbus_dict_open(&iter, &dict);
2085 for (list = technology->device_list; list; list = list->next) {
2086 struct connman_device *device = list->data;
2088 scanning = connman_device_get_scanning(device, technology->type);
2089 ifname = connman_device_get_string(device, "Interface");
2091 DBG("ifname %s scanning : %d", ifname, scanning);
2092 connman_dbus_dict_append_basic(&dict, ifname,
2097 connman_dbus_dict_close(&iter, &dict);
2102 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
2105 DBusMessageIter iter, dict;
2107 struct connman_technology *technology = data;
2108 dbus_int32_t max_scan_ssids = 0;
2109 const char *ifname = NULL;
2111 DBG("technology %p", technology);
2113 reply = dbus_message_new_method_return(msg);
2117 dbus_message_iter_init_append(reply, &iter);
2118 connman_dbus_dict_open(&iter, &dict);
2120 for (list = technology->device_list; list; list = list->next) {
2121 struct connman_device *device = list->data;
2123 max_scan_ssids = connman_device_get_max_scan_ssids(device);
2124 ifname = connman_device_get_string(device, "Interface");
2126 DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
2127 connman_dbus_dict_append_basic(&dict, ifname,
2132 connman_dbus_dict_close(&iter, &dict);
2137 static int technology_enable_device(struct connman_technology *technology,
2138 bool enable_device, const char *ifname, struct connman_device **device_out)
2143 for (list = technology->device_list; list; list = list->next) {
2144 struct connman_device *device = list->data;
2145 const char *str = connman_device_get_string(device, "Interface");
2147 if (g_strcmp0(str, ifname) != 0)
2151 err = __connman_device_enable(device);
2153 err = __connman_device_disable(device);
2155 *device_out = device;
2162 static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
2163 DBusMessage *msg, bool powered, const char *ifname)
2165 DBusMessage *reply = NULL;
2166 struct connman_device *device = NULL;
2169 err = technology_enable_device(technology, powered, ifname, &device);
2171 if (err == -EINPROGRESS) {
2173 connman_device_set_pending_reply(device, msg);
2175 } else if (err == -EALREADY) {
2177 reply = __connman_error_already_enabled(msg);
2179 reply = __connman_error_already_disabled(msg);
2181 reply = __connman_error_failed(msg, -err);
2183 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2188 static DBusMessage *set_device_power(DBusConnection *conn,
2189 DBusMessage *msg, void *data)
2191 struct connman_technology *technology = data;
2192 DBusMessageIter iter;
2197 DBG("conn %p", conn);
2199 if (!dbus_message_iter_init(msg, &iter))
2200 return __connman_error_invalid_arguments(msg);
2202 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2203 return __connman_error_invalid_arguments(msg);
2205 dbus_message_iter_get_basic(&iter, &name);
2206 dbus_message_iter_next(&iter);
2208 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
2209 return __connman_error_invalid_arguments(msg);
2211 DBG("interface name %s", name);
2215 if (len + 1 > IFNAMSIZ)
2216 return __connman_error_invalid_arguments(msg);
2218 dbus_message_iter_get_basic(&iter, &enable);
2219 DBG("powered %s", enable ? "TRUE" : "FALSE");
2221 return technology_set_device_powered(technology, msg, enable, name);
2224 static DBusMessage *set_bssid(DBusConnection *conn,
2225 DBusMessage *msg, void *data)
2227 DBusMessageIter iter;
2231 DBG("conn %p", conn);
2233 if (!dbus_message_iter_init(msg, &iter))
2234 return __connman_error_invalid_arguments(msg);
2236 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2237 return __connman_error_invalid_arguments(msg);
2239 dbus_message_iter_get_basic(&iter, &name);
2240 dbus_message_iter_next(&iter);
2242 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2243 return __connman_error_invalid_arguments(msg);
2245 dbus_message_iter_get_basic(&iter, &bssid);
2247 DBG("interface name %s bssid %s", name, bssid);
2251 if (len + 1 > IFNAMSIZ)
2252 return __connman_error_invalid_arguments(msg);
2254 set_connman_bssid(SET_BSSID, bssid, name);
2256 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2258 static struct connman_technology *technology_get(enum connman_service_type type);
2260 void technology_save_device(struct connman_device *device)
2262 struct connman_technology *technology;
2263 enum connman_service_type type;
2265 type = __connman_device_get_service_type(device);
2267 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2270 technology = technology_get(type);
2274 if (!g_slist_find(technology->device_list, device))
2279 const char *name = get_name(technology->type);
2281 DBG("technology %p type %d name %s", technology, technology->type,
2286 keyfile = __connman_storage_load_global();
2288 keyfile = g_key_file_new();
2290 identifier = g_strdup_printf("%s", name);
2294 GSList *list = NULL;
2295 gchar **ifname_list = NULL;
2296 guint dev_count = g_slist_length(technology->device_list);
2298 if (dev_count >= 1) {
2299 GString *ifname_str = g_string_new(NULL);
2302 for (list = technology->device_list; list; list = list->next) {
2303 struct connman_device *device = list->data;
2305 if (connman_device_get_powered(device)) {
2306 const char *ifname = connman_device_get_string(device, "Interface");
2308 if (ifname_str->len > 0)
2309 g_string_append_printf(ifname_str, " %s", ifname);
2311 g_string_append(ifname_str, ifname);
2315 if (ifname_str->len > 0) {
2316 ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
2317 dev_count = g_strv_length(ifname_list);
2318 g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
2319 (const gchar **) ifname_list, dev_count);
2321 technology->enable_persistent = true;
2323 g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
2324 technology->enable_persistent = false;
2327 g_strfreev(ifname_list);
2328 g_string_free(ifname_str, TRUE);
2332 g_key_file_set_boolean(keyfile, identifier, "Enable",
2333 technology->enable_persistent);
2335 g_key_file_set_boolean(keyfile, identifier, "Tethering",
2336 technology->tethering_persistent);
2338 if (technology->tethering_ident)
2339 g_key_file_set_string(keyfile, identifier,
2340 "Tethering.Identifier",
2341 technology->tethering_ident);
2343 if (technology->tethering_passphrase)
2344 g_key_file_set_string(keyfile, identifier,
2345 "Tethering.Passphrase",
2346 technology->tethering_passphrase);
2351 __connman_storage_save_global(keyfile);
2353 g_key_file_free(keyfile);
2357 #if defined TIZEN_EXT_WIFI_MESH
2358 bool __connman_technology_get_connected(enum connman_service_type type)
2360 struct connman_technology *technology;
2362 technology = technology_find(type);
2367 return technology->connected;
2370 void __connman_technology_mesh_interface_create_finished(
2371 enum connman_service_type type, bool success,
2375 struct connman_technology *technology;
2377 technology = technology_find(type);
2379 DBG("technology %p success %d", technology, success);
2384 msg = technology->mesh_dbus_msg;
2386 DBG("No pending dbus message");
2391 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2392 __connman_device_request_scan(technology->type);
2394 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
2395 ".MeshInterfaceAddFailed", "%s", error);
2396 g_dbus_send_message(connection, reply);
2397 dbus_message_unref(msg);
2398 technology->mesh_dbus_msg = NULL;
2401 void __connman_technology_mesh_interface_remove_finished(
2402 enum connman_service_type type, bool success)
2405 struct connman_technology *technology;
2407 technology = technology_find(type);
2409 DBG("technology %p success %d", technology, success);
2411 if (!technology || !technology->mesh_dbus_msg)
2414 msg = technology->mesh_dbus_msg;
2416 DBG("No pending dbus message");
2421 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2423 reply = __connman_error_failed(msg, EINVAL);
2424 g_dbus_send_message(connection, reply);
2425 dbus_message_unref(msg);
2426 technology->mesh_dbus_msg = NULL;
2429 void __connman_technology_notify_abort_scan(enum connman_service_type type,
2433 struct connman_technology *technology;
2435 technology = technology_find(type);
2437 DBG("technology %p result %d", technology, result);
2439 if (!technology || !technology->mesh_dbus_msg)
2442 msg = technology->mesh_dbus_msg;
2444 DBG("No pending dbus message");
2449 reply = __connman_error_scan_abort_failed(msg);
2451 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2453 g_dbus_send_message(connection, reply);
2454 dbus_message_unref(msg);
2455 technology->mesh_dbus_msg = NULL;
2458 static DBusMessage *mesh_commands(DBusConnection *conn,
2459 DBusMessage *msg, void *data)
2461 struct connman_technology *technology = data;
2462 DBusMessageIter iter, value, dict;
2463 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
2466 DBG("conn %p", conn);
2468 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
2469 return __connman_error_invalid_arguments(msg);
2471 if (!dbus_message_iter_init(msg, &iter))
2472 return __connman_error_invalid_arguments(msg);
2474 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2475 return __connman_error_invalid_arguments(msg);
2477 dbus_message_iter_get_basic(&iter, &cmd);
2478 dbus_message_iter_next(&iter);
2480 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
2481 return __connman_error_invalid_arguments(msg);
2483 dbus_message_iter_recurse(&iter, &value);
2485 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
2486 return __connman_error_invalid_arguments(msg);
2488 DBG("Mesh Command %s", cmd);
2489 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
2490 dbus_message_iter_recurse(&value, &dict);
2491 const char *bridge_ifname = NULL;
2492 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2493 DBusMessageIter entry, value2;
2497 dbus_message_iter_recurse(&dict, &entry);
2499 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2500 return __connman_error_invalid_arguments(msg);
2502 dbus_message_iter_get_basic(&entry, &key);
2503 dbus_message_iter_next(&entry);
2505 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2506 return __connman_error_invalid_arguments(msg);
2508 dbus_message_iter_recurse(&entry, &value2);
2510 type = dbus_message_iter_get_arg_type(&value2);
2512 if (g_str_equal(key, "Ifname")) {
2513 if (type != DBUS_TYPE_STRING)
2514 return __connman_error_invalid_arguments(msg);
2516 dbus_message_iter_get_basic(&value2, &ifname);
2517 } else if (g_str_equal(key, "ParentIfname")) {
2518 if (type != DBUS_TYPE_STRING)
2519 return __connman_error_invalid_arguments(msg);
2521 dbus_message_iter_get_basic(&value2, &parent_ifname);
2522 } else if (g_str_equal(key, "BridgeIfname")) {
2523 if (type != DBUS_TYPE_STRING)
2524 return __connman_error_invalid_arguments(msg);
2526 dbus_message_iter_get_basic(&value2, &bridge_ifname);
2528 dbus_message_iter_next(&dict);
2530 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
2531 bridge_ifname ? bridge_ifname : "NULL");
2532 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
2536 DBG("Failed to add virtual mesh interface");
2537 return __connman_error_failed(msg, -err);
2540 DBG("Successfully added virtual mesh interface");
2542 dbus_message_ref(msg);
2543 technology->mesh_dbus_msg = msg;
2545 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
2546 dbus_message_iter_recurse(&value, &dict);
2547 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2548 DBusMessageIter entry, value2;
2552 dbus_message_iter_recurse(&dict, &entry);
2554 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2555 return __connman_error_invalid_arguments(msg);
2557 dbus_message_iter_get_basic(&entry, &key);
2558 dbus_message_iter_next(&entry);
2560 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2561 return __connman_error_invalid_arguments(msg);
2563 dbus_message_iter_recurse(&entry, &value2);
2565 type = dbus_message_iter_get_arg_type(&value2);
2567 if (g_str_equal(key, "Ifname")) {
2568 if (type != DBUS_TYPE_STRING)
2569 return __connman_error_invalid_arguments(msg);
2571 dbus_message_iter_get_basic(&value2, &ifname);
2573 dbus_message_iter_next(&dict);
2575 DBG("Mesh Ifname %s", ifname);
2576 err = __connman_mesh_remove_virtual_interface(ifname);
2579 DBG("Failed to remove virtual mesh interface");
2580 return __connman_error_failed(msg, -err);
2583 DBG("Successfully removed virtual mesh interface");
2585 dbus_message_ref(msg);
2586 technology->mesh_dbus_msg = msg;
2588 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
2589 struct connman_mesh *connman_mesh;
2590 const char *name = NULL;
2591 const char *sec_type = NULL;
2592 const char *mesh_ifname = NULL;
2593 char *identifier, *group, *address;
2594 unsigned int freq = 0;
2595 unsigned int ieee80211w = 0;
2598 dbus_message_iter_recurse(&value, &dict);
2599 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2600 DBusMessageIter entry, value2;
2604 dbus_message_iter_recurse(&dict, &entry);
2606 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2607 return __connman_error_invalid_arguments(msg);
2609 dbus_message_iter_get_basic(&entry, &key);
2610 dbus_message_iter_next(&entry);
2612 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2613 return __connman_error_invalid_arguments(msg);
2615 dbus_message_iter_recurse(&entry, &value2);
2617 type = dbus_message_iter_get_arg_type(&value2);
2619 if (g_str_equal(key, "Name")) {
2620 if (type != DBUS_TYPE_STRING)
2621 return __connman_error_invalid_arguments(msg);
2623 dbus_message_iter_get_basic(&value2, &name);
2624 } else if (g_str_equal(key, "Frequency")) {
2625 if (type != DBUS_TYPE_UINT16)
2626 return __connman_error_invalid_arguments(msg);
2628 dbus_message_iter_get_basic(&value2, &freq);
2629 } else if (g_str_equal(key, "Security")) {
2630 if (type != DBUS_TYPE_STRING)
2631 return __connman_error_invalid_arguments(msg);
2633 dbus_message_iter_get_basic(&value2, &sec_type);
2634 } else if (g_str_equal(key, "Pmf")) {
2635 if (type != DBUS_TYPE_UINT16)
2636 return __connman_error_invalid_arguments(msg);
2638 dbus_message_iter_get_basic(&value2, &ieee80211w);
2640 dbus_message_iter_next(&dict);
2643 if (name == NULL || sec_type == NULL || freq == 0)
2644 return __connman_error_invalid_arguments(msg);
2646 DBG("Name %s Frequency %d Security type %s Pmf %u",
2647 name, freq, sec_type, ieee80211w);
2649 if (g_strcmp0(sec_type, "none") != 0 &&
2650 g_strcmp0(sec_type, "sae") != 0) {
2651 DBG("Unsupported security");
2652 return __connman_error_invalid_arguments(msg);
2655 mesh_ifname = connman_mesh_get_interface_name();
2657 if (!connman_mesh_is_interface_created()) {
2658 DBG("Mesh interface doesn't exists");
2659 return __connman_error_invalid_command(msg);
2662 str = g_string_sized_new((strlen(name) * 2) + 24);
2664 for (i = 0; name[i]; i++)
2665 g_string_append_printf(str, "%02x", name[i]);
2667 g_string_append_printf(str, "_mesh");
2669 if (g_strcmp0(sec_type, "none") == 0)
2670 g_string_append_printf(str, "_none");
2671 else if (g_strcmp0(sec_type, "sae") == 0)
2672 g_string_append_printf(str, "_sae");
2674 group = g_string_free(str, FALSE);
2676 identifier = connman_inet_ifaddr(mesh_ifname);
2677 address = connman_inet_ifname2addr(mesh_ifname);
2679 connman_mesh = connman_mesh_create(identifier, group);
2680 connman_mesh_set_name(connman_mesh, name);
2681 connman_mesh_set_address(connman_mesh, address);
2682 connman_mesh_set_security(connman_mesh, sec_type);
2683 connman_mesh_set_frequency(connman_mesh, freq);
2684 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
2685 connman_mesh_set_peer_type(connman_mesh,
2686 CONNMAN_MESH_PEER_TYPE_CREATED);
2687 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
2689 connman_mesh_register(connman_mesh);
2693 DBG("Successfully Created Mesh Network");
2694 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2696 } else if (g_str_equal(cmd, "AbortScan")) {
2697 DBG("Abort Scan method");
2698 err = __connman_device_abort_scan(technology->type);
2700 DBG("Failed to abort scan");
2701 return __connman_error_failed(msg, -err);
2704 DBG("Successfully requested to abort scan");
2705 dbus_message_ref(msg);
2706 technology->mesh_dbus_msg = msg;
2708 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
2709 const char *name = NULL;
2710 unsigned int freq = 0;
2711 dbus_message_iter_recurse(&value, &dict);
2712 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2713 DBusMessageIter entry, value2;
2717 dbus_message_iter_recurse(&dict, &entry);
2719 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2720 return __connman_error_invalid_arguments(msg);
2722 dbus_message_iter_get_basic(&entry, &key);
2723 dbus_message_iter_next(&entry);
2725 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2726 return __connman_error_invalid_arguments(msg);
2728 dbus_message_iter_recurse(&entry, &value2);
2730 type = dbus_message_iter_get_arg_type(&value2);
2732 if (g_str_equal(key, "Name")) {
2733 if (type != DBUS_TYPE_STRING)
2734 return __connman_error_invalid_arguments(msg);
2736 dbus_message_iter_get_basic(&value2, &name);
2737 } else if (g_str_equal(key, "Frequency")) {
2738 if (type != DBUS_TYPE_UINT16)
2739 return __connman_error_invalid_arguments(msg);
2741 dbus_message_iter_get_basic(&value2, &freq);
2743 dbus_message_iter_next(&dict);
2746 DBG("MeshID %s Frequency %d sender %s", name, freq,
2747 dbus_message_get_sender(msg));
2749 struct connman_scan_pending *pending_data =
2750 g_try_malloc0(sizeof(struct connman_scan_pending));
2752 return __connman_error_failed(msg, ENOMEM);
2754 pending_data->msg = dbus_message_ref(msg);
2756 technology->scan_pending =
2757 g_slist_prepend(technology->scan_pending, pending_data);
2759 err = __connman_device_request_mesh_specific_scan(technology->type,
2762 reply_scan_pending(technology, err);
2764 DBG("Successfully requested to scan specific Mesh Network");
2766 } else if (g_str_equal(cmd, "SetMeshGate")) {
2767 unsigned int hwmp_rootmode = 0;
2768 bool gate_announce = false;
2769 unsigned int stp = 0;
2771 dbus_message_iter_recurse(&value, &dict);
2772 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2773 DBusMessageIter entry, value2;
2777 dbus_message_iter_recurse(&dict, &entry);
2779 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2780 return __connman_error_invalid_arguments(msg);
2782 dbus_message_iter_get_basic(&entry, &key);
2783 dbus_message_iter_next(&entry);
2785 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2786 return __connman_error_invalid_arguments(msg);
2788 dbus_message_iter_recurse(&entry, &value2);
2790 type = dbus_message_iter_get_arg_type(&value2);
2792 if (g_str_equal(key, "GateAnnounce")) {
2793 if (type != DBUS_TYPE_BOOLEAN)
2794 return __connman_error_invalid_arguments(msg);
2796 dbus_message_iter_get_basic(&value2, &gate_announce);
2797 } else if (g_str_equal(key, "HWMPRootMode")) {
2798 if (type != DBUS_TYPE_UINT16)
2799 return __connman_error_invalid_arguments(msg);
2801 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
2802 } else if (g_str_equal(key, "STP")) {
2803 if (type != DBUS_TYPE_UINT16)
2804 return __connman_error_invalid_arguments(msg);
2806 dbus_message_iter_get_basic(&value2, &stp);
2808 dbus_message_iter_next(&dict);
2811 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
2812 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
2814 err = __connman_mesh_set_stp_gate_announce(gate_announce,
2819 return __connman_error_failed(msg, -err);
2821 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2823 return __connman_error_invalid_command(msg);
2828 static const GDBusMethodTable technology_methods[] = {
2829 { GDBUS_DEPRECATED_METHOD("GetProperties",
2830 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
2832 { GDBUS_ASYNC_METHOD("SetProperty",
2833 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2834 NULL, set_property) },
2835 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
2836 #if defined TIZEN_EXT
2837 { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
2838 NULL, scan_device) },
2839 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
2840 NULL, specific_scan) },
2841 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
2843 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2844 get_5ghz_supported) },
2845 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2846 get_max_scan_ssid) },
2847 { GDBUS_ASYNC_METHOD("SetDevicePower",
2848 GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
2849 NULL, set_device_power) },
2850 { GDBUS_ASYNC_METHOD("SetBSSID",
2851 GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
2854 #if defined TIZEN_EXT_WIFI_MESH
2855 { GDBUS_ASYNC_METHOD("MeshCommands",
2856 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2857 NULL, mesh_commands) },
2862 static const GDBusSignalTable technology_signals[] = {
2863 { GDBUS_SIGNAL("PropertyChanged",
2864 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2865 #if defined TIZEN_EXT
2866 { GDBUS_SIGNAL("DeviceChanged",
2867 GDBUS_ARGS({ "device_property", "a{sv}" })) },
2868 { GDBUS_SIGNAL("DeviceDetected",
2869 GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
2874 static bool technology_dbus_register(struct connman_technology *technology)
2876 if (technology->dbus_registered ||
2877 (technology->rfkill_driven &&
2878 technology->hardblocked))
2881 if (!g_dbus_register_interface(connection, technology->path,
2882 CONNMAN_TECHNOLOGY_INTERFACE,
2883 technology_methods, technology_signals,
2884 NULL, technology, NULL)) {
2885 connman_error("Failed to register %s", technology->path);
2889 technology_added_signal(technology);
2890 technology->dbus_registered = true;
2895 static void technology_dbus_unregister(struct connman_technology *technology)
2897 if (!technology->dbus_registered)
2900 technology_removed_signal(technology);
2901 g_dbus_unregister_interface(connection, technology->path,
2902 CONNMAN_TECHNOLOGY_INTERFACE);
2904 technology->dbus_registered = false;
2907 static void technology_put(struct connman_technology *technology)
2909 DBG("technology %p", technology);
2911 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2914 reply_scan_pending(technology, -EINTR);
2916 while (technology->driver_list) {
2917 struct connman_technology_driver *driver;
2919 driver = technology->driver_list->data;
2922 driver->remove(technology);
2924 technology->driver_list =
2925 g_slist_delete_link(technology->driver_list,
2926 technology->driver_list);
2929 technology_list = g_slist_remove(technology_list, technology);
2931 technology_dbus_unregister(technology);
2933 g_slist_free(technology->device_list);
2935 if (technology->pending_reply) {
2936 dbus_message_unref(technology->pending_reply);
2937 technology->pending_reply = NULL;
2938 g_source_remove(technology->pending_timeout);
2939 technology->pending_timeout = 0;
2942 g_strfreev(technology->enabled_devices);
2944 g_free(technology->path);
2945 g_free(technology->regdom);
2946 g_free(technology->tethering_ident);
2947 g_free(technology->tethering_passphrase);
2951 static struct connman_technology *technology_get(enum connman_service_type type)
2953 GSList *tech_drivers = NULL;
2954 struct connman_technology_driver *driver;
2955 struct connman_technology *technology;
2959 DBG("type %d", type);
2961 str = __connman_service_type2string(type);
2965 technology = technology_find(type);
2967 #if defined TIZEN_EXT_WIFI_MESH
2968 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2969 type != CONNMAN_SERVICE_TYPE_MESH)
2971 if (type != CONNMAN_SERVICE_TYPE_P2P)
2973 __sync_fetch_and_add(&technology->refcount, 1);
2977 /* First check if we have a driver for this technology type */
2978 for (list = driver_list; list; list = list->next) {
2979 driver = list->data;
2981 if (driver->type == type) {
2982 DBG("technology %p driver %p", technology, driver);
2983 tech_drivers = g_slist_append(tech_drivers, driver);
2987 if (!tech_drivers) {
2988 DBG("No matching drivers found for %s.",
2989 __connman_service_type2string(type));
2993 technology = g_try_new0(struct connman_technology, 1);
2997 technology->refcount = 1;
2998 technology->type = type;
2999 technology->path = g_strdup_printf("%s/technology/%s",
3002 #if defined TIZEN_EXT_WIFI_MESH
3003 if (type == CONNMAN_SERVICE_TYPE_MESH) {
3004 struct connman_technology *wifi;
3006 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
3008 technology->enabled = wifi->enabled;
3012 technology_load(technology);
3013 technology_list = g_slist_prepend(technology_list, technology);
3014 technology->driver_list = tech_drivers;
3016 for (list = tech_drivers; list; list = list->next) {
3017 driver = list->data;
3019 if (driver->probe && driver->probe(technology) < 0)
3020 DBG("Driver probe failed for technology %p",
3024 if (!technology_dbus_register(technology)) {
3025 technology_put(technology);
3029 if (type == CONNMAN_SERVICE_TYPE_P2P) {
3030 struct connman_technology *wifi;
3033 enable = technology->enable_persistent;
3035 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
3037 enable = wifi->enabled;
3039 technology_affect_devices(technology, enable);
3042 DBG("technology %p %s", technology, get_name(technology->type));
3047 int connman_technology_driver_register(struct connman_technology_driver *driver)
3050 struct connman_device *device;
3051 enum connman_service_type type;
3053 for (list = driver_list; list; list = list->next) {
3054 if (list->data == driver)
3058 DBG("Registering %s driver", driver->name);
3060 driver_list = g_slist_insert_sorted(driver_list, driver,
3064 * Check for technology less devices if this driver
3065 * can service any of them.
3067 for (list = techless_device_list; list; list = list->next) {
3068 device = list->data;
3070 type = __connman_device_get_service_type(device);
3071 if (type != driver->type)
3074 techless_device_list = g_slist_remove(techless_device_list,
3077 __connman_technology_add_device(device);
3080 /* Check for orphaned rfkill switches. */
3081 g_hash_table_foreach(rfkill_list, rfkill_check,
3082 GINT_TO_POINTER(driver->type));
3085 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3086 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
3090 #if defined TIZEN_EXT_WIFI_MESH
3091 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3092 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
3100 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
3102 GSList *list, *tech_drivers;
3103 struct connman_technology *technology;
3104 struct connman_technology_driver *current;
3106 DBG("Unregistering driver %p name %s", driver, driver->name);
3108 for (list = technology_list; list; list = list->next) {
3109 technology = list->data;
3111 for (tech_drivers = technology->driver_list; tech_drivers;
3112 tech_drivers = g_slist_next(tech_drivers)) {
3113 current = tech_drivers->data;
3114 if (driver != current)
3118 driver->remove(technology);
3120 technology->driver_list =
3121 g_slist_remove(technology->driver_list,
3127 driver_list = g_slist_remove(driver_list, driver);
3129 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3130 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
3132 technology_put(technology);
3134 #if defined TIZEN_EXT_WIFI_MESH
3135 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3136 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
3138 technology_put(technology);
3143 void __connman_technology_add_interface(enum connman_service_type type,
3144 int index, const char *ident)
3146 struct connman_technology *technology;
3147 GSList *tech_drivers;
3148 struct connman_technology_driver *driver;
3152 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3153 case CONNMAN_SERVICE_TYPE_SYSTEM:
3155 case CONNMAN_SERVICE_TYPE_ETHERNET:
3156 case CONNMAN_SERVICE_TYPE_WIFI:
3157 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3158 case CONNMAN_SERVICE_TYPE_CELLULAR:
3159 case CONNMAN_SERVICE_TYPE_GPS:
3160 case CONNMAN_SERVICE_TYPE_VPN:
3161 case CONNMAN_SERVICE_TYPE_GADGET:
3162 case CONNMAN_SERVICE_TYPE_P2P:
3163 #if defined TIZEN_EXT_WIFI_MESH
3164 case CONNMAN_SERVICE_TYPE_MESH:
3169 name = connman_inet_ifname(index);
3170 connman_info("Adding interface %s [ %s ]", name,
3171 __connman_service_type2string(type));
3173 technology = technology_find(type);
3178 for (tech_drivers = technology->driver_list; tech_drivers;
3179 tech_drivers = g_slist_next(tech_drivers)) {
3180 driver = tech_drivers->data;
3182 if (driver->add_interface)
3183 driver->add_interface(technology, index, name, ident);
3187 * At this point we can try to enable tethering automatically as
3188 * now the interfaces are set properly.
3190 if (technology->tethering_persistent)
3191 enable_tethering(technology);
3197 void __connman_technology_remove_interface(enum connman_service_type type,
3198 int index, const char *ident)
3200 struct connman_technology *technology;
3201 GSList *tech_drivers;
3202 struct connman_technology_driver *driver;
3206 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3207 case CONNMAN_SERVICE_TYPE_SYSTEM:
3209 case CONNMAN_SERVICE_TYPE_ETHERNET:
3210 case CONNMAN_SERVICE_TYPE_WIFI:
3211 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3212 case CONNMAN_SERVICE_TYPE_CELLULAR:
3213 case CONNMAN_SERVICE_TYPE_GPS:
3214 case CONNMAN_SERVICE_TYPE_VPN:
3215 case CONNMAN_SERVICE_TYPE_GADGET:
3216 case CONNMAN_SERVICE_TYPE_P2P:
3217 #if defined TIZEN_EXT_WIFI_MESH
3218 case CONNMAN_SERVICE_TYPE_MESH:
3223 name = connman_inet_ifname(index);
3224 connman_info("Remove interface %s [ %s ]", name,
3225 __connman_service_type2string(type));
3228 technology = technology_find(type);
3233 for (tech_drivers = technology->driver_list; tech_drivers;
3234 tech_drivers = g_slist_next(tech_drivers)) {
3235 driver = tech_drivers->data;
3237 if (driver->remove_interface)
3238 driver->remove_interface(technology, index);
3242 int __connman_technology_add_device(struct connman_device *device)
3244 struct connman_technology *technology;
3245 enum connman_service_type type;
3247 type = __connman_device_get_service_type(device);
3249 DBG("device %p type %s", device, get_name(type));
3251 technology = technology_get(type);
3254 * Since no driver can be found for this device at the moment we
3255 * add it to the techless device list.
3257 techless_device_list = g_slist_prepend(techless_device_list,
3263 __sync_synchronize();
3264 if (technology->rfkill_driven) {
3265 if (technology->enabled)
3266 __connman_device_enable(device);
3268 __connman_device_disable(device);
3273 if (technology->enable_persistent &&
3274 !global_offlinemode) {
3275 #if defined TIZEN_EXT
3278 if (technology->enabled_devices && type == CONNMAN_SERVICE_TYPE_WIFI) {
3281 const char *ifname = connman_device_get_string(device, "Interface");
3283 while (technology->enabled_devices[i]) {
3284 if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
3293 err = __connman_device_enable(device);
3295 int err = __connman_device_enable(device);
3298 * connman_technology_add_device() calls __connman_device_enable()
3299 * but since the device is already enabled, the call does not
3300 * propagate through to connman_technology_enabled via
3301 * connman_device_set_powered.
3303 if (err == -EALREADY)
3304 __connman_technology_enabled(type);
3306 /* if technology persistent state is offline */
3307 if (!technology->enable_persistent)
3308 __connman_device_disable(device);
3311 technology->device_list = g_slist_prepend(technology->device_list,
3314 #if defined TIZEN_EXT
3315 technology_save_device(device);
3317 const char *ifname = connman_device_get_string(device, "Interface");
3318 __connman_technology_notify_device_detected(technology, ifname, true);
3320 connman_device_set_mac_policy(device, technology->mac_policy);
3321 connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy);
3322 connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime);
3327 int __connman_technology_remove_device(struct connman_device *device)
3329 struct connman_technology *technology;
3330 enum connman_service_type type;
3332 DBG("device %p", device);
3334 type = __connman_device_get_service_type(device);
3336 technology = technology_find(type);
3338 techless_device_list = g_slist_remove(techless_device_list,
3343 technology->device_list = g_slist_remove(technology->device_list,
3346 #if defined TIZEN_EXT
3347 technology_save_device(device);
3349 const char *ifname = connman_device_get_string(device, "Interface");
3350 __connman_technology_notify_device_detected(technology, ifname, false);
3353 if (technology->tethering)
3354 set_tethering(technology, false);
3356 technology_put(technology);
3361 int __connman_technology_enabled(enum connman_service_type type)
3363 struct connman_technology *technology;
3365 technology = technology_find(type);
3369 DBG("technology %p type %s rfkill %d enabled %d", technology,
3370 get_name(type), technology->rfkill_driven,
3371 technology->enabled);
3373 #if !defined TIZEN_EXT
3374 if (technology->rfkill_driven) {
3375 if (technology->tethering_persistent)
3376 enable_tethering(technology);
3381 return technology_enabled(technology);
3384 int __connman_technology_disabled(enum connman_service_type type)
3386 struct connman_technology *technology;
3389 technology = technology_find(type);
3393 #if !defined TIZEN_EXT
3394 if (technology->rfkill_driven)
3398 for (list = technology->device_list; list; list = list->next) {
3399 struct connman_device *device = list->data;
3401 if (connman_device_get_powered(device))
3405 return technology_disabled(technology);
3408 int __connman_technology_set_offlinemode(bool offlinemode)
3411 int err = -EINVAL, enabled_tech_count = 0;
3413 if (global_offlinemode == offlinemode)
3416 DBG("offlinemode %s", offlinemode ? "On" : "Off");
3419 * This is a bit tricky. When you set offlinemode, there is no
3420 * way to differentiate between attempting offline mode and
3421 * resuming offlinemode from last saved profile. We need that
3422 * information in rfkill_update, otherwise it falls back on the
3423 * technology's persistent state. Hence we set the offline mode here
3424 * but save it & call the notifier only if it is successful.
3427 global_offlinemode = offlinemode;
3429 /* Traverse technology list, enable/disable each technology. */
3430 for (list = technology_list; list; list = list->next) {
3431 struct connman_technology *technology = list->data;
3434 err = technology_disable(technology);
3436 if (technology->hardblocked)
3439 if (technology->enable_persistent) {
3440 err = technology_enable(technology);
3441 enabled_tech_count++;
3446 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
3447 (err == -EINVAL && enabled_tech_count == 0)) {
3448 connman_technology_save_offlinemode();
3449 __connman_notifier_offlinemode(offlinemode);
3451 global_offlinemode = connman_technology_load_offlinemode();
3456 #if defined TIZEN_EXT_WIFI_MESH
3457 static gboolean __add_ethernet_to_bridge(gpointer data)
3460 __connman_mesh_add_ethernet_to_bridge();
3465 void __connman_technology_set_connected(enum connman_service_type type,
3468 struct connman_technology *technology;
3471 technology = technology_find(type);
3475 DBG("technology %p connected %d", technology, connected);
3477 technology->connected = connected;
3479 #if defined TIZEN_EXT_WIFI_MESH
3480 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
3481 g_idle_add(__add_ethernet_to_bridge, NULL);
3485 connman_dbus_property_changed_basic(technology->path,
3486 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
3487 DBUS_TYPE_BOOLEAN, &val);
3490 static bool technology_apply_rfkill_change(struct connman_technology *technology,
3495 bool hardblock_changed = false;
3497 GList *start, *list;
3499 DBG("technology %p --> %d/%d vs %d/%d",
3500 technology, softblock, hardblock,
3501 technology->softblocked, technology->hardblocked);
3503 if (technology->hardblocked == hardblock)
3504 goto softblock_change;
3506 if (!(new_rfkill && !hardblock)) {
3507 start = g_hash_table_get_values(rfkill_list);
3509 for (list = start; list; list = list->next) {
3510 struct connman_rfkill *rfkill = list->data;
3512 if (rfkill->type != technology->type)
3515 if (rfkill->hardblock != hardblock)
3523 goto softblock_change;
3525 technology->hardblocked = hardblock;
3526 hardblock_changed = true;
3529 if (!apply && technology->softblocked != softblock)
3533 return technology->hardblocked;
3535 technology->softblocked = softblock;
3537 if (technology->hardblocked ||
3538 technology->softblocked) {
3539 if (technology_disabled(technology) != -EALREADY)
3540 technology_affect_devices(technology, false);
3541 } else if (!technology->hardblocked &&
3542 !technology->softblocked) {
3543 if (technology_enabled(technology) != -EALREADY)
3544 technology_affect_devices(technology, true);
3547 if (hardblock_changed) {
3548 if (technology->hardblocked) {
3549 DBG("%s is switched off.", get_name(technology->type));
3550 technology_dbus_unregister(technology);
3552 DBG("%s is switched on.", get_name(technology->type));
3553 technology_dbus_register(technology);
3555 if (global_offlinemode)
3556 __connman_rfkill_block(technology->type, true);
3560 return technology->hardblocked;
3563 int __connman_technology_add_rfkill(unsigned int index,
3564 enum connman_service_type type,
3568 struct connman_technology *technology;
3569 struct connman_rfkill *rfkill;
3571 DBG("index %u type %d soft %u hard %u", index, type,
3572 softblock, hardblock);
3574 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3578 rfkill = g_try_new0(struct connman_rfkill, 1);
3582 rfkill->index = index;
3583 rfkill->type = type;
3584 rfkill->softblock = softblock;
3585 rfkill->hardblock = hardblock;
3587 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
3590 #if defined TIZEN_EXT
3591 /* Fix Svace Issue [WGID: 1348]. */
3594 technology = technology_get(type);
3595 /* If there is no driver for this type, ignore it. */
3599 technology->rfkill_driven = true;
3601 #if !defined TIZEN_EXT
3602 /* If hardblocked, there is no need to handle softblocked state */
3603 if (technology_apply_rfkill_change(technology,
3604 softblock, hardblock, true))
3608 if (global_offlinemode)
3612 * Depending on softblocked state we unblock/block according to
3613 * offlinemode and persistente state.
3615 if (technology->softblocked &&
3616 technology->enable_persistent)
3617 return __connman_rfkill_block(type, false);
3618 else if (!technology->softblocked &&
3619 !technology->enable_persistent)
3620 return __connman_rfkill_block(type, true);
3625 int __connman_technology_update_rfkill(unsigned int index,
3626 enum connman_service_type type,
3630 struct connman_technology *technology;
3631 struct connman_rfkill *rfkill;
3633 DBG("index %u soft %u hard %u", index, softblock, hardblock);
3635 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3639 if (rfkill->softblock == softblock &&
3640 rfkill->hardblock == hardblock)
3643 rfkill->softblock = softblock;
3644 rfkill->hardblock = hardblock;
3646 technology = technology_find(type);
3647 /* If there is no driver for this type, ignore it. */
3651 technology_apply_rfkill_change(technology, softblock, hardblock,
3654 if (technology->hardblocked)
3655 DBG("%s hardblocked", get_name(technology->type));
3657 DBG("%s is%s softblocked", get_name(technology->type),
3658 technology->softblocked ? "" : " not");
3663 int __connman_technology_remove_rfkill(unsigned int index,
3664 enum connman_service_type type)
3666 struct connman_technology *technology;
3667 struct connman_rfkill *rfkill;
3669 DBG("index %u", index);
3671 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3675 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
3677 technology = technology_find(type);
3681 technology_apply_rfkill_change(technology,
3682 technology->softblocked, !technology->hardblocked, false);
3684 technology_put(technology);
3689 int __connman_technology_init(void)
3693 connection = connman_dbus_get_connection();
3695 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3698 global_offlinemode = connman_technology_load_offlinemode();
3700 /* This will create settings file if it is missing */
3701 connman_technology_save_offlinemode();
3706 void __connman_technology_cleanup(void)
3710 while (technology_list) {
3711 struct connman_technology *technology = technology_list->data;
3712 technology_list = g_slist_remove(technology_list, technology);
3713 technology_put(technology);
3716 g_hash_table_destroy(rfkill_list);
3718 dbus_connection_unref(connection);