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;
453 DBG("technology %p", technology);
455 keyfile = __connman_storage_load_global();
456 /* Fallback on disabling technology if file not found. */
458 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
459 /* We enable ethernet by default */
460 technology->enable_persistent = true;
462 technology->enable_persistent = false;
466 identifier = g_strdup_printf("%s", get_name(technology->type));
472 technology->enabled_devices = g_key_file_get_string_list(keyfile,
473 identifier, "Enable.Devices", &length, NULL);
474 if (technology->enabled_devices && length == 0) {
475 g_strfreev(technology->enabled_devices);
476 technology->enabled_devices = NULL;
480 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
482 technology->enable_persistent = enable;
484 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
485 technology->enable_persistent = true;
487 technology->enable_persistent = false;
490 g_clear_error(&error);
493 enable = g_key_file_get_boolean(keyfile, identifier,
494 "Tethering", &error);
496 technology->tethering_persistent = enable;
499 g_clear_error(&error);
503 technology_save(technology);
505 technology->tethering_ident = g_key_file_get_string(keyfile,
506 identifier, "Tethering.Identifier", NULL);
508 enc = g_key_file_get_string(keyfile,
509 identifier, "Tethering.Passphrase", NULL);
511 technology->tethering_passphrase = g_strcompress(enc);
513 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
514 unsigned int val = 0;
516 val = g_key_file_get_uint64(keyfile,
517 identifier, "MacPolicy", NULL);
519 technology->mac_policy = val;
521 technology->mac_policy = 0;
523 val = g_key_file_get_uint64(keyfile,
524 identifier, "PreassocMacPolicy", NULL);
526 technology->preassoc_mac_policy = val;
528 technology->preassoc_mac_policy = 0;
530 val = g_key_file_get_uint64(keyfile,
531 identifier, "RandomMacLifetime", NULL);
533 technology->random_mac_lifetime = val;
535 technology->random_mac_lifetime = 60;
537 #endif /* TIZEN_EXT */
542 g_key_file_free(keyfile);
545 bool __connman_technology_get_offlinemode(void)
547 return global_offlinemode;
550 static void connman_technology_save_offlinemode(void)
553 GError *error = NULL;
556 keyfile = __connman_storage_load_global();
559 keyfile = g_key_file_new();
560 g_key_file_set_boolean(keyfile, "global",
561 "OfflineMode", global_offlinemode);
563 __connman_storage_save_global(keyfile);
566 offlinemode = g_key_file_get_boolean(keyfile, "global",
567 "OfflineMode", &error);
569 if (error || offlinemode != global_offlinemode) {
570 g_key_file_set_boolean(keyfile, "global",
571 "OfflineMode", global_offlinemode);
573 g_clear_error(&error);
575 __connman_storage_save_global(keyfile);
579 g_key_file_free(keyfile);
582 static bool connman_technology_load_offlinemode(void)
585 GError *error = NULL;
588 /* If there is a error, we enable offlinemode */
589 keyfile = __connman_storage_load_global();
593 offlinemode = g_key_file_get_boolean(keyfile, "global",
594 "OfflineMode", &error);
597 g_clear_error(&error);
600 g_key_file_free(keyfile);
605 #if defined TIZEN_EXT
606 static void append_devices(DBusMessageIter *iter, void *user_data)
610 struct connman_technology *technology = user_data;
612 for (list = technology->device_list; list; list = list->next) {
613 struct connman_device *device = list->data;
615 const char *str = connman_device_get_string(device, "Interface");
616 struct connman_network *network = connman_device_get_default_network(device);
617 struct connman_service *service = connman_service_lookup_from_network(network);
619 connman_dbus_dict_append_basic(iter, "Ifname",
620 DBUS_TYPE_STRING, &str);
622 val = connman_device_get_powered(device);
623 connman_dbus_dict_append_basic(iter, "Powered",
624 DBUS_TYPE_BOOLEAN, &val);
626 if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) ||
627 __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6))
632 connman_dbus_dict_append_basic(iter, "Connected",
633 DBUS_TYPE_BOOLEAN, &val);
635 str = connman_device_get_string(device, "Address");
636 connman_dbus_dict_append_basic(iter, "MAC.Address",
637 DBUS_TYPE_STRING, &str);
641 void __connman_technology_append_interfaces(DBusMessageIter *array,
642 enum connman_service_type type, const char *ifname)
645 struct connman_technology *technology = NULL;
647 for (list = technology_list; list; list = list->next) {
648 struct connman_technology *local_tech = list->data;
650 if (local_tech->type != type)
653 technology = local_tech;
660 for (list = technology->device_list; list; list = list->next) {
661 struct connman_device *device = list->data;
662 const char *str = connman_device_get_string(device, "Interface");
664 if (g_strcmp0(ifname, str) == 0)
667 dbus_message_iter_append_basic(array,
668 DBUS_TYPE_STRING, &str);
673 static void append_properties(DBusMessageIter *iter,
674 struct connman_technology *technology)
676 DBusMessageIter dict;
680 connman_dbus_dict_open(iter, &dict);
682 str = get_name(technology->type);
684 connman_dbus_dict_append_basic(&dict, "Name",
685 DBUS_TYPE_STRING, &str);
687 str = __connman_service_type2string(technology->type);
689 connman_dbus_dict_append_basic(&dict, "Type",
690 DBUS_TYPE_STRING, &str);
692 __sync_synchronize();
693 val = technology->enabled;
694 connman_dbus_dict_append_basic(&dict, "Powered",
698 val = technology->connected;
699 connman_dbus_dict_append_basic(&dict, "Connected",
703 val = technology->tethering;
704 connman_dbus_dict_append_basic(&dict, "Tethering",
708 if (technology->tethering_ident)
709 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
711 &technology->tethering_ident);
713 if (technology->tethering_passphrase)
714 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
716 &technology->tethering_passphrase);
718 #if defined TIZEN_EXT
719 connman_dbus_dict_append_basic(&dict, "MacPolicy",
721 &(technology->mac_policy));
723 connman_dbus_dict_append_basic(&dict, "PreassocMacPolicy",
725 &(technology->preassoc_mac_policy));
727 connman_dbus_dict_append_basic(&dict, "RandomMacLifetime",
729 &(technology->random_mac_lifetime));
731 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
732 connman_dbus_dict_append_dict(&dict, "Device.List",
733 append_devices, technology);
734 if (technology->regdom)
735 connman_dbus_dict_append_basic(&dict, "CountryCode",
737 &technology->regdom);
739 connman_dbus_dict_close(iter, &dict);
742 static void technology_added_signal(struct connman_technology *technology)
745 DBusMessageIter iter;
747 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
748 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
752 dbus_message_iter_init_append(signal, &iter);
753 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
755 append_properties(&iter, technology);
757 dbus_connection_send(connection, signal, NULL);
758 dbus_message_unref(signal);
761 static void technology_removed_signal(struct connman_technology *technology)
763 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
764 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
765 DBUS_TYPE_OBJECT_PATH, &technology->path,
769 static DBusMessage *get_properties(DBusConnection *conn,
770 DBusMessage *message, void *user_data)
772 struct connman_technology *technology = user_data;
774 DBusMessageIter iter;
776 reply = dbus_message_new_method_return(message);
780 dbus_message_iter_init_append(reply, &iter);
781 append_properties(&iter, technology);
786 void __connman_technology_list_struct(DBusMessageIter *array)
789 DBusMessageIter entry;
791 for (list = technology_list; list; list = list->next) {
792 struct connman_technology *technology = list->data;
794 if (!technology->path ||
795 (technology->rfkill_driven &&
796 technology->hardblocked))
799 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
801 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
803 append_properties(&entry, technology);
804 dbus_message_iter_close_container(array, &entry);
808 static gboolean technology_pending_reply(gpointer user_data)
810 struct connman_technology *technology = user_data;
813 /* Power request timed out, send ETIMEDOUT. */
814 if (technology->pending_reply) {
815 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
817 g_dbus_send_message(connection, reply);
819 dbus_message_unref(technology->pending_reply);
820 technology->pending_reply = NULL;
821 technology->pending_timeout = 0;
827 static int technology_affect_devices(struct connman_technology *technology,
830 int err = 0, err_dev;
833 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
835 __connman_technology_enabled(technology->type);
837 __connman_technology_disabled(technology->type);
841 #if defined TIZEN_EXT_WIFI_MESH
842 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
846 for (list = technology->device_list; list; list = list->next) {
847 struct connman_device *device = list->data;
850 err_dev = __connman_device_enable(device);
852 err_dev = __connman_device_disable(device);
854 if (err_dev < 0 && err_dev != -EALREADY)
861 static void powered_changed(struct connman_technology *technology)
865 if (!technology->dbus_registered)
868 if (technology->pending_reply) {
869 g_dbus_send_reply(connection,
870 technology->pending_reply, DBUS_TYPE_INVALID);
871 dbus_message_unref(technology->pending_reply);
872 technology->pending_reply = NULL;
874 g_source_remove(technology->pending_timeout);
875 technology->pending_timeout = 0;
878 __sync_synchronize();
879 enabled = technology->enabled;
880 #if defined TIZEN_EXT
881 DBG("ConnMan, Powered : %s, %s",
882 enabled ? "TRUE" : "FALSE",technology->path);
884 connman_dbus_property_changed_basic(technology->path,
885 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
886 DBUS_TYPE_BOOLEAN, &enabled);
889 static void enable_tethering(struct connman_technology *technology)
893 if (!connman_setting_get_bool("PersistentTetheringMode"))
896 ret = set_tethering(technology, true);
897 if (ret < 0 && ret != -EALREADY)
898 DBG("Cannot enable tethering yet for %s (%d/%s)",
899 get_name(technology->type),
900 -ret, strerror(-ret));
903 static int technology_enabled(struct connman_technology *technology)
905 __sync_synchronize();
906 if (technology->enabled)
909 technology->enabled = true;
911 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
912 struct connman_technology *p2p;
914 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
915 if (p2p && !p2p->enabled && p2p->enable_persistent)
916 technology_enabled(p2p);
919 if (technology->tethering_persistent)
920 enable_tethering(technology);
922 powered_changed(technology);
927 static int technology_enable(struct connman_technology *technology)
932 DBG("technology %p enable", technology);
934 __sync_synchronize();
936 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
937 struct connman_technology *wifi;
939 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
940 if (wifi && wifi->enabled)
941 return technology_enabled(technology);
945 if (technology->enabled)
948 if (technology->pending_reply)
951 if (connman_setting_get_bool("PersistentTetheringMode") &&
952 technology->tethering)
953 set_tethering(technology, true);
955 if (technology->rfkill_driven)
956 err = __connman_rfkill_block(technology->type, false);
958 err_dev = technology_affect_devices(technology, true);
960 if (!technology->rfkill_driven)
966 static int technology_disabled(struct connman_technology *technology)
968 __sync_synchronize();
969 if (!technology->enabled)
972 technology->enabled = false;
974 powered_changed(technology);
979 static int technology_disable(struct connman_technology *technology)
983 DBG("technology %p disable", technology);
985 __sync_synchronize();
987 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
988 technology->enable_persistent = false;
989 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
990 __connman_peer_disconnect_all();
991 return technology_disabled(technology);
992 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
993 struct connman_technology *p2p;
995 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
996 if (p2p && p2p->enabled) {
997 p2p->enable_persistent = true;
998 technology_disabled(p2p);
1002 if (!technology->enabled)
1005 if (technology->pending_reply)
1008 if (technology->tethering)
1009 set_tethering(technology, false);
1011 err = technology_affect_devices(technology, false);
1013 if (technology->rfkill_driven)
1014 err = __connman_rfkill_block(technology->type, true);
1019 static DBusMessage *set_powered(struct connman_technology *technology,
1020 DBusMessage *msg, bool powered)
1022 DBusMessage *reply = NULL;
1025 if (technology->rfkill_driven && technology->hardblocked) {
1031 err = technology_enable(technology);
1033 err = technology_disable(technology);
1035 if (err != -EBUSY) {
1036 technology->enable_persistent = powered;
1037 technology_save(technology);
1041 if (err == -EINPROGRESS) {
1042 technology->pending_reply = dbus_message_ref(msg);
1043 technology->pending_timeout = g_timeout_add_seconds(10,
1044 technology_pending_reply, technology);
1045 } else if (err == -EALREADY) {
1047 reply = __connman_error_already_enabled(msg);
1049 reply = __connman_error_already_disabled(msg);
1051 reply = __connman_error_failed(msg, -err);
1053 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1058 #if defined TIZEN_EXT
1059 int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
1061 static int bssid_len;
1062 static const char *def_ifname = "default";
1063 static GSList *bssid_list = NULL;
1065 const char *local_ifname = ifname;
1067 struct connman_bssid_pending *bssid_info;
1069 DBG("mode: %d, ifname: %s", mode, ifname);
1072 local_ifname = def_ifname;
1074 for (list = bssid_list; list; list = list->next) {
1075 bssid_info = list->data;
1077 if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
1083 if (mode == CHECK_BSSID) {
1090 if (mode == GET_BSSID && bssid) {
1092 memcpy(bssid, bssid_info->bssid, 6);
1098 if (mode == RESET_BSSID) {
1100 bssid_list = g_slist_remove(bssid_list, bssid_info);
1101 g_free(bssid_info->ifname);
1107 if (mode != SET_BSSID || !bssid) {
1108 DBG("Invalid parameter");
1113 bssid_list = g_slist_remove(bssid_list, bssid_info);
1114 g_free(bssid_info->ifname);
1118 bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
1120 DBG("Failed to allocate memory");
1124 unsigned char *bssid_data = bssid_info->bssid;
1126 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1127 &bssid_data[0], &bssid_data[1], &bssid_data[2],
1128 &bssid_data[3], &bssid_data[4], &bssid_data[5]);
1129 if (bssid_len != 6) {
1130 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
1135 DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
1137 bssid_data[0], bssid_data[1], bssid_data[2],
1138 bssid_data[3], bssid_data[4], bssid_data[5],
1141 bssid_info->ifname = g_strdup(ifname);
1142 bssid_list = g_slist_prepend(bssid_list, bssid_info);
1147 void connman_technology_mac_policy_notify(struct connman_technology *technology,
1148 unsigned int policy)
1150 DBG("Mac polict set to %u", policy);
1152 technology->mac_policy = policy;
1153 technology_save(technology);
1156 void __connman_technology_notify_mac_policy_by_device(struct connman_device *device,
1157 int result, unsigned int policy)
1159 struct connman_technology *technology;
1160 enum connman_service_type type;
1162 type = __connman_device_get_service_type(device);
1163 technology = technology_find(type);
1168 connman_technology_mac_policy_notify(technology, policy);
1171 static DBusMessage *set_mac_policy(struct connman_technology *technology,
1172 DBusMessage *msg, unsigned int policy)
1174 DBusMessage *reply = NULL;
1176 unsigned int last_policy = technology->mac_policy;
1178 if (technology->rfkill_driven && technology->hardblocked) {
1183 for (GSList *list = technology->device_list; list; list = list->next) {
1184 struct connman_device *device = list->data;
1186 err = connman_device_set_mac_policy(device, policy);
1193 if (err != -EACCES && err != -EOPNOTSUPP) {
1194 for (GSList *list = technology->device_list; list; list = list->next) {
1195 struct connman_device *device = list->data;
1197 connman_device_set_mac_policy(device, last_policy);
1201 reply = __connman_error_failed(msg, -err);
1203 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1209 void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology,
1210 unsigned int policy)
1212 DBG("Preassoc mac polict set to %u", policy);
1214 technology->preassoc_mac_policy = policy;
1215 technology_save(technology);
1218 void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device,
1219 int result, unsigned int policy)
1221 struct connman_technology *technology;
1222 enum connman_service_type type;
1224 type = __connman_device_get_service_type(device);
1225 technology = technology_find(type);
1230 connman_technology_preassoc_mac_policy_notify(technology, policy);
1233 static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology,
1234 DBusMessage *msg, unsigned int policy)
1236 DBusMessage *reply = NULL;
1238 unsigned int last_policy = technology->preassoc_mac_policy;
1240 if (technology->rfkill_driven && technology->hardblocked) {
1245 for (GSList *list = technology->device_list; list; list = list->next) {
1246 struct connman_device *device = list->data;
1248 err = connman_device_set_preassoc_mac_policy(device, policy);
1255 if (err != -EACCES && err != -EOPNOTSUPP) {
1256 for (GSList *list = technology->device_list; list; list = list->next) {
1257 struct connman_device *device = list->data;
1259 connman_device_set_preassoc_mac_policy(device, last_policy);
1263 reply = __connman_error_failed(msg, -err);
1265 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1271 void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology,
1272 unsigned int lifetime)
1274 DBG("Random mac lifetime set to %u", lifetime);
1276 technology->random_mac_lifetime = lifetime;
1277 technology_save(technology);
1280 void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device,
1281 int result, unsigned int lifetime)
1283 struct connman_technology *technology;
1284 enum connman_service_type type;
1286 type = __connman_device_get_service_type(device);
1287 technology = technology_find(type);
1292 connman_technology_random_mac_lifetime_notify(technology, lifetime);
1295 static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology,
1296 DBusMessage *msg, unsigned int lifetime)
1298 DBusMessage *reply = NULL;
1300 unsigned int last_lifetime = technology->random_mac_lifetime;
1302 if (technology->rfkill_driven && technology->hardblocked) {
1307 for (GSList *list = technology->device_list; list; list = list->next) {
1308 struct connman_device *device = list->data;
1310 err = connman_device_set_random_mac_lifetime(device, lifetime);
1315 if (err != -EACCES && err != -EOPNOTSUPP) {
1316 for (GSList *list = technology->device_list; list; list = list->next) {
1317 struct connman_device *device = list->data;
1319 connman_device_set_random_mac_lifetime(device, last_lifetime);
1323 reply = __connman_error_failed(msg, -err);
1325 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1332 static DBusMessage *set_property(DBusConnection *conn,
1333 DBusMessage *msg, void *data)
1335 struct connman_technology *technology = data;
1336 DBusMessageIter iter, value;
1340 DBG("conn %p", conn);
1342 if (!dbus_message_iter_init(msg, &iter))
1343 return __connman_error_invalid_arguments(msg);
1345 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1346 return __connman_error_invalid_arguments(msg);
1348 dbus_message_iter_get_basic(&iter, &name);
1349 dbus_message_iter_next(&iter);
1351 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1352 return __connman_error_invalid_arguments(msg);
1354 dbus_message_iter_recurse(&iter, &value);
1356 type = dbus_message_iter_get_arg_type(&value);
1358 DBG("property %s", name);
1360 if (g_str_equal(name, "Tethering")) {
1361 dbus_bool_t tethering;
1364 if (type != DBUS_TYPE_BOOLEAN)
1365 return __connman_error_invalid_arguments(msg);
1367 if (!connman_technology_is_tethering_allowed(technology->type)) {
1368 DBG("%s tethering not allowed by config file",
1369 __connman_service_type2string(technology->type));
1370 return __connman_error_not_supported(msg);
1373 dbus_message_iter_get_basic(&value, &tethering);
1375 if (technology->tethering == tethering) {
1377 return __connman_error_already_disabled(msg);
1379 return __connman_error_already_enabled(msg);
1382 err = set_tethering(technology, tethering);
1384 return __connman_error_failed(msg, -err);
1386 technology->tethering_persistent = tethering;
1388 technology_save(technology);
1390 } else if (g_str_equal(name, "TetheringIdentifier")) {
1393 dbus_message_iter_get_basic(&value, &str);
1395 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1396 return __connman_error_not_supported(msg);
1398 if (strlen(str) < 1 || strlen(str) > 32)
1399 return __connman_error_invalid_arguments(msg);
1401 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1402 g_free(technology->tethering_ident);
1403 technology->tethering_ident = g_strdup(str);
1404 technology_save(technology);
1406 connman_dbus_property_changed_basic(technology->path,
1407 CONNMAN_TECHNOLOGY_INTERFACE,
1408 "TetheringIdentifier",
1410 &technology->tethering_ident);
1412 } else if (g_str_equal(name, "TetheringPassphrase")) {
1415 dbus_message_iter_get_basic(&value, &str);
1417 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1418 return __connman_error_not_supported(msg);
1420 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1423 return __connman_error_passphrase_required(msg);
1425 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1426 g_free(technology->tethering_passphrase);
1427 technology->tethering_passphrase = g_strdup(str);
1428 technology_save(technology);
1430 connman_dbus_property_changed_basic(technology->path,
1431 CONNMAN_TECHNOLOGY_INTERFACE,
1432 "TetheringPassphrase",
1434 &technology->tethering_passphrase);
1436 } else if (g_str_equal(name, "Powered")) {
1439 if (type != DBUS_TYPE_BOOLEAN)
1440 return __connman_error_invalid_arguments(msg);
1442 dbus_message_iter_get_basic(&value, &enable);
1444 return set_powered(technology, msg, enable);
1445 #if defined TIZEN_EXT
1446 } else if (g_str_equal(name, "SetBSSID")) {
1449 if (type != DBUS_TYPE_STRING)
1450 return __connman_error_invalid_arguments(msg);
1452 dbus_message_iter_get_basic(&value, &key);
1453 DBG("BSSID %s", key);
1454 set_connman_bssid(SET_BSSID, key, NULL);
1455 } else if (g_str_equal(name, "MacPolicy")) {
1456 dbus_uint32_t mac_policy;
1458 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1459 return __connman_error_not_supported(msg);
1461 if (type != DBUS_TYPE_UINT32)
1462 return __connman_error_invalid_arguments(msg);
1464 dbus_message_iter_get_basic(&value, &mac_policy);
1466 if (mac_policy <= 2)
1467 return set_mac_policy(technology, msg, mac_policy);
1469 return __connman_error_invalid_arguments(msg);
1471 } else if (g_str_equal(name, "PreassocMacPolicy")) {
1472 dbus_uint32_t preassoc_mac_policy;
1474 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1475 return __connman_error_not_supported(msg);
1477 if (type != DBUS_TYPE_UINT32)
1478 return __connman_error_invalid_arguments(msg);
1480 dbus_message_iter_get_basic(&value, &preassoc_mac_policy);
1482 if (preassoc_mac_policy <= 2)
1483 return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy);
1485 return __connman_error_invalid_arguments(msg);
1487 } else if (g_str_equal(name, "RandomMacLifetime")) {
1488 dbus_uint32_t random_mac_lifetime;
1490 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1491 return __connman_error_not_supported(msg);
1493 if (type != DBUS_TYPE_UINT32)
1494 return __connman_error_invalid_arguments(msg);
1496 dbus_message_iter_get_basic(&value, &random_mac_lifetime);
1498 if (random_mac_lifetime > 0)
1499 return set_random_mac_lifetime(technology, msg, random_mac_lifetime);
1501 return __connman_error_invalid_arguments(msg);
1503 } else if (g_str_equal(name, "CountryCode")) {
1506 dbus_message_iter_get_basic(&value, &str);
1507 DBG("country code %s", str);
1508 connman_technology_set_regdom(str);
1511 return __connman_error_invalid_property(msg);
1513 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1516 static void reply_scan_pending(struct connman_technology *technology, int err)
1520 DBG("technology %p err %d", technology, err);
1522 while (technology->scan_pending) {
1523 #if defined TIZEN_EXT
1524 struct connman_scan_pending *pending_data = technology->scan_pending->data;
1525 DBusMessage *msg = pending_data->msg;
1527 DBusMessage *msg = technology->scan_pending->data;
1529 DBG("reply to %s", dbus_message_get_sender(msg));
1532 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1534 reply = __connman_error_failed(msg, -err);
1535 g_dbus_send_message(connection, reply);
1536 dbus_message_unref(msg);
1538 technology->scan_pending =
1539 g_slist_delete_link(technology->scan_pending,
1540 technology->scan_pending);
1541 #if defined TIZEN_EXT
1542 g_free(pending_data->ifname);
1543 g_free(pending_data);
1548 #if defined TIZEN_EXT
1549 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1552 DBusMessage *signal;
1553 DBusMessageIter iter;
1554 dbus_bool_t result = FALSE;
1556 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1557 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1561 dbus_message_iter_init_append(signal, &iter);
1563 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1565 connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
1567 result = dbus_connection_send(connection, signal, NULL);
1568 dbus_message_unref(signal);
1570 DBG("Successfuly sent signal");
1575 void __connman_technology_notify_scan_done(const char *ifname, int val)
1578 DBusMessage *signal;
1579 DBusMessageIter iter;
1581 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1582 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1586 dbus_message_iter_init_append(signal, &iter);
1588 connman_dbus_property_append_basic(&iter, ifname,
1589 DBUS_TYPE_INT32, &val);
1591 connman_dbus_property_append_basic(&iter, "",
1592 DBUS_TYPE_INT32, &val);
1594 dbus_connection_send(connection, signal, NULL);
1595 dbus_message_unref(signal);
1597 DBG("Successfuly sent ScanDone signal");
1600 static void reply_scan_pending_device(
1601 struct connman_technology *technology, const char *ifname, int count)
1605 dbus_bool_t status = 0;
1606 connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
1608 DBG("technology %p ifname %s count %d", technology, ifname, count);
1610 list = technology->scan_pending;
1613 struct connman_scan_pending *pending_data = list->data;
1614 DBusMessage *msg = pending_data->msg;
1617 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1618 scan_type = pending_data->scan_type;
1620 if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
1623 scan_type = pending_data->scan_type;
1625 DBG("reply to %s", dbus_message_get_sender(msg));
1626 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1628 g_dbus_send_message(connection, reply);
1629 dbus_message_unref(msg);
1631 technology->scan_pending =
1632 g_slist_remove(technology->scan_pending, pending_data);
1634 g_free(pending_data->ifname);
1635 g_free(pending_data);
1638 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1639 scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1641 __connman_technology_notify_scan_changed(ifname, &status);
1642 __connman_technology_notify_scan_done(ifname, scan_type);
1645 static void __connman_technology_notify_device_detected(
1646 struct connman_technology *technology, const char *ifname, bool val)
1649 DBusMessage *signal;
1650 DBusMessageIter iter;
1651 dbus_bool_t detected = val;
1656 signal = dbus_message_new_signal(technology->path,
1657 CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
1661 dbus_message_iter_init_append(signal, &iter);
1662 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
1663 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
1665 dbus_connection_send(connection, signal, NULL);
1666 dbus_message_unref(signal);
1668 DBG("Successfuly sent DeviceDetected signal");
1671 void __connman_technology_notify_roaming_state(const char *ifname,
1672 const char *state, const char *cur_bssid, const char *dst_bssid)
1675 DBusMessage *signal;
1676 DBusMessageIter array, dict;
1678 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1679 CONNMAN_MANAGER_INTERFACE, "RoamingStateChanged");
1683 dbus_message_iter_init_append(signal, &array);
1685 connman_dbus_dict_open(&array, &dict);
1688 connman_dbus_dict_append_basic(&dict, "Interface",
1689 DBUS_TYPE_STRING, &ifname);
1691 connman_dbus_dict_append_basic(&dict, "State",
1692 DBUS_TYPE_STRING, &state);
1694 connman_dbus_dict_append_basic(&dict, "ConnectedBSSID",
1695 DBUS_TYPE_STRING, &cur_bssid);
1697 connman_dbus_dict_append_basic(&dict, "TargetBSSID",
1698 DBUS_TYPE_STRING, &dst_bssid);
1700 connman_dbus_dict_close(&array, &dict);
1702 dbus_connection_send(connection, signal, NULL);
1703 dbus_message_unref(signal);
1705 DBG("Successfully sent Roaming State Changed signal");
1709 void __connman_technology_scan_started(struct connman_device *device)
1711 DBG("device %p", device);
1712 #if defined TIZEN_EXT
1713 dbus_bool_t status = 1;
1714 const char *ifname = connman_device_get_string(device, "Interface");
1716 __connman_technology_notify_scan_changed(ifname, &status);
1720 void __connman_technology_scan_stopped(struct connman_device *device,
1721 enum connman_service_type type)
1724 struct connman_technology *technology;
1727 technology = technology_find(type);
1729 DBG("technology %p device %p", technology, device);
1734 for (list = technology->device_list; list; list = list->next) {
1735 struct connman_device *other_device = list->data;
1737 if (device == other_device)
1740 if (connman_device_get_scanning(other_device, type))
1744 #if defined TIZEN_EXT
1745 const char *ifname = connman_device_get_string(device, "Interface");
1746 reply_scan_pending_device(technology, ifname, count);
1751 reply_scan_pending(technology, 0);
1755 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1756 int result, const char *alpha2)
1758 bool regdom_set = false;
1759 struct connman_technology *technology;
1760 enum connman_service_type type;
1761 GSList *tech_drivers;
1763 type = __connman_device_get_service_type(device);
1764 technology = technology_find(type);
1771 for (tech_drivers = technology->driver_list;
1773 tech_drivers = g_slist_next(tech_drivers)) {
1774 struct connman_technology_driver *driver =
1777 if (driver->set_regdom) {
1778 driver->set_regdom(technology, alpha2);
1788 connman_technology_regdom_notify(technology, alpha2);
1791 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1793 struct connman_technology *technology = data;
1796 DBG("technology %p request from %s", technology,
1797 dbus_message_get_sender(msg));
1799 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1800 !technology->enabled)
1801 return __connman_error_permission_denied(msg);
1803 #if !defined TIZEN_EXT
1804 dbus_message_ref(msg);
1805 technology->scan_pending =
1806 g_slist_prepend(technology->scan_pending, msg);
1809 err = __connman_device_request_scan_full(technology->type);
1811 #if defined TIZEN_EXT
1812 return __connman_error_failed(msg, -err);
1814 reply_scan_pending(technology, err);
1817 #if defined TIZEN_EXT
1818 struct connman_scan_pending *pending_data =
1819 g_try_malloc0(sizeof(struct connman_scan_pending));
1821 return __connman_error_failed(msg, ENOMEM);
1823 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1824 DBG("scan_type %d", pending_data->scan_type);
1826 pending_data->msg = dbus_message_ref(msg);
1828 technology->scan_pending =
1829 g_slist_prepend(technology->scan_pending, pending_data);
1834 #if defined TIZEN_EXT
1835 static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
1837 struct connman_technology *technology = data;
1838 DBusMessageIter iter;
1842 DBG("technology %p request from %s", technology,
1843 dbus_message_get_sender(msg));
1845 if (!dbus_message_iter_init(msg, &iter))
1846 return __connman_error_invalid_arguments(msg);
1848 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1849 return __connman_error_invalid_arguments(msg);
1851 dbus_message_iter_get_basic(&iter, &ifname);
1852 DBG("Interface name %s", ifname);
1854 if (!ifname || strlen(ifname) == 0)
1855 return __connman_error_invalid_arguments(msg);
1857 err = connman_device_request_device_scan(technology->type, ifname, true);
1859 return __connman_error_failed(msg, -err);
1861 struct connman_scan_pending *pending_data =
1862 g_try_malloc0(sizeof(struct connman_scan_pending));
1864 return __connman_error_failed(msg, ENOMEM);
1866 pending_data->ifname = g_strdup(ifname);
1867 if (pending_data->ifname == NULL) {
1868 g_free(pending_data);
1869 return __connman_error_failed(msg, ENOMEM);
1872 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1873 DBG("scan_type %d", pending_data->scan_type);
1875 pending_data->msg = dbus_message_ref(msg);
1877 technology->scan_pending =
1878 g_slist_prepend(technology->scan_pending, pending_data);
1883 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1885 struct connman_technology *technology = data;
1886 GSList *specific_scan_list = NULL;
1888 const char *name = NULL;
1889 const char *freq = NULL;
1890 const char *ifname = NULL;
1891 DBusMessageIter iter, dict;
1894 DBG("technology %p request from %s", technology,
1895 dbus_message_get_sender(msg));
1897 if (!dbus_message_iter_init(msg, &iter))
1898 return __connman_error_invalid_arguments(msg);
1900 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1901 return __connman_error_invalid_arguments(msg);
1903 dbus_message_iter_recurse(&iter, &dict);
1904 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1905 DBusMessageIter entry, value2;
1909 dbus_message_iter_recurse(&dict, &entry);
1910 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1911 g_slist_free_full(specific_scan_list, g_free);
1912 return __connman_error_invalid_arguments(msg);
1915 dbus_message_iter_get_basic(&entry, &key);
1916 dbus_message_iter_next(&entry);
1918 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1919 g_slist_free_full(specific_scan_list, g_free);
1920 return __connman_error_invalid_arguments(msg);
1923 dbus_message_iter_recurse(&entry, &value2);
1924 type = dbus_message_iter_get_arg_type(&value2);
1925 if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
1927 dbus_message_iter_get_basic(&value2, &ifname);
1928 DBG("ifname %s", ifname);
1929 } else if (g_str_equal(key, "SSID")) {
1930 if (type != DBUS_TYPE_STRING) {
1931 g_slist_free_full(specific_scan_list, g_free);
1932 return __connman_error_invalid_arguments(msg);
1935 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1936 dbus_message_iter_get_basic(&value2, &name);
1937 DBG("name %s", name);
1938 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1939 } else if (g_str_equal(key, "Frequency")) {
1940 if (type != DBUS_TYPE_STRING) {
1941 g_slist_free_full(specific_scan_list, g_free);
1942 return __connman_error_invalid_arguments(msg);
1945 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1946 dbus_message_iter_get_basic(&value2, &freq);
1947 DBG("freq %s", freq);
1948 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1949 } else if (g_str_equal(key, "SSID_Mixed")) {
1950 if (type != DBUS_TYPE_STRING) {
1951 g_slist_free_full(specific_scan_list, g_free);
1952 return __connman_error_invalid_arguments(msg);
1955 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1956 dbus_message_iter_get_basic(&value2, &name);
1958 connman_multi_scan_ap_s *ap =
1959 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1961 g_strlcpy(ap->str, name, strlen(name) + 1);
1963 specific_scan_list = g_slist_append(specific_scan_list, ap);
1965 DBG("Failed to allocate memory");
1967 } else if (g_str_equal(key, "Frequency_Mixed")) {
1968 if (type != DBUS_TYPE_STRING) {
1969 g_slist_free_full(specific_scan_list, g_free);
1970 return __connman_error_invalid_arguments(msg);
1973 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1974 dbus_message_iter_get_basic(&value2, &freq);
1976 connman_multi_scan_ap_s *ap =
1977 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1979 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1981 specific_scan_list = g_slist_append(specific_scan_list, ap);
1983 DBG("Failed to allocate memory");
1985 dbus_message_iter_next(&dict);
1988 err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
1990 return __connman_error_failed(msg, -err);
1992 guint list_size = g_slist_length(specific_scan_list);
1994 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1995 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
1996 g_slist_free_full(specific_scan_list, g_free);
1998 struct connman_scan_pending *pending_data =
1999 g_try_malloc0(sizeof(struct connman_scan_pending));
2001 return __connman_error_failed(msg, ENOMEM);
2004 pending_data->ifname = g_strdup(ifname);
2005 if (pending_data->ifname == NULL) {
2006 g_free(pending_data);
2007 return __connman_error_failed(msg, ENOMEM);
2012 pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
2014 pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
2015 DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
2017 pending_data->msg = dbus_message_ref(msg);
2019 technology->scan_pending =
2020 g_slist_prepend(technology->scan_pending, pending_data);
2025 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
2028 DBusMessageIter iter, dict;
2030 struct connman_technology *technology = data;
2031 dbus_bool_t supported = false;
2032 const char *ifname = NULL;
2034 DBG("technology %p", technology);
2036 reply = dbus_message_new_method_return(msg);
2040 dbus_message_iter_init_append(reply, &iter);
2041 connman_dbus_dict_open(&iter, &dict);
2043 for (list = technology->device_list; list; list = list->next) {
2044 struct connman_device *device = list->data;
2046 supported = connman_device_get_wifi_5ghz_supported(device);
2047 ifname = connman_device_get_string(device, "Interface");
2049 DBG("ifname %s supported : %d", ifname, supported);
2050 connman_dbus_dict_append_basic(&dict, ifname,
2055 connman_dbus_dict_close(&iter, &dict);
2060 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
2063 DBusMessageIter iter, dict;
2065 struct connman_technology *technology = data;
2066 dbus_bool_t scanning = false;
2067 const char *ifname = NULL;
2069 DBG("technology %p", technology);
2071 reply = dbus_message_new_method_return(msg);
2075 dbus_message_iter_init_append(reply, &iter);
2076 connman_dbus_dict_open(&iter, &dict);
2078 for (list = technology->device_list; list; list = list->next) {
2079 struct connman_device *device = list->data;
2081 scanning = connman_device_get_scanning(device, technology->type);
2082 ifname = connman_device_get_string(device, "Interface");
2084 DBG("ifname %s scanning : %d", ifname, scanning);
2085 connman_dbus_dict_append_basic(&dict, ifname,
2090 connman_dbus_dict_close(&iter, &dict);
2095 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
2098 DBusMessageIter iter, dict;
2100 struct connman_technology *technology = data;
2101 dbus_int32_t max_scan_ssids = 0;
2102 const char *ifname = NULL;
2104 DBG("technology %p", technology);
2106 reply = dbus_message_new_method_return(msg);
2110 dbus_message_iter_init_append(reply, &iter);
2111 connman_dbus_dict_open(&iter, &dict);
2113 for (list = technology->device_list; list; list = list->next) {
2114 struct connman_device *device = list->data;
2116 max_scan_ssids = connman_device_get_max_scan_ssids(device);
2117 ifname = connman_device_get_string(device, "Interface");
2119 DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
2120 connman_dbus_dict_append_basic(&dict, ifname,
2125 connman_dbus_dict_close(&iter, &dict);
2130 static int technology_enable_device(struct connman_technology *technology,
2131 bool enable_device, const char *ifname, struct connman_device **device_out)
2136 for (list = technology->device_list; list; list = list->next) {
2137 struct connman_device *device = list->data;
2138 const char *str = connman_device_get_string(device, "Interface");
2140 if (g_strcmp0(str, ifname) != 0)
2144 err = __connman_device_enable(device);
2146 err = __connman_device_disable(device);
2148 *device_out = device;
2155 static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
2156 DBusMessage *msg, bool powered, const char *ifname)
2158 DBusMessage *reply = NULL;
2159 struct connman_device *device = NULL;
2162 err = technology_enable_device(technology, powered, ifname, &device);
2164 if (err == -EINPROGRESS) {
2166 connman_device_set_pending_reply(device, msg);
2168 } else if (err == -EALREADY) {
2170 reply = __connman_error_already_enabled(msg);
2172 reply = __connman_error_already_disabled(msg);
2174 reply = __connman_error_failed(msg, -err);
2176 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2181 static DBusMessage *set_device_power(DBusConnection *conn,
2182 DBusMessage *msg, void *data)
2184 struct connman_technology *technology = data;
2185 DBusMessageIter iter;
2190 DBG("conn %p", conn);
2192 if (!dbus_message_iter_init(msg, &iter))
2193 return __connman_error_invalid_arguments(msg);
2195 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2196 return __connman_error_invalid_arguments(msg);
2198 dbus_message_iter_get_basic(&iter, &name);
2199 dbus_message_iter_next(&iter);
2201 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
2202 return __connman_error_invalid_arguments(msg);
2204 DBG("interface name %s", name);
2208 if (len + 1 > IFNAMSIZ)
2209 return __connman_error_invalid_arguments(msg);
2211 dbus_message_iter_get_basic(&iter, &enable);
2212 DBG("powered %s", enable ? "TRUE" : "FALSE");
2214 return technology_set_device_powered(technology, msg, enable, name);
2217 static DBusMessage *set_bssid(DBusConnection *conn,
2218 DBusMessage *msg, void *data)
2220 DBusMessageIter iter;
2224 DBG("conn %p", conn);
2226 if (!dbus_message_iter_init(msg, &iter))
2227 return __connman_error_invalid_arguments(msg);
2229 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2230 return __connman_error_invalid_arguments(msg);
2232 dbus_message_iter_get_basic(&iter, &name);
2233 dbus_message_iter_next(&iter);
2235 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2236 return __connman_error_invalid_arguments(msg);
2238 dbus_message_iter_get_basic(&iter, &bssid);
2240 DBG("interface name %s bssid %s", name, bssid);
2244 if (len + 1 > IFNAMSIZ)
2245 return __connman_error_invalid_arguments(msg);
2247 set_connman_bssid(SET_BSSID, bssid, name);
2249 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2251 static struct connman_technology *technology_get(enum connman_service_type type);
2253 void technology_save_device(struct connman_device *device)
2255 struct connman_technology *technology;
2256 enum connman_service_type type;
2258 type = __connman_device_get_service_type(device);
2260 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2263 technology = technology_get(type);
2267 if (!g_slist_find(technology->device_list, device))
2272 const char *name = get_name(technology->type);
2274 DBG("technology %p type %d name %s", technology, technology->type,
2279 keyfile = __connman_storage_load_global();
2281 keyfile = g_key_file_new();
2283 identifier = g_strdup_printf("%s", name);
2287 GSList *list = NULL;
2288 gchar **ifname_list = NULL;
2289 guint dev_count = g_slist_length(technology->device_list);
2291 if (dev_count >= 1) {
2292 GString *ifname_str = g_string_new(NULL);
2295 for (list = technology->device_list; list; list = list->next) {
2296 struct connman_device *device = list->data;
2298 if (connman_device_get_powered(device)) {
2299 const char *ifname = connman_device_get_string(device, "Interface");
2301 if (ifname_str->len > 0)
2302 g_string_append_printf(ifname_str, " %s", ifname);
2304 g_string_append(ifname_str, ifname);
2308 if (ifname_str->len > 0) {
2309 ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
2310 dev_count = g_strv_length(ifname_list);
2311 g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
2312 (const gchar **) ifname_list, dev_count);
2314 technology->enable_persistent = true;
2316 g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
2317 technology->enable_persistent = false;
2320 g_strfreev(ifname_list);
2321 g_string_free(ifname_str, TRUE);
2325 g_key_file_set_boolean(keyfile, identifier, "Enable",
2326 technology->enable_persistent);
2328 g_key_file_set_boolean(keyfile, identifier, "Tethering",
2329 technology->tethering_persistent);
2331 if (technology->tethering_ident)
2332 g_key_file_set_string(keyfile, identifier,
2333 "Tethering.Identifier",
2334 technology->tethering_ident);
2336 if (technology->tethering_passphrase)
2337 g_key_file_set_string(keyfile, identifier,
2338 "Tethering.Passphrase",
2339 technology->tethering_passphrase);
2344 __connman_storage_save_global(keyfile);
2346 g_key_file_free(keyfile);
2350 #if defined TIZEN_EXT_WIFI_MESH
2351 bool __connman_technology_get_connected(enum connman_service_type type)
2353 struct connman_technology *technology;
2355 technology = technology_find(type);
2360 return technology->connected;
2363 void __connman_technology_mesh_interface_create_finished(
2364 enum connman_service_type type, bool success,
2368 struct connman_technology *technology;
2370 technology = technology_find(type);
2372 DBG("technology %p success %d", technology, success);
2377 msg = technology->mesh_dbus_msg;
2379 DBG("No pending dbus message");
2384 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2385 __connman_device_request_scan(technology->type);
2387 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
2388 ".MeshInterfaceAddFailed", "%s", error);
2389 g_dbus_send_message(connection, reply);
2390 dbus_message_unref(msg);
2391 technology->mesh_dbus_msg = NULL;
2394 void __connman_technology_mesh_interface_remove_finished(
2395 enum connman_service_type type, bool success)
2398 struct connman_technology *technology;
2400 technology = technology_find(type);
2402 DBG("technology %p success %d", technology, success);
2404 if (!technology || !technology->mesh_dbus_msg)
2407 msg = technology->mesh_dbus_msg;
2409 DBG("No pending dbus message");
2414 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2416 reply = __connman_error_failed(msg, EINVAL);
2417 g_dbus_send_message(connection, reply);
2418 dbus_message_unref(msg);
2419 technology->mesh_dbus_msg = NULL;
2422 void __connman_technology_notify_abort_scan(enum connman_service_type type,
2426 struct connman_technology *technology;
2428 technology = technology_find(type);
2430 DBG("technology %p result %d", technology, result);
2432 if (!technology || !technology->mesh_dbus_msg)
2435 msg = technology->mesh_dbus_msg;
2437 DBG("No pending dbus message");
2442 reply = __connman_error_scan_abort_failed(msg);
2444 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2446 g_dbus_send_message(connection, reply);
2447 dbus_message_unref(msg);
2448 technology->mesh_dbus_msg = NULL;
2451 static DBusMessage *mesh_commands(DBusConnection *conn,
2452 DBusMessage *msg, void *data)
2454 struct connman_technology *technology = data;
2455 DBusMessageIter iter, value, dict;
2456 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
2459 DBG("conn %p", conn);
2461 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
2462 return __connman_error_invalid_arguments(msg);
2464 if (!dbus_message_iter_init(msg, &iter))
2465 return __connman_error_invalid_arguments(msg);
2467 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2468 return __connman_error_invalid_arguments(msg);
2470 dbus_message_iter_get_basic(&iter, &cmd);
2471 dbus_message_iter_next(&iter);
2473 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
2474 return __connman_error_invalid_arguments(msg);
2476 dbus_message_iter_recurse(&iter, &value);
2478 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
2479 return __connman_error_invalid_arguments(msg);
2481 DBG("Mesh Command %s", cmd);
2482 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
2483 dbus_message_iter_recurse(&value, &dict);
2484 const char *bridge_ifname = NULL;
2485 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2486 DBusMessageIter entry, value2;
2490 dbus_message_iter_recurse(&dict, &entry);
2492 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2493 return __connman_error_invalid_arguments(msg);
2495 dbus_message_iter_get_basic(&entry, &key);
2496 dbus_message_iter_next(&entry);
2498 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2499 return __connman_error_invalid_arguments(msg);
2501 dbus_message_iter_recurse(&entry, &value2);
2503 type = dbus_message_iter_get_arg_type(&value2);
2505 if (g_str_equal(key, "Ifname")) {
2506 if (type != DBUS_TYPE_STRING)
2507 return __connman_error_invalid_arguments(msg);
2509 dbus_message_iter_get_basic(&value2, &ifname);
2510 } else if (g_str_equal(key, "ParentIfname")) {
2511 if (type != DBUS_TYPE_STRING)
2512 return __connman_error_invalid_arguments(msg);
2514 dbus_message_iter_get_basic(&value2, &parent_ifname);
2515 } else if (g_str_equal(key, "BridgeIfname")) {
2516 if (type != DBUS_TYPE_STRING)
2517 return __connman_error_invalid_arguments(msg);
2519 dbus_message_iter_get_basic(&value2, &bridge_ifname);
2521 dbus_message_iter_next(&dict);
2523 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
2524 bridge_ifname ? bridge_ifname : "NULL");
2525 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
2529 DBG("Failed to add virtual mesh interface");
2530 return __connman_error_failed(msg, -err);
2533 DBG("Successfully added virtual mesh interface");
2535 dbus_message_ref(msg);
2536 technology->mesh_dbus_msg = msg;
2538 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
2539 dbus_message_iter_recurse(&value, &dict);
2540 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2541 DBusMessageIter entry, value2;
2545 dbus_message_iter_recurse(&dict, &entry);
2547 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2548 return __connman_error_invalid_arguments(msg);
2550 dbus_message_iter_get_basic(&entry, &key);
2551 dbus_message_iter_next(&entry);
2553 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2554 return __connman_error_invalid_arguments(msg);
2556 dbus_message_iter_recurse(&entry, &value2);
2558 type = dbus_message_iter_get_arg_type(&value2);
2560 if (g_str_equal(key, "Ifname")) {
2561 if (type != DBUS_TYPE_STRING)
2562 return __connman_error_invalid_arguments(msg);
2564 dbus_message_iter_get_basic(&value2, &ifname);
2566 dbus_message_iter_next(&dict);
2568 DBG("Mesh Ifname %s", ifname);
2569 err = __connman_mesh_remove_virtual_interface(ifname);
2572 DBG("Failed to remove virtual mesh interface");
2573 return __connman_error_failed(msg, -err);
2576 DBG("Successfully removed virtual mesh interface");
2578 dbus_message_ref(msg);
2579 technology->mesh_dbus_msg = msg;
2581 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
2582 struct connman_mesh *connman_mesh;
2583 const char *name = NULL;
2584 const char *sec_type = NULL;
2585 const char *mesh_ifname = NULL;
2586 char *identifier, *group, *address;
2587 unsigned int freq = 0;
2588 unsigned int ieee80211w = 0;
2591 dbus_message_iter_recurse(&value, &dict);
2592 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2593 DBusMessageIter entry, value2;
2597 dbus_message_iter_recurse(&dict, &entry);
2599 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2600 return __connman_error_invalid_arguments(msg);
2602 dbus_message_iter_get_basic(&entry, &key);
2603 dbus_message_iter_next(&entry);
2605 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2606 return __connman_error_invalid_arguments(msg);
2608 dbus_message_iter_recurse(&entry, &value2);
2610 type = dbus_message_iter_get_arg_type(&value2);
2612 if (g_str_equal(key, "Name")) {
2613 if (type != DBUS_TYPE_STRING)
2614 return __connman_error_invalid_arguments(msg);
2616 dbus_message_iter_get_basic(&value2, &name);
2617 } else if (g_str_equal(key, "Frequency")) {
2618 if (type != DBUS_TYPE_UINT16)
2619 return __connman_error_invalid_arguments(msg);
2621 dbus_message_iter_get_basic(&value2, &freq);
2622 } else if (g_str_equal(key, "Security")) {
2623 if (type != DBUS_TYPE_STRING)
2624 return __connman_error_invalid_arguments(msg);
2626 dbus_message_iter_get_basic(&value2, &sec_type);
2627 } else if (g_str_equal(key, "Pmf")) {
2628 if (type != DBUS_TYPE_UINT16)
2629 return __connman_error_invalid_arguments(msg);
2631 dbus_message_iter_get_basic(&value2, &ieee80211w);
2633 dbus_message_iter_next(&dict);
2636 if (name == NULL || sec_type == NULL || freq == 0)
2637 return __connman_error_invalid_arguments(msg);
2639 DBG("Name %s Frequency %d Security type %s Pmf %u",
2640 name, freq, sec_type, ieee80211w);
2642 if (g_strcmp0(sec_type, "none") != 0 &&
2643 g_strcmp0(sec_type, "sae") != 0) {
2644 DBG("Unsupported security");
2645 return __connman_error_invalid_arguments(msg);
2648 mesh_ifname = connman_mesh_get_interface_name();
2650 if (!connman_mesh_is_interface_created()) {
2651 DBG("Mesh interface doesn't exists");
2652 return __connman_error_invalid_command(msg);
2655 str = g_string_sized_new((strlen(name) * 2) + 24);
2657 for (i = 0; name[i]; i++)
2658 g_string_append_printf(str, "%02x", name[i]);
2660 g_string_append_printf(str, "_mesh");
2662 if (g_strcmp0(sec_type, "none") == 0)
2663 g_string_append_printf(str, "_none");
2664 else if (g_strcmp0(sec_type, "sae") == 0)
2665 g_string_append_printf(str, "_sae");
2667 group = g_string_free(str, FALSE);
2669 identifier = connman_inet_ifaddr(mesh_ifname);
2670 address = connman_inet_ifname2addr(mesh_ifname);
2672 connman_mesh = connman_mesh_create(identifier, group);
2673 connman_mesh_set_name(connman_mesh, name);
2674 connman_mesh_set_address(connman_mesh, address);
2675 connman_mesh_set_security(connman_mesh, sec_type);
2676 connman_mesh_set_frequency(connman_mesh, freq);
2677 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
2678 connman_mesh_set_peer_type(connman_mesh,
2679 CONNMAN_MESH_PEER_TYPE_CREATED);
2680 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
2682 connman_mesh_register(connman_mesh);
2686 DBG("Successfully Created Mesh Network");
2687 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2689 } else if (g_str_equal(cmd, "AbortScan")) {
2690 DBG("Abort Scan method");
2691 err = __connman_device_abort_scan(technology->type);
2693 DBG("Failed to abort scan");
2694 return __connman_error_failed(msg, -err);
2697 DBG("Successfully requested to abort scan");
2698 dbus_message_ref(msg);
2699 technology->mesh_dbus_msg = msg;
2701 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
2702 const char *name = NULL;
2703 unsigned int freq = 0;
2704 dbus_message_iter_recurse(&value, &dict);
2705 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2706 DBusMessageIter entry, value2;
2710 dbus_message_iter_recurse(&dict, &entry);
2712 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2713 return __connman_error_invalid_arguments(msg);
2715 dbus_message_iter_get_basic(&entry, &key);
2716 dbus_message_iter_next(&entry);
2718 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2719 return __connman_error_invalid_arguments(msg);
2721 dbus_message_iter_recurse(&entry, &value2);
2723 type = dbus_message_iter_get_arg_type(&value2);
2725 if (g_str_equal(key, "Name")) {
2726 if (type != DBUS_TYPE_STRING)
2727 return __connman_error_invalid_arguments(msg);
2729 dbus_message_iter_get_basic(&value2, &name);
2730 } else if (g_str_equal(key, "Frequency")) {
2731 if (type != DBUS_TYPE_UINT16)
2732 return __connman_error_invalid_arguments(msg);
2734 dbus_message_iter_get_basic(&value2, &freq);
2736 dbus_message_iter_next(&dict);
2739 DBG("MeshID %s Frequency %d sender %s", name, freq,
2740 dbus_message_get_sender(msg));
2742 struct connman_scan_pending *pending_data =
2743 g_try_malloc0(sizeof(struct connman_scan_pending));
2745 return __connman_error_failed(msg, ENOMEM);
2747 pending_data->msg = dbus_message_ref(msg);
2749 technology->scan_pending =
2750 g_slist_prepend(technology->scan_pending, pending_data);
2752 err = __connman_device_request_mesh_specific_scan(technology->type,
2755 reply_scan_pending(technology, err);
2757 DBG("Successfully requested to scan specific Mesh Network");
2759 } else if (g_str_equal(cmd, "SetMeshGate")) {
2760 unsigned int hwmp_rootmode = 0;
2761 bool gate_announce = false;
2762 unsigned int stp = 0;
2764 dbus_message_iter_recurse(&value, &dict);
2765 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2766 DBusMessageIter entry, value2;
2770 dbus_message_iter_recurse(&dict, &entry);
2772 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2773 return __connman_error_invalid_arguments(msg);
2775 dbus_message_iter_get_basic(&entry, &key);
2776 dbus_message_iter_next(&entry);
2778 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2779 return __connman_error_invalid_arguments(msg);
2781 dbus_message_iter_recurse(&entry, &value2);
2783 type = dbus_message_iter_get_arg_type(&value2);
2785 if (g_str_equal(key, "GateAnnounce")) {
2786 if (type != DBUS_TYPE_BOOLEAN)
2787 return __connman_error_invalid_arguments(msg);
2789 dbus_message_iter_get_basic(&value2, &gate_announce);
2790 } else if (g_str_equal(key, "HWMPRootMode")) {
2791 if (type != DBUS_TYPE_UINT16)
2792 return __connman_error_invalid_arguments(msg);
2794 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
2795 } else if (g_str_equal(key, "STP")) {
2796 if (type != DBUS_TYPE_UINT16)
2797 return __connman_error_invalid_arguments(msg);
2799 dbus_message_iter_get_basic(&value2, &stp);
2801 dbus_message_iter_next(&dict);
2804 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
2805 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
2807 err = __connman_mesh_set_stp_gate_announce(gate_announce,
2812 return __connman_error_failed(msg, -err);
2814 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2816 return __connman_error_invalid_command(msg);
2821 static const GDBusMethodTable technology_methods[] = {
2822 { GDBUS_DEPRECATED_METHOD("GetProperties",
2823 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
2825 { GDBUS_ASYNC_METHOD("SetProperty",
2826 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2827 NULL, set_property) },
2828 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
2829 #if defined TIZEN_EXT
2830 { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
2831 NULL, scan_device) },
2832 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
2833 NULL, specific_scan) },
2834 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
2836 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2837 get_5ghz_supported) },
2838 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2839 get_max_scan_ssid) },
2840 { GDBUS_ASYNC_METHOD("SetDevicePower",
2841 GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
2842 NULL, set_device_power) },
2843 { GDBUS_ASYNC_METHOD("SetBSSID",
2844 GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
2847 #if defined TIZEN_EXT_WIFI_MESH
2848 { GDBUS_ASYNC_METHOD("MeshCommands",
2849 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2850 NULL, mesh_commands) },
2855 static const GDBusSignalTable technology_signals[] = {
2856 { GDBUS_SIGNAL("PropertyChanged",
2857 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2858 #if defined TIZEN_EXT
2859 { GDBUS_SIGNAL("DeviceChanged",
2860 GDBUS_ARGS({ "device_property", "a{sv}" })) },
2861 { GDBUS_SIGNAL("DeviceDetected",
2862 GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
2867 static bool technology_dbus_register(struct connman_technology *technology)
2869 if (technology->dbus_registered ||
2870 (technology->rfkill_driven &&
2871 technology->hardblocked))
2874 if (!g_dbus_register_interface(connection, technology->path,
2875 CONNMAN_TECHNOLOGY_INTERFACE,
2876 technology_methods, technology_signals,
2877 NULL, technology, NULL)) {
2878 connman_error("Failed to register %s", technology->path);
2882 technology_added_signal(technology);
2883 technology->dbus_registered = true;
2888 static void technology_dbus_unregister(struct connman_technology *technology)
2890 if (!technology->dbus_registered)
2893 technology_removed_signal(technology);
2894 g_dbus_unregister_interface(connection, technology->path,
2895 CONNMAN_TECHNOLOGY_INTERFACE);
2897 technology->dbus_registered = false;
2900 static void technology_put(struct connman_technology *technology)
2902 DBG("technology %p", technology);
2904 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2907 reply_scan_pending(technology, -EINTR);
2909 while (technology->driver_list) {
2910 struct connman_technology_driver *driver;
2912 driver = technology->driver_list->data;
2915 driver->remove(technology);
2917 technology->driver_list =
2918 g_slist_delete_link(technology->driver_list,
2919 technology->driver_list);
2922 technology_list = g_slist_remove(technology_list, technology);
2924 technology_dbus_unregister(technology);
2926 g_slist_free(technology->device_list);
2928 if (technology->pending_reply) {
2929 dbus_message_unref(technology->pending_reply);
2930 technology->pending_reply = NULL;
2931 g_source_remove(technology->pending_timeout);
2932 technology->pending_timeout = 0;
2935 g_strfreev(technology->enabled_devices);
2937 g_free(technology->path);
2938 g_free(technology->regdom);
2939 g_free(technology->tethering_ident);
2940 g_free(technology->tethering_passphrase);
2944 static struct connman_technology *technology_get(enum connman_service_type type)
2946 GSList *tech_drivers = NULL;
2947 struct connman_technology_driver *driver;
2948 struct connman_technology *technology;
2952 DBG("type %d", type);
2954 str = __connman_service_type2string(type);
2958 technology = technology_find(type);
2960 #if defined TIZEN_EXT_WIFI_MESH
2961 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2962 type != CONNMAN_SERVICE_TYPE_MESH)
2964 if (type != CONNMAN_SERVICE_TYPE_P2P)
2966 __sync_fetch_and_add(&technology->refcount, 1);
2970 /* First check if we have a driver for this technology type */
2971 for (list = driver_list; list; list = list->next) {
2972 driver = list->data;
2974 if (driver->type == type) {
2975 DBG("technology %p driver %p", technology, driver);
2976 tech_drivers = g_slist_append(tech_drivers, driver);
2980 if (!tech_drivers) {
2981 DBG("No matching drivers found for %s.",
2982 __connman_service_type2string(type));
2986 technology = g_try_new0(struct connman_technology, 1);
2990 technology->refcount = 1;
2991 technology->type = type;
2992 technology->path = g_strdup_printf("%s/technology/%s",
2995 #if defined TIZEN_EXT_WIFI_MESH
2996 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2997 struct connman_technology *wifi;
2999 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
3001 technology->enabled = wifi->enabled;
3005 technology_load(technology);
3006 technology_list = g_slist_prepend(technology_list, technology);
3007 technology->driver_list = tech_drivers;
3009 for (list = tech_drivers; list; list = list->next) {
3010 driver = list->data;
3012 if (driver->probe && driver->probe(technology) < 0)
3013 DBG("Driver probe failed for technology %p",
3017 if (!technology_dbus_register(technology)) {
3018 technology_put(technology);
3022 if (type == CONNMAN_SERVICE_TYPE_P2P) {
3023 struct connman_technology *wifi;
3026 enable = technology->enable_persistent;
3028 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
3030 enable = wifi->enabled;
3032 technology_affect_devices(technology, enable);
3035 DBG("technology %p %s", technology, get_name(technology->type));
3040 int connman_technology_driver_register(struct connman_technology_driver *driver)
3043 struct connman_device *device;
3044 enum connman_service_type type;
3046 for (list = driver_list; list; list = list->next) {
3047 if (list->data == driver)
3051 DBG("Registering %s driver", driver->name);
3053 driver_list = g_slist_insert_sorted(driver_list, driver,
3057 * Check for technology less devices if this driver
3058 * can service any of them.
3060 for (list = techless_device_list; list; list = list->next) {
3061 device = list->data;
3063 type = __connman_device_get_service_type(device);
3064 if (type != driver->type)
3067 techless_device_list = g_slist_remove(techless_device_list,
3070 __connman_technology_add_device(device);
3073 /* Check for orphaned rfkill switches. */
3074 g_hash_table_foreach(rfkill_list, rfkill_check,
3075 GINT_TO_POINTER(driver->type));
3078 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3079 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
3083 #if defined TIZEN_EXT_WIFI_MESH
3084 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3085 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
3093 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
3095 GSList *list, *tech_drivers;
3096 struct connman_technology *technology;
3097 struct connman_technology_driver *current;
3099 DBG("Unregistering driver %p name %s", driver, driver->name);
3101 for (list = technology_list; list; list = list->next) {
3102 technology = list->data;
3104 for (tech_drivers = technology->driver_list; tech_drivers;
3105 tech_drivers = g_slist_next(tech_drivers)) {
3106 current = tech_drivers->data;
3107 if (driver != current)
3111 driver->remove(technology);
3113 technology->driver_list =
3114 g_slist_remove(technology->driver_list,
3120 driver_list = g_slist_remove(driver_list, driver);
3122 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3123 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
3125 technology_put(technology);
3127 #if defined TIZEN_EXT_WIFI_MESH
3128 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3129 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
3131 technology_put(technology);
3136 void __connman_technology_add_interface(enum connman_service_type type,
3137 int index, const char *ident)
3139 struct connman_technology *technology;
3140 GSList *tech_drivers;
3141 struct connman_technology_driver *driver;
3145 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3146 case CONNMAN_SERVICE_TYPE_SYSTEM:
3148 case CONNMAN_SERVICE_TYPE_ETHERNET:
3149 case CONNMAN_SERVICE_TYPE_WIFI:
3150 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3151 case CONNMAN_SERVICE_TYPE_CELLULAR:
3152 case CONNMAN_SERVICE_TYPE_GPS:
3153 case CONNMAN_SERVICE_TYPE_VPN:
3154 case CONNMAN_SERVICE_TYPE_GADGET:
3155 case CONNMAN_SERVICE_TYPE_P2P:
3156 #if defined TIZEN_EXT_WIFI_MESH
3157 case CONNMAN_SERVICE_TYPE_MESH:
3162 name = connman_inet_ifname(index);
3163 connman_info("Adding interface %s [ %s ]", name,
3164 __connman_service_type2string(type));
3166 technology = technology_find(type);
3171 for (tech_drivers = technology->driver_list; tech_drivers;
3172 tech_drivers = g_slist_next(tech_drivers)) {
3173 driver = tech_drivers->data;
3175 if (driver->add_interface)
3176 driver->add_interface(technology, index, name, ident);
3180 * At this point we can try to enable tethering automatically as
3181 * now the interfaces are set properly.
3183 if (technology->tethering_persistent)
3184 enable_tethering(technology);
3190 void __connman_technology_remove_interface(enum connman_service_type type,
3191 int index, const char *ident)
3193 struct connman_technology *technology;
3194 GSList *tech_drivers;
3195 struct connman_technology_driver *driver;
3199 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3200 case CONNMAN_SERVICE_TYPE_SYSTEM:
3202 case CONNMAN_SERVICE_TYPE_ETHERNET:
3203 case CONNMAN_SERVICE_TYPE_WIFI:
3204 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3205 case CONNMAN_SERVICE_TYPE_CELLULAR:
3206 case CONNMAN_SERVICE_TYPE_GPS:
3207 case CONNMAN_SERVICE_TYPE_VPN:
3208 case CONNMAN_SERVICE_TYPE_GADGET:
3209 case CONNMAN_SERVICE_TYPE_P2P:
3210 #if defined TIZEN_EXT_WIFI_MESH
3211 case CONNMAN_SERVICE_TYPE_MESH:
3216 name = connman_inet_ifname(index);
3217 connman_info("Remove interface %s [ %s ]", name,
3218 __connman_service_type2string(type));
3221 technology = technology_find(type);
3226 for (tech_drivers = technology->driver_list; tech_drivers;
3227 tech_drivers = g_slist_next(tech_drivers)) {
3228 driver = tech_drivers->data;
3230 if (driver->remove_interface)
3231 driver->remove_interface(technology, index);
3235 int __connman_technology_add_device(struct connman_device *device)
3237 struct connman_technology *technology;
3238 enum connman_service_type type;
3240 type = __connman_device_get_service_type(device);
3242 DBG("device %p type %s", device, get_name(type));
3244 technology = technology_get(type);
3247 * Since no driver can be found for this device at the moment we
3248 * add it to the techless device list.
3250 techless_device_list = g_slist_prepend(techless_device_list,
3256 __sync_synchronize();
3257 if (technology->rfkill_driven) {
3258 if (technology->enabled)
3259 __connman_device_enable(device);
3261 __connman_device_disable(device);
3266 if (technology->enable_persistent &&
3267 !global_offlinemode) {
3268 #if defined TIZEN_EXT
3271 if (technology->enabled_devices && type == CONNMAN_SERVICE_TYPE_WIFI) {
3274 const char *ifname = connman_device_get_string(device, "Interface");
3276 while (technology->enabled_devices[i]) {
3277 if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
3286 err = __connman_device_enable(device);
3288 int err = __connman_device_enable(device);
3291 * connman_technology_add_device() calls __connman_device_enable()
3292 * but since the device is already enabled, the call does not
3293 * propagate through to connman_technology_enabled via
3294 * connman_device_set_powered.
3296 if (err == -EALREADY)
3297 __connman_technology_enabled(type);
3299 /* if technology persistent state is offline */
3300 if (!technology->enable_persistent)
3301 __connman_device_disable(device);
3304 technology->device_list = g_slist_prepend(technology->device_list,
3307 #if defined TIZEN_EXT
3308 technology_save_device(device);
3310 const char *ifname = connman_device_get_string(device, "Interface");
3311 __connman_technology_notify_device_detected(technology, ifname, true);
3313 connman_device_set_mac_policy(device, technology->mac_policy);
3314 connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy);
3315 connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime);
3320 int __connman_technology_remove_device(struct connman_device *device)
3322 struct connman_technology *technology;
3323 enum connman_service_type type;
3325 DBG("device %p", device);
3327 type = __connman_device_get_service_type(device);
3329 technology = technology_find(type);
3331 techless_device_list = g_slist_remove(techless_device_list,
3336 technology->device_list = g_slist_remove(technology->device_list,
3339 #if defined TIZEN_EXT
3340 technology_save_device(device);
3342 const char *ifname = connman_device_get_string(device, "Interface");
3343 __connman_technology_notify_device_detected(technology, ifname, false);
3346 if (technology->tethering)
3347 set_tethering(technology, false);
3349 technology_put(technology);
3354 int __connman_technology_enabled(enum connman_service_type type)
3356 struct connman_technology *technology;
3358 technology = technology_find(type);
3362 DBG("technology %p type %s rfkill %d enabled %d", technology,
3363 get_name(type), technology->rfkill_driven,
3364 technology->enabled);
3366 #if !defined TIZEN_EXT
3367 if (technology->rfkill_driven) {
3368 if (technology->tethering_persistent)
3369 enable_tethering(technology);
3374 return technology_enabled(technology);
3377 int __connman_technology_disabled(enum connman_service_type type)
3379 struct connman_technology *technology;
3382 technology = technology_find(type);
3386 #if !defined TIZEN_EXT
3387 if (technology->rfkill_driven)
3391 for (list = technology->device_list; list; list = list->next) {
3392 struct connman_device *device = list->data;
3394 if (connman_device_get_powered(device))
3398 return technology_disabled(technology);
3401 int __connman_technology_set_offlinemode(bool offlinemode)
3404 int err = -EINVAL, enabled_tech_count = 0;
3406 if (global_offlinemode == offlinemode)
3409 DBG("offlinemode %s", offlinemode ? "On" : "Off");
3412 * This is a bit tricky. When you set offlinemode, there is no
3413 * way to differentiate between attempting offline mode and
3414 * resuming offlinemode from last saved profile. We need that
3415 * information in rfkill_update, otherwise it falls back on the
3416 * technology's persistent state. Hence we set the offline mode here
3417 * but save it & call the notifier only if it is successful.
3420 global_offlinemode = offlinemode;
3422 /* Traverse technology list, enable/disable each technology. */
3423 for (list = technology_list; list; list = list->next) {
3424 struct connman_technology *technology = list->data;
3427 err = technology_disable(technology);
3429 if (technology->hardblocked)
3432 if (technology->enable_persistent) {
3433 err = technology_enable(technology);
3434 enabled_tech_count++;
3439 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
3440 (err == -EINVAL && enabled_tech_count == 0)) {
3441 connman_technology_save_offlinemode();
3442 __connman_notifier_offlinemode(offlinemode);
3444 global_offlinemode = connman_technology_load_offlinemode();
3449 #if defined TIZEN_EXT_WIFI_MESH
3450 static gboolean __add_ethernet_to_bridge(gpointer data)
3453 __connman_mesh_add_ethernet_to_bridge();
3458 void __connman_technology_set_connected(enum connman_service_type type,
3461 struct connman_technology *technology;
3464 technology = technology_find(type);
3468 DBG("technology %p connected %d", technology, connected);
3470 technology->connected = connected;
3472 #if defined TIZEN_EXT_WIFI_MESH
3473 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
3474 g_idle_add(__add_ethernet_to_bridge, NULL);
3478 connman_dbus_property_changed_basic(technology->path,
3479 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
3480 DBUS_TYPE_BOOLEAN, &val);
3483 static bool technology_apply_rfkill_change(struct connman_technology *technology,
3488 bool hardblock_changed = false;
3490 GList *start, *list;
3492 DBG("technology %p --> %d/%d vs %d/%d",
3493 technology, softblock, hardblock,
3494 technology->softblocked, technology->hardblocked);
3496 if (technology->hardblocked == hardblock)
3497 goto softblock_change;
3499 if (!(new_rfkill && !hardblock)) {
3500 start = g_hash_table_get_values(rfkill_list);
3502 for (list = start; list; list = list->next) {
3503 struct connman_rfkill *rfkill = list->data;
3505 if (rfkill->type != technology->type)
3508 if (rfkill->hardblock != hardblock)
3516 goto softblock_change;
3518 technology->hardblocked = hardblock;
3519 hardblock_changed = true;
3522 if (!apply && technology->softblocked != softblock)
3526 return technology->hardblocked;
3528 technology->softblocked = softblock;
3530 if (technology->hardblocked ||
3531 technology->softblocked) {
3532 if (technology_disabled(technology) != -EALREADY)
3533 technology_affect_devices(technology, false);
3534 } else if (!technology->hardblocked &&
3535 !technology->softblocked) {
3536 if (technology_enabled(technology) != -EALREADY)
3537 technology_affect_devices(technology, true);
3540 if (hardblock_changed) {
3541 if (technology->hardblocked) {
3542 DBG("%s is switched off.", get_name(technology->type));
3543 technology_dbus_unregister(technology);
3545 DBG("%s is switched on.", get_name(technology->type));
3546 technology_dbus_register(technology);
3548 if (global_offlinemode)
3549 __connman_rfkill_block(technology->type, true);
3553 return technology->hardblocked;
3556 int __connman_technology_add_rfkill(unsigned int index,
3557 enum connman_service_type type,
3561 struct connman_technology *technology;
3562 struct connman_rfkill *rfkill;
3564 DBG("index %u type %d soft %u hard %u", index, type,
3565 softblock, hardblock);
3567 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3571 rfkill = g_try_new0(struct connman_rfkill, 1);
3575 rfkill->index = index;
3576 rfkill->type = type;
3577 rfkill->softblock = softblock;
3578 rfkill->hardblock = hardblock;
3580 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
3583 #if defined TIZEN_EXT
3584 /* Fix Svace Issue [WGID: 1348]. */
3587 technology = technology_get(type);
3588 /* If there is no driver for this type, ignore it. */
3592 technology->rfkill_driven = true;
3594 #if !defined TIZEN_EXT
3595 /* If hardblocked, there is no need to handle softblocked state */
3596 if (technology_apply_rfkill_change(technology,
3597 softblock, hardblock, true))
3601 if (global_offlinemode)
3605 * Depending on softblocked state we unblock/block according to
3606 * offlinemode and persistente state.
3608 if (technology->softblocked &&
3609 technology->enable_persistent)
3610 return __connman_rfkill_block(type, false);
3611 else if (!technology->softblocked &&
3612 !technology->enable_persistent)
3613 return __connman_rfkill_block(type, true);
3618 int __connman_technology_update_rfkill(unsigned int index,
3619 enum connman_service_type type,
3623 struct connman_technology *technology;
3624 struct connman_rfkill *rfkill;
3626 DBG("index %u soft %u hard %u", index, softblock, hardblock);
3628 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3632 if (rfkill->softblock == softblock &&
3633 rfkill->hardblock == hardblock)
3636 rfkill->softblock = softblock;
3637 rfkill->hardblock = hardblock;
3639 technology = technology_find(type);
3640 /* If there is no driver for this type, ignore it. */
3644 technology_apply_rfkill_change(technology, softblock, hardblock,
3647 if (technology->hardblocked)
3648 DBG("%s hardblocked", get_name(technology->type));
3650 DBG("%s is%s softblocked", get_name(technology->type),
3651 technology->softblocked ? "" : " not");
3656 int __connman_technology_remove_rfkill(unsigned int index,
3657 enum connman_service_type type)
3659 struct connman_technology *technology;
3660 struct connman_rfkill *rfkill;
3662 DBG("index %u", index);
3664 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3668 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
3670 technology = technology_find(type);
3674 technology_apply_rfkill_change(technology,
3675 technology->softblocked, !technology->hardblocked, false);
3677 technology_put(technology);
3682 int __connman_technology_init(void)
3686 connection = connman_dbus_get_connection();
3688 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3691 global_offlinemode = connman_technology_load_offlinemode();
3693 /* This will create settings file if it is missing */
3694 connman_technology_save_offlinemode();
3699 void __connman_technology_cleanup(void)
3703 while (technology_list) {
3704 struct connman_technology *technology = technology_list->data;
3705 technology_list = g_slist_remove(technology_list, technology);
3706 technology_put(technology);
3709 g_hash_table_destroy(rfkill_list);
3711 dbus_connection_unref(connection);