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 g_key_file_set_string(keyfile, identifier,
221 "Tethering.Passphrase",
222 technology->tethering_passphrase);
225 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
226 g_key_file_set_uint64(keyfile, identifier, "MacPolicy",
227 technology->mac_policy);
229 g_key_file_set_uint64(keyfile, identifier, "PreassocMacPolicy",
230 technology->preassoc_mac_policy);
232 g_key_file_set_uint64(keyfile, identifier, "RandomMacLifetime",
233 technology->random_mac_lifetime);
235 #endif /* TIZEN_EXT */
240 __connman_storage_save_global(keyfile);
242 g_key_file_free(keyfile);
245 static void tethering_changed(struct connman_technology *technology)
247 dbus_bool_t tethering = technology->tethering;
249 connman_dbus_property_changed_basic(technology->path,
250 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
251 DBUS_TYPE_BOOLEAN, &tethering);
253 technology_save(technology);
256 int connman_technology_tethering_notify(struct connman_technology *technology,
261 DBG("technology %p enabled %u", technology, enabled);
263 if (technology->tethering == enabled)
267 err = __connman_tethering_set_enabled();
271 __connman_tethering_set_disabled();
273 technology->tethering = enabled;
274 tethering_changed(technology);
279 static int set_tethering(struct connman_technology *technology,
282 int result = -EOPNOTSUPP;
284 const char *ident, *passphrase, *bridge;
285 GSList *tech_drivers;
287 ident = technology->tethering_ident;
288 passphrase = technology->tethering_passphrase;
290 __sync_synchronize();
291 if (!technology->enabled)
294 bridge = __connman_tethering_get_bridge();
298 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
299 (!ident || !passphrase))
302 for (tech_drivers = technology->driver_list; tech_drivers;
303 tech_drivers = g_slist_next(tech_drivers)) {
304 struct connman_technology_driver *driver = tech_drivers->data;
306 if (!driver || !driver->set_tethering)
309 err = driver->set_tethering(technology, ident, passphrase,
312 if (result == -EINPROGRESS)
315 if (err == -EINPROGRESS || err == 0)
322 void connman_technology_regdom_notify(struct connman_technology *technology,
328 connman_error("Failed to set regulatory domain");
330 DBG("Regulatory domain set to %s", alpha2);
332 g_free(technology->regdom);
333 technology->regdom = g_strdup(alpha2);
336 static int set_regdom_by_device(struct connman_technology *technology,
341 for (list = technology->device_list; list; list = list->next) {
342 struct connman_device *device = list->data;
344 if (connman_device_set_regdom(device, alpha2) != 0)
351 int connman_technology_set_regdom(const char *alpha2)
353 GSList *list, *tech_drivers;
355 for (list = technology_list; list; list = list->next) {
356 struct connman_technology *technology = list->data;
358 if (set_regdom_by_device(technology, alpha2) != 0) {
360 for (tech_drivers = technology->driver_list;
362 tech_drivers = g_slist_next(tech_drivers)) {
364 struct connman_technology_driver *driver =
367 if (driver->set_regdom)
368 driver->set_regdom(technology, alpha2);
376 static struct connman_technology *technology_find(enum connman_service_type type)
380 DBG("type %d", type);
382 for (list = technology_list; list; list = list->next) {
383 struct connman_technology *technology = list->data;
385 if (technology->type == type)
392 enum connman_service_type connman_technology_get_type
393 (struct connman_technology *technology)
396 return CONNMAN_SERVICE_TYPE_UNKNOWN;
398 return technology->type;
401 bool connman_technology_get_wifi_tethering(const char **ssid,
404 struct connman_technology *technology;
411 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
415 if (!technology->tethering)
418 *ssid = technology->tethering_ident;
419 *psk = technology->tethering_passphrase;
424 #if defined TIZEN_EXT
425 const char *connman_techonology_get_path(enum connman_service_type type)
427 struct connman_technology *technology = technology_find(type);
432 return technology->path;
436 static void free_rfkill(gpointer data)
438 struct connman_rfkill *rfkill = data;
443 static void technology_load(struct connman_technology *technology)
447 GError *error = NULL;
448 bool enable, need_saving = false;
450 DBG("technology %p", technology);
452 keyfile = __connman_storage_load_global();
453 /* Fallback on disabling technology if file not found. */
455 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
456 /* We enable ethernet by default */
457 technology->enable_persistent = true;
459 technology->enable_persistent = false;
463 identifier = g_strdup_printf("%s", get_name(technology->type));
469 technology->enabled_devices = g_key_file_get_string_list(keyfile,
470 identifier, "Enable.Devices", &length, NULL);
471 if (technology->enabled_devices && length == 0) {
472 g_strfreev(technology->enabled_devices);
473 technology->enabled_devices = NULL;
477 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
479 technology->enable_persistent = enable;
481 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
482 technology->enable_persistent = true;
484 technology->enable_persistent = false;
487 g_clear_error(&error);
490 enable = g_key_file_get_boolean(keyfile, identifier,
491 "Tethering", &error);
493 technology->tethering_persistent = enable;
496 g_clear_error(&error);
500 technology_save(technology);
502 technology->tethering_ident = g_key_file_get_string(keyfile,
503 identifier, "Tethering.Identifier", NULL);
505 technology->tethering_passphrase = g_key_file_get_string(keyfile,
506 identifier, "Tethering.Passphrase", NULL);
509 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
510 unsigned int val = 0;
512 val = g_key_file_get_uint64(keyfile,
513 identifier, "MacPolicy", NULL);
515 technology->mac_policy = val;
517 technology->mac_policy = 0;
519 val = g_key_file_get_uint64(keyfile,
520 identifier, "PreassocMacPolicy", NULL);
522 technology->preassoc_mac_policy = val;
524 technology->preassoc_mac_policy = 0;
526 val = g_key_file_get_uint64(keyfile,
527 identifier, "RandomMacLifetime", NULL);
529 technology->random_mac_lifetime = val;
531 technology->random_mac_lifetime = 60;
533 #endif /* TIZEN_EXT */
538 g_key_file_free(keyfile);
541 bool __connman_technology_get_offlinemode(void)
543 return global_offlinemode;
546 static void connman_technology_save_offlinemode(void)
549 GError *error = NULL;
552 keyfile = __connman_storage_load_global();
555 keyfile = g_key_file_new();
556 g_key_file_set_boolean(keyfile, "global",
557 "OfflineMode", global_offlinemode);
559 __connman_storage_save_global(keyfile);
562 offlinemode = g_key_file_get_boolean(keyfile, "global",
563 "OfflineMode", &error);
565 if (error || offlinemode != global_offlinemode) {
566 g_key_file_set_boolean(keyfile, "global",
567 "OfflineMode", global_offlinemode);
569 g_clear_error(&error);
571 __connman_storage_save_global(keyfile);
575 g_key_file_free(keyfile);
578 static bool connman_technology_load_offlinemode(void)
581 GError *error = NULL;
584 /* If there is a error, we enable offlinemode */
585 keyfile = __connman_storage_load_global();
589 offlinemode = g_key_file_get_boolean(keyfile, "global",
590 "OfflineMode", &error);
593 g_clear_error(&error);
596 g_key_file_free(keyfile);
601 #if defined TIZEN_EXT
602 static void append_devices(DBusMessageIter *iter, void *user_data)
606 struct connman_technology *technology = user_data;
608 for (list = technology->device_list; list; list = list->next) {
609 struct connman_device *device = list->data;
611 const char *str = connman_device_get_string(device, "Interface");
612 struct connman_network *network = connman_device_get_default_network(device);
613 struct connman_service *service = connman_service_lookup_from_network(network);
615 connman_dbus_dict_append_basic(iter, "Ifname",
616 DBUS_TYPE_STRING, &str);
618 val = connman_device_get_powered(device);
619 connman_dbus_dict_append_basic(iter, "Powered",
620 DBUS_TYPE_BOOLEAN, &val);
622 if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) ||
623 __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6))
628 connman_dbus_dict_append_basic(iter, "Connected",
629 DBUS_TYPE_BOOLEAN, &val);
631 str = connman_device_get_string(device, "Address");
632 connman_dbus_dict_append_basic(iter, "MAC.Address",
633 DBUS_TYPE_STRING, &str);
637 void __connman_technology_append_interfaces(DBusMessageIter *array,
638 enum connman_service_type type, const char *ifname)
641 struct connman_technology *technology = NULL;
643 for (list = technology_list; list; list = list->next) {
644 struct connman_technology *local_tech = list->data;
646 if (local_tech->type != type)
649 technology = local_tech;
656 for (list = technology->device_list; list; list = list->next) {
657 struct connman_device *device = list->data;
658 const char *str = connman_device_get_string(device, "Interface");
660 if (g_strcmp0(ifname, str) == 0)
663 dbus_message_iter_append_basic(array,
664 DBUS_TYPE_STRING, &str);
669 static void append_properties(DBusMessageIter *iter,
670 struct connman_technology *technology)
672 DBusMessageIter dict;
676 connman_dbus_dict_open(iter, &dict);
678 str = get_name(technology->type);
680 connman_dbus_dict_append_basic(&dict, "Name",
681 DBUS_TYPE_STRING, &str);
683 str = __connman_service_type2string(technology->type);
685 connman_dbus_dict_append_basic(&dict, "Type",
686 DBUS_TYPE_STRING, &str);
688 __sync_synchronize();
689 val = technology->enabled;
690 connman_dbus_dict_append_basic(&dict, "Powered",
694 val = technology->connected;
695 connman_dbus_dict_append_basic(&dict, "Connected",
699 val = technology->tethering;
700 connman_dbus_dict_append_basic(&dict, "Tethering",
704 if (technology->tethering_ident)
705 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
707 &technology->tethering_ident);
709 if (technology->tethering_passphrase)
710 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
712 &technology->tethering_passphrase);
714 connman_dbus_dict_append_basic(&dict, "MacPolicy",
716 &(technology->mac_policy));
718 connman_dbus_dict_append_basic(&dict, "PreassocMacPolicy",
720 &(technology->preassoc_mac_policy));
722 connman_dbus_dict_append_basic(&dict, "RandomMacLifetime",
724 &(technology->random_mac_lifetime));
725 #if defined TIZEN_EXT
726 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
727 connman_dbus_dict_append_dict(&dict, "Device.List",
728 append_devices, technology);
729 if (technology->regdom)
730 connman_dbus_dict_append_basic(&dict, "CountryCode",
732 &technology->regdom);
734 connman_dbus_dict_close(iter, &dict);
737 static void technology_added_signal(struct connman_technology *technology)
740 DBusMessageIter iter;
742 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
743 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
747 dbus_message_iter_init_append(signal, &iter);
748 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
750 append_properties(&iter, technology);
752 dbus_connection_send(connection, signal, NULL);
753 dbus_message_unref(signal);
756 static void technology_removed_signal(struct connman_technology *technology)
758 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
759 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
760 DBUS_TYPE_OBJECT_PATH, &technology->path,
764 static DBusMessage *get_properties(DBusConnection *conn,
765 DBusMessage *message, void *user_data)
767 struct connman_technology *technology = user_data;
769 DBusMessageIter iter;
771 reply = dbus_message_new_method_return(message);
775 dbus_message_iter_init_append(reply, &iter);
776 append_properties(&iter, technology);
781 void __connman_technology_list_struct(DBusMessageIter *array)
784 DBusMessageIter entry;
786 for (list = technology_list; list; list = list->next) {
787 struct connman_technology *technology = list->data;
789 if (!technology->path ||
790 (technology->rfkill_driven &&
791 technology->hardblocked))
794 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
796 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
798 append_properties(&entry, technology);
799 dbus_message_iter_close_container(array, &entry);
803 static gboolean technology_pending_reply(gpointer user_data)
805 struct connman_technology *technology = user_data;
808 /* Power request timed out, send ETIMEDOUT. */
809 if (technology->pending_reply) {
810 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
812 g_dbus_send_message(connection, reply);
814 dbus_message_unref(technology->pending_reply);
815 technology->pending_reply = NULL;
816 technology->pending_timeout = 0;
822 static int technology_affect_devices(struct connman_technology *technology,
825 int err = 0, err_dev;
828 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
830 __connman_technology_enabled(technology->type);
832 __connman_technology_disabled(technology->type);
836 #if defined TIZEN_EXT_WIFI_MESH
837 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
841 for (list = technology->device_list; list; list = list->next) {
842 struct connman_device *device = list->data;
845 err_dev = __connman_device_enable(device);
847 err_dev = __connman_device_disable(device);
849 if (err_dev < 0 && err_dev != -EALREADY)
856 static void powered_changed(struct connman_technology *technology)
860 if (!technology->dbus_registered)
863 if (technology->pending_reply) {
864 g_dbus_send_reply(connection,
865 technology->pending_reply, DBUS_TYPE_INVALID);
866 dbus_message_unref(technology->pending_reply);
867 technology->pending_reply = NULL;
869 g_source_remove(technology->pending_timeout);
870 technology->pending_timeout = 0;
873 __sync_synchronize();
874 enabled = technology->enabled;
875 #if defined TIZEN_EXT
876 DBG("ConnMan, Powered : %s, %s",
877 enabled ? "TRUE" : "FALSE",technology->path);
879 connman_dbus_property_changed_basic(technology->path,
880 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
881 DBUS_TYPE_BOOLEAN, &enabled);
884 static void enable_tethering(struct connman_technology *technology)
888 if (!connman_setting_get_bool("PersistentTetheringMode"))
891 ret = set_tethering(technology, true);
892 if (ret < 0 && ret != -EALREADY)
893 DBG("Cannot enable tethering yet for %s (%d/%s)",
894 get_name(technology->type),
895 -ret, strerror(-ret));
898 static int technology_enabled(struct connman_technology *technology)
900 __sync_synchronize();
901 if (technology->enabled)
904 technology->enabled = true;
906 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
907 struct connman_technology *p2p;
909 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
910 if (p2p && !p2p->enabled && p2p->enable_persistent)
911 technology_enabled(p2p);
914 if (technology->tethering_persistent)
915 enable_tethering(technology);
917 powered_changed(technology);
922 static int technology_enable(struct connman_technology *technology)
927 DBG("technology %p enable", technology);
929 __sync_synchronize();
931 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
932 struct connman_technology *wifi;
934 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
935 if (wifi && wifi->enabled)
936 return technology_enabled(technology);
940 if (technology->enabled)
943 if (technology->pending_reply)
946 if (connman_setting_get_bool("PersistentTetheringMode") &&
947 technology->tethering)
948 set_tethering(technology, true);
950 if (technology->rfkill_driven)
951 err = __connman_rfkill_block(technology->type, false);
953 err_dev = technology_affect_devices(technology, true);
955 if (!technology->rfkill_driven)
961 static int technology_disabled(struct connman_technology *technology)
963 __sync_synchronize();
964 if (!technology->enabled)
967 technology->enabled = false;
969 powered_changed(technology);
974 static int technology_disable(struct connman_technology *technology)
978 DBG("technology %p disable", technology);
980 __sync_synchronize();
982 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
983 technology->enable_persistent = false;
984 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
985 __connman_peer_disconnect_all();
986 return technology_disabled(technology);
987 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
988 struct connman_technology *p2p;
990 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
991 if (p2p && p2p->enabled) {
992 p2p->enable_persistent = true;
993 technology_disabled(p2p);
997 if (!technology->enabled)
1000 if (technology->pending_reply)
1003 if (technology->tethering)
1004 set_tethering(technology, false);
1006 err = technology_affect_devices(technology, false);
1008 if (technology->rfkill_driven)
1009 err = __connman_rfkill_block(technology->type, true);
1014 static DBusMessage *set_powered(struct connman_technology *technology,
1015 DBusMessage *msg, bool powered)
1017 DBusMessage *reply = NULL;
1020 if (technology->rfkill_driven && technology->hardblocked) {
1026 err = technology_enable(technology);
1028 err = technology_disable(technology);
1030 if (err != -EBUSY) {
1031 technology->enable_persistent = powered;
1032 technology_save(technology);
1036 if (err == -EINPROGRESS) {
1037 technology->pending_reply = dbus_message_ref(msg);
1038 technology->pending_timeout = g_timeout_add_seconds(10,
1039 technology_pending_reply, technology);
1040 } else if (err == -EALREADY) {
1042 reply = __connman_error_already_enabled(msg);
1044 reply = __connman_error_already_disabled(msg);
1046 reply = __connman_error_failed(msg, -err);
1048 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1053 #if defined TIZEN_EXT
1054 int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
1056 static int bssid_len;
1057 static const char *def_ifname = "default";
1058 static GSList *bssid_list = NULL;
1060 const char *local_ifname = ifname;
1062 struct connman_bssid_pending *bssid_info;
1064 DBG("mode: %d, ifname: %s", mode, ifname);
1067 local_ifname = def_ifname;
1069 for (list = bssid_list; list; list = list->next) {
1070 bssid_info = list->data;
1072 if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
1078 if (mode == CHECK_BSSID) {
1085 if (mode == GET_BSSID && bssid) {
1087 memcpy(bssid, bssid_info->bssid, 6);
1093 if (mode == RESET_BSSID) {
1095 bssid_list = g_slist_remove(bssid_list, bssid_info);
1096 g_free(bssid_info->ifname);
1102 if (mode != SET_BSSID || !bssid) {
1103 DBG("Invalid parameter");
1108 bssid_list = g_slist_remove(bssid_list, bssid_info);
1109 g_free(bssid_info->ifname);
1113 bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
1115 DBG("Failed to allocate memory");
1119 unsigned char *bssid_data = bssid_info->bssid;
1121 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1122 &bssid_data[0], &bssid_data[1], &bssid_data[2],
1123 &bssid_data[3], &bssid_data[4], &bssid_data[5]);
1124 if (bssid_len != 6) {
1125 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
1130 DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
1132 bssid_data[0], bssid_data[1], bssid_data[2],
1133 bssid_data[3], bssid_data[4], bssid_data[5],
1136 bssid_info->ifname = g_strdup(ifname);
1137 bssid_list = g_slist_prepend(bssid_list, bssid_info);
1142 void connman_technology_mac_policy_notify(struct connman_technology *technology,
1143 unsigned int policy)
1145 DBG("Mac polict set to %u", policy);
1147 technology->mac_policy = policy;
1148 technology_save(technology);
1151 void __connman_technology_notify_mac_policy_by_device(struct connman_device *device,
1152 int result, unsigned int policy)
1154 struct connman_technology *technology;
1155 enum connman_service_type type;
1157 type = __connman_device_get_service_type(device);
1158 technology = technology_find(type);
1163 connman_technology_mac_policy_notify(technology, policy);
1166 static DBusMessage *set_mac_policy(struct connman_technology *technology,
1167 DBusMessage *msg, unsigned int policy)
1169 DBusMessage *reply = NULL;
1171 unsigned int last_policy = technology->mac_policy;
1173 if (technology->rfkill_driven && technology->hardblocked) {
1178 for (GSList *list = technology->device_list; list; list = list->next) {
1179 struct connman_device *device = list->data;
1181 err = connman_device_set_mac_policy(device, policy);
1188 if (err != -EACCES && err != -EOPNOTSUPP) {
1189 for (GSList *list = technology->device_list; list; list = list->next) {
1190 struct connman_device *device = list->data;
1192 connman_device_set_mac_policy(device, last_policy);
1196 reply = __connman_error_failed(msg, -err);
1198 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1204 void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology,
1205 unsigned int policy)
1207 DBG("Preassoc mac polict set to %u", policy);
1209 technology->preassoc_mac_policy = policy;
1210 technology_save(technology);
1213 void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device,
1214 int result, unsigned int policy)
1216 struct connman_technology *technology;
1217 enum connman_service_type type;
1219 type = __connman_device_get_service_type(device);
1220 technology = technology_find(type);
1225 connman_technology_preassoc_mac_policy_notify(technology, policy);
1228 static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology,
1229 DBusMessage *msg, unsigned int policy)
1231 DBusMessage *reply = NULL;
1233 unsigned int last_policy = technology->preassoc_mac_policy;
1235 if (technology->rfkill_driven && technology->hardblocked) {
1240 for (GSList *list = technology->device_list; list; list = list->next) {
1241 struct connman_device *device = list->data;
1243 err = connman_device_set_preassoc_mac_policy(device, policy);
1250 if (err != -EACCES && err != -EOPNOTSUPP) {
1251 for (GSList *list = technology->device_list; list; list = list->next) {
1252 struct connman_device *device = list->data;
1254 connman_device_set_preassoc_mac_policy(device, last_policy);
1258 reply = __connman_error_failed(msg, -err);
1260 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1266 void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology,
1267 unsigned int lifetime)
1269 DBG("Random mac lifetime set to %u", lifetime);
1271 technology->random_mac_lifetime = lifetime;
1272 technology_save(technology);
1275 void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device,
1276 int result, unsigned int lifetime)
1278 struct connman_technology *technology;
1279 enum connman_service_type type;
1281 type = __connman_device_get_service_type(device);
1282 technology = technology_find(type);
1287 connman_technology_random_mac_lifetime_notify(technology, lifetime);
1290 static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology,
1291 DBusMessage *msg, unsigned int lifetime)
1293 DBusMessage *reply = NULL;
1295 unsigned int last_lifetime = technology->random_mac_lifetime;
1297 if (technology->rfkill_driven && technology->hardblocked) {
1302 for (GSList *list = technology->device_list; list; list = list->next) {
1303 struct connman_device *device = list->data;
1305 err = connman_device_set_random_mac_lifetime(device, lifetime);
1310 if (err != -EACCES && err != -EOPNOTSUPP) {
1311 for (GSList *list = technology->device_list; list; list = list->next) {
1312 struct connman_device *device = list->data;
1314 connman_device_set_random_mac_lifetime(device, last_lifetime);
1318 reply = __connman_error_failed(msg, -err);
1320 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1327 static DBusMessage *set_property(DBusConnection *conn,
1328 DBusMessage *msg, void *data)
1330 struct connman_technology *technology = data;
1331 DBusMessageIter iter, value;
1335 DBG("conn %p", conn);
1337 if (!dbus_message_iter_init(msg, &iter))
1338 return __connman_error_invalid_arguments(msg);
1340 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1341 return __connman_error_invalid_arguments(msg);
1343 dbus_message_iter_get_basic(&iter, &name);
1344 dbus_message_iter_next(&iter);
1346 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1347 return __connman_error_invalid_arguments(msg);
1349 dbus_message_iter_recurse(&iter, &value);
1351 type = dbus_message_iter_get_arg_type(&value);
1353 DBG("property %s", name);
1355 if (g_str_equal(name, "Tethering")) {
1356 dbus_bool_t tethering;
1359 if (type != DBUS_TYPE_BOOLEAN)
1360 return __connman_error_invalid_arguments(msg);
1362 if (!connman_technology_is_tethering_allowed(technology->type)) {
1363 DBG("%s tethering not allowed by config file",
1364 __connman_service_type2string(technology->type));
1365 return __connman_error_not_supported(msg);
1368 dbus_message_iter_get_basic(&value, &tethering);
1370 if (technology->tethering == tethering) {
1372 return __connman_error_already_disabled(msg);
1374 return __connman_error_already_enabled(msg);
1377 err = set_tethering(technology, tethering);
1379 return __connman_error_failed(msg, -err);
1381 technology->tethering_persistent = tethering;
1383 technology_save(technology);
1385 } else if (g_str_equal(name, "TetheringIdentifier")) {
1388 dbus_message_iter_get_basic(&value, &str);
1390 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1391 return __connman_error_not_supported(msg);
1393 if (strlen(str) < 1 || strlen(str) > 32)
1394 return __connman_error_invalid_arguments(msg);
1396 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1397 g_free(technology->tethering_ident);
1398 technology->tethering_ident = g_strdup(str);
1399 technology_save(technology);
1401 connman_dbus_property_changed_basic(technology->path,
1402 CONNMAN_TECHNOLOGY_INTERFACE,
1403 "TetheringIdentifier",
1405 &technology->tethering_ident);
1407 } else if (g_str_equal(name, "TetheringPassphrase")) {
1410 dbus_message_iter_get_basic(&value, &str);
1412 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1413 return __connman_error_not_supported(msg);
1415 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1418 return __connman_error_passphrase_required(msg);
1420 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1421 g_free(technology->tethering_passphrase);
1422 technology->tethering_passphrase = g_strdup(str);
1423 technology_save(technology);
1425 connman_dbus_property_changed_basic(technology->path,
1426 CONNMAN_TECHNOLOGY_INTERFACE,
1427 "TetheringPassphrase",
1429 &technology->tethering_passphrase);
1431 } else if (g_str_equal(name, "Powered")) {
1434 if (type != DBUS_TYPE_BOOLEAN)
1435 return __connman_error_invalid_arguments(msg);
1437 dbus_message_iter_get_basic(&value, &enable);
1439 return set_powered(technology, msg, enable);
1440 #if defined TIZEN_EXT
1441 } else if (g_str_equal(name, "SetBSSID")) {
1444 if (type != DBUS_TYPE_STRING)
1445 return __connman_error_invalid_arguments(msg);
1447 dbus_message_iter_get_basic(&value, &key);
1448 DBG("BSSID %s", key);
1449 set_connman_bssid(SET_BSSID, key, NULL);
1450 } else if (g_str_equal(name, "MacPolicy")) {
1451 dbus_uint32_t mac_policy;
1453 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1454 return __connman_error_not_supported(msg);
1456 if (type != DBUS_TYPE_UINT32)
1457 return __connman_error_invalid_arguments(msg);
1459 dbus_message_iter_get_basic(&value, &mac_policy);
1461 if (mac_policy <= 2)
1462 return set_mac_policy(technology, msg, mac_policy);
1464 return __connman_error_invalid_arguments(msg);
1466 } else if (g_str_equal(name, "PreassocMacPolicy")) {
1467 dbus_uint32_t preassoc_mac_policy;
1469 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1470 return __connman_error_not_supported(msg);
1472 if (type != DBUS_TYPE_UINT32)
1473 return __connman_error_invalid_arguments(msg);
1475 dbus_message_iter_get_basic(&value, &preassoc_mac_policy);
1477 if (preassoc_mac_policy <= 2)
1478 return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy);
1480 return __connman_error_invalid_arguments(msg);
1482 } else if (g_str_equal(name, "RandomMacLifetime")) {
1483 dbus_uint32_t random_mac_lifetime;
1485 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1486 return __connman_error_not_supported(msg);
1488 if (type != DBUS_TYPE_UINT32)
1489 return __connman_error_invalid_arguments(msg);
1491 dbus_message_iter_get_basic(&value, &random_mac_lifetime);
1493 if (random_mac_lifetime > 0)
1494 return set_random_mac_lifetime(technology, msg, random_mac_lifetime);
1496 return __connman_error_invalid_arguments(msg);
1498 } else if (g_str_equal(name, "CountryCode")) {
1501 dbus_message_iter_get_basic(&value, &str);
1502 DBG("country code %s", str);
1503 connman_technology_set_regdom(str);
1506 return __connman_error_invalid_property(msg);
1508 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1511 static void reply_scan_pending(struct connman_technology *technology, int err)
1515 DBG("technology %p err %d", technology, err);
1517 while (technology->scan_pending) {
1518 #if defined TIZEN_EXT
1519 struct connman_scan_pending *pending_data = technology->scan_pending->data;
1520 DBusMessage *msg = pending_data->msg;
1522 DBusMessage *msg = technology->scan_pending->data;
1524 DBG("reply to %s", dbus_message_get_sender(msg));
1527 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1529 reply = __connman_error_failed(msg, -err);
1530 g_dbus_send_message(connection, reply);
1531 dbus_message_unref(msg);
1533 technology->scan_pending =
1534 g_slist_delete_link(technology->scan_pending,
1535 technology->scan_pending);
1536 #if defined TIZEN_EXT
1537 g_free(pending_data->ifname);
1538 g_free(pending_data);
1543 #if defined TIZEN_EXT
1544 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1547 DBusMessage *signal;
1548 DBusMessageIter iter;
1549 dbus_bool_t result = FALSE;
1551 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1552 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1556 dbus_message_iter_init_append(signal, &iter);
1558 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1560 connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
1562 result = dbus_connection_send(connection, signal, NULL);
1563 dbus_message_unref(signal);
1565 DBG("Successfuly sent signal");
1570 void __connman_technology_notify_scan_done(const char *ifname, int val)
1573 DBusMessage *signal;
1574 DBusMessageIter iter;
1576 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1577 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1581 dbus_message_iter_init_append(signal, &iter);
1583 connman_dbus_property_append_basic(&iter, ifname,
1584 DBUS_TYPE_INT32, &val);
1586 connman_dbus_property_append_basic(&iter, "",
1587 DBUS_TYPE_INT32, &val);
1589 dbus_connection_send(connection, signal, NULL);
1590 dbus_message_unref(signal);
1592 DBG("Successfuly sent ScanDone signal");
1595 static void reply_scan_pending_device(
1596 struct connman_technology *technology, const char *ifname, int count)
1600 dbus_bool_t status = 0;
1601 connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
1603 DBG("technology %p ifname %s count %d", technology, ifname, count);
1605 list = technology->scan_pending;
1608 struct connman_scan_pending *pending_data = list->data;
1609 DBusMessage *msg = pending_data->msg;
1612 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1613 scan_type = pending_data->scan_type;
1615 if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
1618 scan_type = pending_data->scan_type;
1620 DBG("reply to %s", dbus_message_get_sender(msg));
1621 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1623 g_dbus_send_message(connection, reply);
1624 dbus_message_unref(msg);
1626 technology->scan_pending =
1627 g_slist_remove(technology->scan_pending, pending_data);
1629 g_free(pending_data->ifname);
1630 g_free(pending_data);
1633 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1634 scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1636 __connman_technology_notify_scan_changed(ifname, &status);
1637 __connman_technology_notify_scan_done(ifname, scan_type);
1640 static void __connman_technology_notify_device_detected(
1641 struct connman_technology *technology, const char *ifname, bool val)
1644 DBusMessage *signal;
1645 DBusMessageIter iter;
1646 dbus_bool_t detected = val;
1651 signal = dbus_message_new_signal(technology->path,
1652 CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
1656 dbus_message_iter_init_append(signal, &iter);
1657 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
1658 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
1660 dbus_connection_send(connection, signal, NULL);
1661 dbus_message_unref(signal);
1663 DBG("Successfuly sent DeviceDetected signal");
1667 void __connman_technology_scan_started(struct connman_device *device)
1669 DBG("device %p", device);
1670 #if defined TIZEN_EXT
1671 dbus_bool_t status = 1;
1672 const char *ifname = connman_device_get_string(device, "Interface");
1674 __connman_technology_notify_scan_changed(ifname, &status);
1678 void __connman_technology_scan_stopped(struct connman_device *device,
1679 enum connman_service_type type)
1682 struct connman_technology *technology;
1685 technology = technology_find(type);
1687 DBG("technology %p device %p", technology, device);
1692 for (list = technology->device_list; list; list = list->next) {
1693 struct connman_device *other_device = list->data;
1695 if (device == other_device)
1698 if (connman_device_get_scanning(other_device, type))
1702 #if defined TIZEN_EXT
1703 const char *ifname = connman_device_get_string(device, "Interface");
1704 reply_scan_pending_device(technology, ifname, count);
1709 reply_scan_pending(technology, 0);
1713 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1714 int result, const char *alpha2)
1716 bool regdom_set = false;
1717 struct connman_technology *technology;
1718 enum connman_service_type type;
1719 GSList *tech_drivers;
1721 type = __connman_device_get_service_type(device);
1722 technology = technology_find(type);
1729 for (tech_drivers = technology->driver_list;
1731 tech_drivers = g_slist_next(tech_drivers)) {
1732 struct connman_technology_driver *driver =
1735 if (driver->set_regdom) {
1736 driver->set_regdom(technology, alpha2);
1746 connman_technology_regdom_notify(technology, alpha2);
1749 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1751 struct connman_technology *technology = data;
1754 DBG("technology %p request from %s", technology,
1755 dbus_message_get_sender(msg));
1757 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1758 !technology->enabled)
1759 return __connman_error_permission_denied(msg);
1761 #if !defined TIZEN_EXT
1762 dbus_message_ref(msg);
1763 technology->scan_pending =
1764 g_slist_prepend(technology->scan_pending, msg);
1767 err = __connman_device_request_scan_full(technology->type);
1769 #if defined TIZEN_EXT
1770 return __connman_error_failed(msg, -err);
1772 reply_scan_pending(technology, err);
1775 #if defined TIZEN_EXT
1776 struct connman_scan_pending *pending_data =
1777 g_try_malloc0(sizeof(struct connman_scan_pending));
1779 return __connman_error_failed(msg, ENOMEM);
1781 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1782 DBG("scan_type %d", pending_data->scan_type);
1784 pending_data->msg = dbus_message_ref(msg);
1786 technology->scan_pending =
1787 g_slist_prepend(technology->scan_pending, pending_data);
1792 #if defined TIZEN_EXT
1793 static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
1795 struct connman_technology *technology = data;
1796 DBusMessageIter iter;
1800 DBG("technology %p request from %s", technology,
1801 dbus_message_get_sender(msg));
1803 if (!dbus_message_iter_init(msg, &iter))
1804 return __connman_error_invalid_arguments(msg);
1806 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1807 return __connman_error_invalid_arguments(msg);
1809 dbus_message_iter_get_basic(&iter, &ifname);
1810 DBG("Interface name %s", ifname);
1812 if (!ifname || strlen(ifname) == 0)
1813 return __connman_error_invalid_arguments(msg);
1815 err = connman_device_request_device_scan(technology->type, ifname, true);
1817 return __connman_error_failed(msg, -err);
1819 struct connman_scan_pending *pending_data =
1820 g_try_malloc0(sizeof(struct connman_scan_pending));
1822 return __connman_error_failed(msg, ENOMEM);
1824 pending_data->ifname = g_strdup(ifname);
1825 if (pending_data->ifname == NULL) {
1826 g_free(pending_data);
1827 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 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1843 struct connman_technology *technology = data;
1844 GSList *specific_scan_list = NULL;
1846 const char *name = NULL;
1847 const char *freq = NULL;
1848 const char *ifname = NULL;
1849 DBusMessageIter iter, dict;
1852 DBG("technology %p request from %s", technology,
1853 dbus_message_get_sender(msg));
1855 if (!dbus_message_iter_init(msg, &iter))
1856 return __connman_error_invalid_arguments(msg);
1858 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1859 return __connman_error_invalid_arguments(msg);
1861 dbus_message_iter_recurse(&iter, &dict);
1862 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1863 DBusMessageIter entry, value2;
1867 dbus_message_iter_recurse(&dict, &entry);
1868 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1869 g_slist_free_full(specific_scan_list, g_free);
1870 return __connman_error_invalid_arguments(msg);
1873 dbus_message_iter_get_basic(&entry, &key);
1874 dbus_message_iter_next(&entry);
1876 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1877 g_slist_free_full(specific_scan_list, g_free);
1878 return __connman_error_invalid_arguments(msg);
1881 dbus_message_iter_recurse(&entry, &value2);
1882 type = dbus_message_iter_get_arg_type(&value2);
1883 if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
1885 dbus_message_iter_get_basic(&value2, &ifname);
1886 DBG("ifname %s", ifname);
1887 } else if (g_str_equal(key, "SSID")) {
1888 if (type != DBUS_TYPE_STRING) {
1889 g_slist_free_full(specific_scan_list, g_free);
1890 return __connman_error_invalid_arguments(msg);
1893 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1894 dbus_message_iter_get_basic(&value2, &name);
1895 DBG("name %s", name);
1896 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1897 } else if (g_str_equal(key, "Frequency")) {
1898 if (type != DBUS_TYPE_STRING) {
1899 g_slist_free_full(specific_scan_list, g_free);
1900 return __connman_error_invalid_arguments(msg);
1903 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1904 dbus_message_iter_get_basic(&value2, &freq);
1905 DBG("freq %s", freq);
1906 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1907 } else if (g_str_equal(key, "SSID_Mixed")) {
1908 if (type != DBUS_TYPE_STRING) {
1909 g_slist_free_full(specific_scan_list, g_free);
1910 return __connman_error_invalid_arguments(msg);
1913 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1914 dbus_message_iter_get_basic(&value2, &name);
1916 connman_multi_scan_ap_s *ap =
1917 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1919 g_strlcpy(ap->str, name, strlen(name) + 1);
1921 specific_scan_list = g_slist_append(specific_scan_list, ap);
1923 DBG("Failed to allocate memory");
1925 } else if (g_str_equal(key, "Frequency_Mixed")) {
1926 if (type != DBUS_TYPE_STRING) {
1927 g_slist_free_full(specific_scan_list, g_free);
1928 return __connman_error_invalid_arguments(msg);
1931 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1932 dbus_message_iter_get_basic(&value2, &freq);
1934 connman_multi_scan_ap_s *ap =
1935 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1937 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1939 specific_scan_list = g_slist_append(specific_scan_list, ap);
1941 DBG("Failed to allocate memory");
1943 dbus_message_iter_next(&dict);
1946 err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
1948 return __connman_error_failed(msg, -err);
1950 guint list_size = g_slist_length(specific_scan_list);
1952 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1953 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
1954 g_slist_free_full(specific_scan_list, g_free);
1956 struct connman_scan_pending *pending_data =
1957 g_try_malloc0(sizeof(struct connman_scan_pending));
1959 return __connman_error_failed(msg, ENOMEM);
1962 pending_data->ifname = g_strdup(ifname);
1963 if (pending_data->ifname == NULL) {
1964 g_free(pending_data);
1965 return __connman_error_failed(msg, ENOMEM);
1970 pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1972 pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1973 DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
1975 pending_data->msg = dbus_message_ref(msg);
1977 technology->scan_pending =
1978 g_slist_prepend(technology->scan_pending, pending_data);
1983 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
1986 DBusMessageIter iter, dict;
1988 struct connman_technology *technology = data;
1989 dbus_bool_t supported = false;
1990 const char *ifname = NULL;
1992 DBG("technology %p", technology);
1994 reply = dbus_message_new_method_return(msg);
1998 dbus_message_iter_init_append(reply, &iter);
1999 connman_dbus_dict_open(&iter, &dict);
2001 for (list = technology->device_list; list; list = list->next) {
2002 struct connman_device *device = list->data;
2004 supported = connman_device_get_wifi_5ghz_supported(device);
2005 ifname = connman_device_get_string(device, "Interface");
2007 DBG("ifname %s supported : %d", ifname, supported);
2008 connman_dbus_dict_append_basic(&dict, ifname,
2013 connman_dbus_dict_close(&iter, &dict);
2018 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
2021 DBusMessageIter iter, dict;
2023 struct connman_technology *technology = data;
2024 dbus_bool_t scanning = false;
2025 const char *ifname = NULL;
2027 DBG("technology %p", technology);
2029 reply = dbus_message_new_method_return(msg);
2033 dbus_message_iter_init_append(reply, &iter);
2034 connman_dbus_dict_open(&iter, &dict);
2036 for (list = technology->device_list; list; list = list->next) {
2037 struct connman_device *device = list->data;
2039 scanning = connman_device_get_scanning(device, technology->type);
2040 ifname = connman_device_get_string(device, "Interface");
2042 DBG("ifname %s scanning : %d", ifname, scanning);
2043 connman_dbus_dict_append_basic(&dict, ifname,
2048 connman_dbus_dict_close(&iter, &dict);
2053 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
2056 DBusMessageIter iter, dict;
2058 struct connman_technology *technology = data;
2059 dbus_int32_t max_scan_ssids = 0;
2060 const char *ifname = NULL;
2062 DBG("technology %p", technology);
2064 reply = dbus_message_new_method_return(msg);
2068 dbus_message_iter_init_append(reply, &iter);
2069 connman_dbus_dict_open(&iter, &dict);
2071 for (list = technology->device_list; list; list = list->next) {
2072 struct connman_device *device = list->data;
2074 max_scan_ssids = connman_device_get_max_scan_ssids(device);
2075 ifname = connman_device_get_string(device, "Interface");
2077 DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
2078 connman_dbus_dict_append_basic(&dict, ifname,
2083 connman_dbus_dict_close(&iter, &dict);
2088 static int technology_enable_device(struct connman_technology *technology,
2089 bool enable_device, const char *ifname, struct connman_device **device_out)
2094 for (list = technology->device_list; list; list = list->next) {
2095 struct connman_device *device = list->data;
2096 const char *str = connman_device_get_string(device, "Interface");
2098 if (g_strcmp0(str, ifname) != 0)
2102 err = __connman_device_enable(device);
2104 err = __connman_device_disable(device);
2106 *device_out = device;
2113 static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
2114 DBusMessage *msg, bool powered, const char *ifname)
2116 DBusMessage *reply = NULL;
2117 struct connman_device *device = NULL;
2120 err = technology_enable_device(technology, powered, ifname, &device);
2122 if (err == -EINPROGRESS) {
2124 connman_device_set_pending_reply(device, msg);
2126 } else if (err == -EALREADY) {
2128 reply = __connman_error_already_enabled(msg);
2130 reply = __connman_error_already_disabled(msg);
2132 reply = __connman_error_failed(msg, -err);
2134 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2139 static DBusMessage *set_device_power(DBusConnection *conn,
2140 DBusMessage *msg, void *data)
2142 struct connman_technology *technology = data;
2143 DBusMessageIter iter;
2148 DBG("conn %p", conn);
2150 if (!dbus_message_iter_init(msg, &iter))
2151 return __connman_error_invalid_arguments(msg);
2153 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2154 return __connman_error_invalid_arguments(msg);
2156 dbus_message_iter_get_basic(&iter, &name);
2157 dbus_message_iter_next(&iter);
2159 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
2160 return __connman_error_invalid_arguments(msg);
2162 DBG("interface name %s", name);
2166 if (len + 1 > IFNAMSIZ)
2167 return __connman_error_invalid_arguments(msg);
2169 dbus_message_iter_get_basic(&iter, &enable);
2170 DBG("powered %s", enable ? "TRUE" : "FALSE");
2172 return technology_set_device_powered(technology, msg, enable, name);
2175 static DBusMessage *set_bssid(DBusConnection *conn,
2176 DBusMessage *msg, void *data)
2178 DBusMessageIter iter;
2182 DBG("conn %p", conn);
2184 if (!dbus_message_iter_init(msg, &iter))
2185 return __connman_error_invalid_arguments(msg);
2187 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2188 return __connman_error_invalid_arguments(msg);
2190 dbus_message_iter_get_basic(&iter, &name);
2191 dbus_message_iter_next(&iter);
2193 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2194 return __connman_error_invalid_arguments(msg);
2196 dbus_message_iter_get_basic(&iter, &bssid);
2198 DBG("interface name %s bssid %s", name, bssid);
2202 if (len + 1 > IFNAMSIZ)
2203 return __connman_error_invalid_arguments(msg);
2205 set_connman_bssid(SET_BSSID, bssid, name);
2207 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2209 static struct connman_technology *technology_get(enum connman_service_type type);
2211 void technology_save_device(struct connman_device *device)
2213 struct connman_technology *technology;
2214 enum connman_service_type type;
2216 type = __connman_device_get_service_type(device);
2217 technology = technology_get(type);
2223 const char *name = get_name(technology->type);
2225 DBG("technology %p type %d name %s", technology, technology->type,
2230 keyfile = __connman_storage_load_global();
2232 keyfile = g_key_file_new();
2234 identifier = g_strdup_printf("%s", name);
2238 GSList *list = NULL;
2239 gchar **ifname_list = NULL;
2240 guint dev_count = g_slist_length(technology->device_list);
2242 if (dev_count > 1) {
2243 GString *ifname_str = g_string_new(NULL);
2246 for (list = technology->device_list; list; list = list->next) {
2247 struct connman_device *device = list->data;
2249 if (connman_device_get_powered(device)) {
2250 const char *ifname = connman_device_get_string(device, "Interface");
2252 if (ifname_str->len > 0)
2253 g_string_append_printf(ifname_str, " %s", ifname);
2255 g_string_append(ifname_str, ifname);
2259 if (ifname_str->len > 0) {
2260 ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
2261 dev_count = g_strv_length(ifname_list);
2262 g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
2263 (const gchar **) ifname_list, dev_count);
2265 technology->enable_persistent = true;
2267 g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
2268 technology->enable_persistent = false;
2271 g_strfreev(ifname_list);
2272 g_string_free(ifname_str, TRUE);
2276 g_key_file_set_boolean(keyfile, identifier, "Enable",
2277 technology->enable_persistent);
2279 g_key_file_set_boolean(keyfile, identifier, "Tethering",
2280 technology->tethering_persistent);
2282 if (technology->tethering_ident)
2283 g_key_file_set_string(keyfile, identifier,
2284 "Tethering.Identifier",
2285 technology->tethering_ident);
2287 if (technology->tethering_passphrase)
2288 g_key_file_set_string(keyfile, identifier,
2289 "Tethering.Passphrase",
2290 technology->tethering_passphrase);
2295 __connman_storage_save_global(keyfile);
2297 g_key_file_free(keyfile);
2301 #if defined TIZEN_EXT_WIFI_MESH
2302 bool __connman_technology_get_connected(enum connman_service_type type)
2304 struct connman_technology *technology;
2306 technology = technology_find(type);
2311 return technology->connected;
2314 void __connman_technology_mesh_interface_create_finished(
2315 enum connman_service_type type, bool success,
2319 struct connman_technology *technology;
2321 technology = technology_find(type);
2323 DBG("technology %p success %d", technology, success);
2328 msg = technology->mesh_dbus_msg;
2330 DBG("No pending dbus message");
2335 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2336 __connman_device_request_scan(technology->type);
2338 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
2339 ".MeshInterfaceAddFailed", "%s", error);
2340 g_dbus_send_message(connection, reply);
2341 dbus_message_unref(msg);
2342 technology->mesh_dbus_msg = NULL;
2345 void __connman_technology_mesh_interface_remove_finished(
2346 enum connman_service_type type, bool success)
2349 struct connman_technology *technology;
2351 technology = technology_find(type);
2353 DBG("technology %p success %d", technology, success);
2355 if (!technology || !technology->mesh_dbus_msg)
2358 msg = technology->mesh_dbus_msg;
2360 DBG("No pending dbus message");
2365 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2367 reply = __connman_error_failed(msg, EINVAL);
2368 g_dbus_send_message(connection, reply);
2369 dbus_message_unref(msg);
2370 technology->mesh_dbus_msg = NULL;
2373 void __connman_technology_notify_abort_scan(enum connman_service_type type,
2377 struct connman_technology *technology;
2379 technology = technology_find(type);
2381 DBG("technology %p result %d", technology, result);
2383 if (!technology || !technology->mesh_dbus_msg)
2386 msg = technology->mesh_dbus_msg;
2388 DBG("No pending dbus message");
2393 reply = __connman_error_scan_abort_failed(msg);
2395 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2397 g_dbus_send_message(connection, reply);
2398 dbus_message_unref(msg);
2399 technology->mesh_dbus_msg = NULL;
2402 static DBusMessage *mesh_commands(DBusConnection *conn,
2403 DBusMessage *msg, void *data)
2405 struct connman_technology *technology = data;
2406 DBusMessageIter iter, value, dict;
2407 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
2410 DBG("conn %p", conn);
2412 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
2413 return __connman_error_invalid_arguments(msg);
2415 if (!dbus_message_iter_init(msg, &iter))
2416 return __connman_error_invalid_arguments(msg);
2418 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2419 return __connman_error_invalid_arguments(msg);
2421 dbus_message_iter_get_basic(&iter, &cmd);
2422 dbus_message_iter_next(&iter);
2424 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
2425 return __connman_error_invalid_arguments(msg);
2427 dbus_message_iter_recurse(&iter, &value);
2429 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
2430 return __connman_error_invalid_arguments(msg);
2432 DBG("Mesh Command %s", cmd);
2433 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
2434 dbus_message_iter_recurse(&value, &dict);
2435 const char *bridge_ifname = NULL;
2436 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2437 DBusMessageIter entry, value2;
2441 dbus_message_iter_recurse(&dict, &entry);
2443 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2444 return __connman_error_invalid_arguments(msg);
2446 dbus_message_iter_get_basic(&entry, &key);
2447 dbus_message_iter_next(&entry);
2449 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2450 return __connman_error_invalid_arguments(msg);
2452 dbus_message_iter_recurse(&entry, &value2);
2454 type = dbus_message_iter_get_arg_type(&value2);
2456 if (g_str_equal(key, "Ifname")) {
2457 if (type != DBUS_TYPE_STRING)
2458 return __connman_error_invalid_arguments(msg);
2460 dbus_message_iter_get_basic(&value2, &ifname);
2461 } else if (g_str_equal(key, "ParentIfname")) {
2462 if (type != DBUS_TYPE_STRING)
2463 return __connman_error_invalid_arguments(msg);
2465 dbus_message_iter_get_basic(&value2, &parent_ifname);
2466 } else if (g_str_equal(key, "BridgeIfname")) {
2467 if (type != DBUS_TYPE_STRING)
2468 return __connman_error_invalid_arguments(msg);
2470 dbus_message_iter_get_basic(&value2, &bridge_ifname);
2472 dbus_message_iter_next(&dict);
2474 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
2475 bridge_ifname ? bridge_ifname : "NULL");
2476 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
2480 DBG("Failed to add virtual mesh interface");
2481 return __connman_error_failed(msg, -err);
2484 DBG("Successfully added virtual mesh interface");
2486 dbus_message_ref(msg);
2487 technology->mesh_dbus_msg = msg;
2489 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
2490 dbus_message_iter_recurse(&value, &dict);
2491 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2492 DBusMessageIter entry, value2;
2496 dbus_message_iter_recurse(&dict, &entry);
2498 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2499 return __connman_error_invalid_arguments(msg);
2501 dbus_message_iter_get_basic(&entry, &key);
2502 dbus_message_iter_next(&entry);
2504 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2505 return __connman_error_invalid_arguments(msg);
2507 dbus_message_iter_recurse(&entry, &value2);
2509 type = dbus_message_iter_get_arg_type(&value2);
2511 if (g_str_equal(key, "Ifname")) {
2512 if (type != DBUS_TYPE_STRING)
2513 return __connman_error_invalid_arguments(msg);
2515 dbus_message_iter_get_basic(&value2, &ifname);
2517 dbus_message_iter_next(&dict);
2519 DBG("Mesh Ifname %s", ifname);
2520 err = __connman_mesh_remove_virtual_interface(ifname);
2523 DBG("Failed to remove virtual mesh interface");
2524 return __connman_error_failed(msg, -err);
2527 DBG("Successfully removed virtual mesh interface");
2529 dbus_message_ref(msg);
2530 technology->mesh_dbus_msg = msg;
2532 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
2533 struct connman_mesh *connman_mesh;
2534 const char *name = NULL;
2535 const char *sec_type = NULL;
2536 const char *mesh_ifname = NULL;
2537 char *identifier, *group, *address;
2538 unsigned int freq = 0;
2539 unsigned int ieee80211w = 0;
2542 dbus_message_iter_recurse(&value, &dict);
2543 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2544 DBusMessageIter entry, value2;
2548 dbus_message_iter_recurse(&dict, &entry);
2550 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2551 return __connman_error_invalid_arguments(msg);
2553 dbus_message_iter_get_basic(&entry, &key);
2554 dbus_message_iter_next(&entry);
2556 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2557 return __connman_error_invalid_arguments(msg);
2559 dbus_message_iter_recurse(&entry, &value2);
2561 type = dbus_message_iter_get_arg_type(&value2);
2563 if (g_str_equal(key, "Name")) {
2564 if (type != DBUS_TYPE_STRING)
2565 return __connman_error_invalid_arguments(msg);
2567 dbus_message_iter_get_basic(&value2, &name);
2568 } else if (g_str_equal(key, "Frequency")) {
2569 if (type != DBUS_TYPE_UINT16)
2570 return __connman_error_invalid_arguments(msg);
2572 dbus_message_iter_get_basic(&value2, &freq);
2573 } else if (g_str_equal(key, "Security")) {
2574 if (type != DBUS_TYPE_STRING)
2575 return __connman_error_invalid_arguments(msg);
2577 dbus_message_iter_get_basic(&value2, &sec_type);
2578 } else if (g_str_equal(key, "Pmf")) {
2579 if (type != DBUS_TYPE_UINT16)
2580 return __connman_error_invalid_arguments(msg);
2582 dbus_message_iter_get_basic(&value2, &ieee80211w);
2584 dbus_message_iter_next(&dict);
2587 if (name == NULL || sec_type == NULL || freq == 0)
2588 return __connman_error_invalid_arguments(msg);
2590 DBG("Name %s Frequency %d Security type %s Pmf %u",
2591 name, freq, sec_type, ieee80211w);
2593 if (g_strcmp0(sec_type, "none") != 0 &&
2594 g_strcmp0(sec_type, "sae") != 0) {
2595 DBG("Unsupported security");
2596 return __connman_error_invalid_arguments(msg);
2599 mesh_ifname = connman_mesh_get_interface_name();
2601 if (!connman_mesh_is_interface_created()) {
2602 DBG("Mesh interface doesn't exists");
2603 return __connman_error_invalid_command(msg);
2606 str = g_string_sized_new((strlen(name) * 2) + 24);
2608 for (i = 0; name[i]; i++)
2609 g_string_append_printf(str, "%02x", name[i]);
2611 g_string_append_printf(str, "_mesh");
2613 if (g_strcmp0(sec_type, "none") == 0)
2614 g_string_append_printf(str, "_none");
2615 else if (g_strcmp0(sec_type, "sae") == 0)
2616 g_string_append_printf(str, "_sae");
2618 group = g_string_free(str, FALSE);
2620 identifier = connman_inet_ifaddr(mesh_ifname);
2621 address = connman_inet_ifname2addr(mesh_ifname);
2623 connman_mesh = connman_mesh_create(identifier, group);
2624 connman_mesh_set_name(connman_mesh, name);
2625 connman_mesh_set_address(connman_mesh, address);
2626 connman_mesh_set_security(connman_mesh, sec_type);
2627 connman_mesh_set_frequency(connman_mesh, freq);
2628 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
2629 connman_mesh_set_peer_type(connman_mesh,
2630 CONNMAN_MESH_PEER_TYPE_CREATED);
2631 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
2633 connman_mesh_register(connman_mesh);
2637 DBG("Successfully Created Mesh Network");
2638 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2640 } else if (g_str_equal(cmd, "AbortScan")) {
2641 DBG("Abort Scan method");
2642 err = __connman_device_abort_scan(technology->type);
2644 DBG("Failed to abort scan");
2645 return __connman_error_failed(msg, -err);
2648 DBG("Successfully requested to abort scan");
2649 dbus_message_ref(msg);
2650 technology->mesh_dbus_msg = msg;
2652 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
2653 const char *name = NULL;
2654 unsigned int freq = 0;
2655 dbus_message_iter_recurse(&value, &dict);
2656 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2657 DBusMessageIter entry, value2;
2661 dbus_message_iter_recurse(&dict, &entry);
2663 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2664 return __connman_error_invalid_arguments(msg);
2666 dbus_message_iter_get_basic(&entry, &key);
2667 dbus_message_iter_next(&entry);
2669 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2670 return __connman_error_invalid_arguments(msg);
2672 dbus_message_iter_recurse(&entry, &value2);
2674 type = dbus_message_iter_get_arg_type(&value2);
2676 if (g_str_equal(key, "Name")) {
2677 if (type != DBUS_TYPE_STRING)
2678 return __connman_error_invalid_arguments(msg);
2680 dbus_message_iter_get_basic(&value2, &name);
2681 } else if (g_str_equal(key, "Frequency")) {
2682 if (type != DBUS_TYPE_UINT16)
2683 return __connman_error_invalid_arguments(msg);
2685 dbus_message_iter_get_basic(&value2, &freq);
2687 dbus_message_iter_next(&dict);
2690 DBG("MeshID %s Frequency %d sender %s", name, freq,
2691 dbus_message_get_sender(msg));
2693 struct connman_scan_pending *pending_data =
2694 g_try_malloc0(sizeof(struct connman_scan_pending));
2696 return __connman_error_failed(msg, ENOMEM);
2698 pending_data->msg = dbus_message_ref(msg);
2700 technology->scan_pending =
2701 g_slist_prepend(technology->scan_pending, pending_data);
2703 err = __connman_device_request_mesh_specific_scan(technology->type,
2706 reply_scan_pending(technology, err);
2708 DBG("Successfully requested to scan specific Mesh Network");
2710 } else if (g_str_equal(cmd, "SetMeshGate")) {
2711 unsigned int hwmp_rootmode = 0;
2712 bool gate_announce = false;
2713 unsigned int stp = 0;
2715 dbus_message_iter_recurse(&value, &dict);
2716 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2717 DBusMessageIter entry, value2;
2721 dbus_message_iter_recurse(&dict, &entry);
2723 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2724 return __connman_error_invalid_arguments(msg);
2726 dbus_message_iter_get_basic(&entry, &key);
2727 dbus_message_iter_next(&entry);
2729 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2730 return __connman_error_invalid_arguments(msg);
2732 dbus_message_iter_recurse(&entry, &value2);
2734 type = dbus_message_iter_get_arg_type(&value2);
2736 if (g_str_equal(key, "GateAnnounce")) {
2737 if (type != DBUS_TYPE_BOOLEAN)
2738 return __connman_error_invalid_arguments(msg);
2740 dbus_message_iter_get_basic(&value2, &gate_announce);
2741 } else if (g_str_equal(key, "HWMPRootMode")) {
2742 if (type != DBUS_TYPE_UINT16)
2743 return __connman_error_invalid_arguments(msg);
2745 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
2746 } else if (g_str_equal(key, "STP")) {
2747 if (type != DBUS_TYPE_UINT16)
2748 return __connman_error_invalid_arguments(msg);
2750 dbus_message_iter_get_basic(&value2, &stp);
2752 dbus_message_iter_next(&dict);
2755 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
2756 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
2758 err = __connman_mesh_set_stp_gate_announce(gate_announce,
2763 return __connman_error_failed(msg, -err);
2765 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2767 return __connman_error_invalid_command(msg);
2772 static const GDBusMethodTable technology_methods[] = {
2773 { GDBUS_DEPRECATED_METHOD("GetProperties",
2774 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
2776 { GDBUS_ASYNC_METHOD("SetProperty",
2777 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2778 NULL, set_property) },
2779 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
2780 #if defined TIZEN_EXT
2781 { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
2782 NULL, scan_device) },
2783 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
2784 NULL, specific_scan) },
2785 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
2787 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2788 get_5ghz_supported) },
2789 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2790 get_max_scan_ssid) },
2791 { GDBUS_ASYNC_METHOD("SetDevicePower",
2792 GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
2793 NULL, set_device_power) },
2794 { GDBUS_ASYNC_METHOD("SetBSSID",
2795 GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
2798 #if defined TIZEN_EXT_WIFI_MESH
2799 { GDBUS_ASYNC_METHOD("MeshCommands",
2800 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2801 NULL, mesh_commands) },
2806 static const GDBusSignalTable technology_signals[] = {
2807 { GDBUS_SIGNAL("PropertyChanged",
2808 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2809 #if defined TIZEN_EXT
2810 { GDBUS_SIGNAL("DeviceChanged",
2811 GDBUS_ARGS({ "device_property", "a{sv}" })) },
2812 { GDBUS_SIGNAL("DeviceDetected",
2813 GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
2818 static bool technology_dbus_register(struct connman_technology *technology)
2820 if (technology->dbus_registered ||
2821 (technology->rfkill_driven &&
2822 technology->hardblocked))
2825 if (!g_dbus_register_interface(connection, technology->path,
2826 CONNMAN_TECHNOLOGY_INTERFACE,
2827 technology_methods, technology_signals,
2828 NULL, technology, NULL)) {
2829 connman_error("Failed to register %s", technology->path);
2833 technology_added_signal(technology);
2834 technology->dbus_registered = true;
2839 static void technology_dbus_unregister(struct connman_technology *technology)
2841 if (!technology->dbus_registered)
2844 technology_removed_signal(technology);
2845 g_dbus_unregister_interface(connection, technology->path,
2846 CONNMAN_TECHNOLOGY_INTERFACE);
2848 technology->dbus_registered = false;
2851 static void technology_put(struct connman_technology *technology)
2853 DBG("technology %p", technology);
2855 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2858 reply_scan_pending(technology, -EINTR);
2860 while (technology->driver_list) {
2861 struct connman_technology_driver *driver;
2863 driver = technology->driver_list->data;
2866 driver->remove(technology);
2868 technology->driver_list =
2869 g_slist_delete_link(technology->driver_list,
2870 technology->driver_list);
2873 technology_list = g_slist_remove(technology_list, technology);
2875 technology_dbus_unregister(technology);
2877 g_slist_free(technology->device_list);
2879 if (technology->pending_reply) {
2880 dbus_message_unref(technology->pending_reply);
2881 technology->pending_reply = NULL;
2882 g_source_remove(technology->pending_timeout);
2883 technology->pending_timeout = 0;
2886 g_strfreev(technology->enabled_devices);
2888 g_free(technology->path);
2889 g_free(technology->regdom);
2890 g_free(technology->tethering_ident);
2891 g_free(technology->tethering_passphrase);
2895 static struct connman_technology *technology_get(enum connman_service_type type)
2897 GSList *tech_drivers = NULL;
2898 struct connman_technology_driver *driver;
2899 struct connman_technology *technology;
2903 DBG("type %d", type);
2905 str = __connman_service_type2string(type);
2909 technology = technology_find(type);
2911 #if defined TIZEN_EXT_WIFI_MESH
2912 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2913 type != CONNMAN_SERVICE_TYPE_MESH)
2915 if (type != CONNMAN_SERVICE_TYPE_P2P)
2917 __sync_fetch_and_add(&technology->refcount, 1);
2921 /* First check if we have a driver for this technology type */
2922 for (list = driver_list; list; list = list->next) {
2923 driver = list->data;
2925 if (driver->type == type) {
2926 DBG("technology %p driver %p", technology, driver);
2927 tech_drivers = g_slist_append(tech_drivers, driver);
2931 if (!tech_drivers) {
2932 DBG("No matching drivers found for %s.",
2933 __connman_service_type2string(type));
2937 technology = g_try_new0(struct connman_technology, 1);
2941 technology->refcount = 1;
2942 technology->type = type;
2943 technology->path = g_strdup_printf("%s/technology/%s",
2946 #if defined TIZEN_EXT_WIFI_MESH
2947 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2948 struct connman_technology *wifi;
2950 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2952 technology->enabled = wifi->enabled;
2956 technology_load(technology);
2957 technology_list = g_slist_prepend(technology_list, technology);
2958 technology->driver_list = tech_drivers;
2960 for (list = tech_drivers; list; list = list->next) {
2961 driver = list->data;
2963 if (driver->probe && driver->probe(technology) < 0)
2964 DBG("Driver probe failed for technology %p",
2968 if (!technology_dbus_register(technology)) {
2969 technology_put(technology);
2973 if (type == CONNMAN_SERVICE_TYPE_P2P) {
2974 struct connman_technology *wifi;
2977 enable = technology->enable_persistent;
2979 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2981 enable = wifi->enabled;
2983 technology_affect_devices(technology, enable);
2986 DBG("technology %p %s", technology, get_name(technology->type));
2991 int connman_technology_driver_register(struct connman_technology_driver *driver)
2994 struct connman_device *device;
2995 enum connman_service_type type;
2997 for (list = driver_list; list; list = list->next) {
2998 if (list->data == driver)
3002 DBG("Registering %s driver", driver->name);
3004 driver_list = g_slist_insert_sorted(driver_list, driver,
3008 * Check for technology less devices if this driver
3009 * can service any of them.
3011 for (list = techless_device_list; list; list = list->next) {
3012 device = list->data;
3014 type = __connman_device_get_service_type(device);
3015 if (type != driver->type)
3018 techless_device_list = g_slist_remove(techless_device_list,
3021 __connman_technology_add_device(device);
3024 /* Check for orphaned rfkill switches. */
3025 g_hash_table_foreach(rfkill_list, rfkill_check,
3026 GINT_TO_POINTER(driver->type));
3029 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3030 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
3034 #if defined TIZEN_EXT_WIFI_MESH
3035 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3036 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
3044 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
3046 GSList *list, *tech_drivers;
3047 struct connman_technology *technology;
3048 struct connman_technology_driver *current;
3050 DBG("Unregistering driver %p name %s", driver, driver->name);
3052 for (list = technology_list; list; list = list->next) {
3053 technology = list->data;
3055 for (tech_drivers = technology->driver_list; tech_drivers;
3056 tech_drivers = g_slist_next(tech_drivers)) {
3057 current = tech_drivers->data;
3058 if (driver != current)
3062 driver->remove(technology);
3064 technology->driver_list =
3065 g_slist_remove(technology->driver_list,
3071 driver_list = g_slist_remove(driver_list, driver);
3073 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3074 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
3076 technology_put(technology);
3078 #if defined TIZEN_EXT_WIFI_MESH
3079 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3080 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
3082 technology_put(technology);
3087 void __connman_technology_add_interface(enum connman_service_type type,
3088 int index, const char *ident)
3090 struct connman_technology *technology;
3091 GSList *tech_drivers;
3092 struct connman_technology_driver *driver;
3096 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3097 case CONNMAN_SERVICE_TYPE_SYSTEM:
3099 case CONNMAN_SERVICE_TYPE_ETHERNET:
3100 case CONNMAN_SERVICE_TYPE_WIFI:
3101 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3102 case CONNMAN_SERVICE_TYPE_CELLULAR:
3103 case CONNMAN_SERVICE_TYPE_GPS:
3104 case CONNMAN_SERVICE_TYPE_VPN:
3105 case CONNMAN_SERVICE_TYPE_GADGET:
3106 case CONNMAN_SERVICE_TYPE_P2P:
3107 #if defined TIZEN_EXT_WIFI_MESH
3108 case CONNMAN_SERVICE_TYPE_MESH:
3113 name = connman_inet_ifname(index);
3114 connman_info("Adding interface %s [ %s ]", name,
3115 __connman_service_type2string(type));
3117 technology = technology_find(type);
3122 for (tech_drivers = technology->driver_list; tech_drivers;
3123 tech_drivers = g_slist_next(tech_drivers)) {
3124 driver = tech_drivers->data;
3126 if (driver->add_interface)
3127 driver->add_interface(technology, index, name, ident);
3131 * At this point we can try to enable tethering automatically as
3132 * now the interfaces are set properly.
3134 if (technology->tethering_persistent)
3135 enable_tethering(technology);
3141 void __connman_technology_remove_interface(enum connman_service_type type,
3142 int index, const char *ident)
3144 struct connman_technology *technology;
3145 GSList *tech_drivers;
3146 struct connman_technology_driver *driver;
3150 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3151 case CONNMAN_SERVICE_TYPE_SYSTEM:
3153 case CONNMAN_SERVICE_TYPE_ETHERNET:
3154 case CONNMAN_SERVICE_TYPE_WIFI:
3155 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3156 case CONNMAN_SERVICE_TYPE_CELLULAR:
3157 case CONNMAN_SERVICE_TYPE_GPS:
3158 case CONNMAN_SERVICE_TYPE_VPN:
3159 case CONNMAN_SERVICE_TYPE_GADGET:
3160 case CONNMAN_SERVICE_TYPE_P2P:
3161 #if defined TIZEN_EXT_WIFI_MESH
3162 case CONNMAN_SERVICE_TYPE_MESH:
3167 name = connman_inet_ifname(index);
3168 connman_info("Remove interface %s [ %s ]", name,
3169 __connman_service_type2string(type));
3172 technology = technology_find(type);
3177 for (tech_drivers = technology->driver_list; tech_drivers;
3178 tech_drivers = g_slist_next(tech_drivers)) {
3179 driver = tech_drivers->data;
3181 if (driver->remove_interface)
3182 driver->remove_interface(technology, index);
3186 int __connman_technology_add_device(struct connman_device *device)
3188 struct connman_technology *technology;
3189 enum connman_service_type type;
3191 type = __connman_device_get_service_type(device);
3193 DBG("device %p type %s", device, get_name(type));
3195 technology = technology_get(type);
3198 * Since no driver can be found for this device at the moment we
3199 * add it to the techless device list.
3201 techless_device_list = g_slist_prepend(techless_device_list,
3207 __sync_synchronize();
3208 if (technology->rfkill_driven) {
3209 if (technology->enabled)
3210 __connman_device_enable(device);
3212 __connman_device_disable(device);
3217 if (technology->enable_persistent &&
3218 !global_offlinemode) {
3219 #if defined TIZEN_EXT
3222 if (technology->enabled_devices) {
3225 const char *ifname = connman_device_get_string(device, "Interface");
3227 while (technology->enabled_devices[i]) {
3228 if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
3237 err = __connman_device_enable(device);
3239 int err = __connman_device_enable(device);
3242 * connman_technology_add_device() calls __connman_device_enable()
3243 * but since the device is already enabled, the call does not
3244 * propagate through to connman_technology_enabled via
3245 * connman_device_set_powered.
3247 if (err == -EALREADY)
3248 __connman_technology_enabled(type);
3250 /* if technology persistent state is offline */
3251 if (!technology->enable_persistent)
3252 __connman_device_disable(device);
3255 technology->device_list = g_slist_prepend(technology->device_list,
3258 #if defined TIZEN_EXT
3259 const char *ifname = connman_device_get_string(device, "Interface");
3260 __connman_technology_notify_device_detected(technology, ifname, true);
3262 connman_device_set_mac_policy(device, technology->mac_policy);
3263 connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy);
3264 connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime);
3269 int __connman_technology_remove_device(struct connman_device *device)
3271 struct connman_technology *technology;
3272 enum connman_service_type type;
3274 DBG("device %p", device);
3276 type = __connman_device_get_service_type(device);
3278 technology = technology_find(type);
3280 techless_device_list = g_slist_remove(techless_device_list,
3285 technology->device_list = g_slist_remove(technology->device_list,
3288 #if defined TIZEN_EXT
3289 const char *ifname = connman_device_get_string(device, "Interface");
3290 __connman_technology_notify_device_detected(technology, ifname, false);
3293 if (technology->tethering)
3294 set_tethering(technology, false);
3296 technology_put(technology);
3301 int __connman_technology_enabled(enum connman_service_type type)
3303 struct connman_technology *technology;
3305 technology = technology_find(type);
3309 DBG("technology %p type %s rfkill %d enabled %d", technology,
3310 get_name(type), technology->rfkill_driven,
3311 technology->enabled);
3313 #if !defined TIZEN_EXT
3314 if (technology->rfkill_driven) {
3315 if (technology->tethering_persistent)
3316 enable_tethering(technology);
3321 return technology_enabled(technology);
3324 int __connman_technology_disabled(enum connman_service_type type)
3326 struct connman_technology *technology;
3329 technology = technology_find(type);
3333 #if !defined TIZEN_EXT
3334 if (technology->rfkill_driven)
3338 for (list = technology->device_list; list; list = list->next) {
3339 struct connman_device *device = list->data;
3341 if (connman_device_get_powered(device))
3345 return technology_disabled(technology);
3348 int __connman_technology_set_offlinemode(bool offlinemode)
3351 int err = -EINVAL, enabled_tech_count = 0;
3353 if (global_offlinemode == offlinemode)
3356 DBG("offlinemode %s", offlinemode ? "On" : "Off");
3359 * This is a bit tricky. When you set offlinemode, there is no
3360 * way to differentiate between attempting offline mode and
3361 * resuming offlinemode from last saved profile. We need that
3362 * information in rfkill_update, otherwise it falls back on the
3363 * technology's persistent state. Hence we set the offline mode here
3364 * but save it & call the notifier only if it is successful.
3367 global_offlinemode = offlinemode;
3369 /* Traverse technology list, enable/disable each technology. */
3370 for (list = technology_list; list; list = list->next) {
3371 struct connman_technology *technology = list->data;
3374 err = technology_disable(technology);
3376 if (technology->hardblocked)
3379 if (technology->enable_persistent) {
3380 err = technology_enable(technology);
3381 enabled_tech_count++;
3386 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
3387 (err == -EINVAL && enabled_tech_count == 0)) {
3388 connman_technology_save_offlinemode();
3389 __connman_notifier_offlinemode(offlinemode);
3391 global_offlinemode = connman_technology_load_offlinemode();
3396 #if defined TIZEN_EXT_WIFI_MESH
3397 static gboolean __add_ethernet_to_bridge(gpointer data)
3400 __connman_mesh_add_ethernet_to_bridge();
3405 void __connman_technology_set_connected(enum connman_service_type type,
3408 struct connman_technology *technology;
3411 technology = technology_find(type);
3415 DBG("technology %p connected %d", technology, connected);
3417 technology->connected = connected;
3419 #if defined TIZEN_EXT_WIFI_MESH
3420 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
3421 g_idle_add(__add_ethernet_to_bridge, NULL);
3425 connman_dbus_property_changed_basic(technology->path,
3426 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
3427 DBUS_TYPE_BOOLEAN, &val);
3430 static bool technology_apply_rfkill_change(struct connman_technology *technology,
3435 bool hardblock_changed = false;
3437 GList *start, *list;
3439 DBG("technology %p --> %d/%d vs %d/%d",
3440 technology, softblock, hardblock,
3441 technology->softblocked, technology->hardblocked);
3443 if (technology->hardblocked == hardblock)
3444 goto softblock_change;
3446 if (!(new_rfkill && !hardblock)) {
3447 start = g_hash_table_get_values(rfkill_list);
3449 for (list = start; list; list = list->next) {
3450 struct connman_rfkill *rfkill = list->data;
3452 if (rfkill->type != technology->type)
3455 if (rfkill->hardblock != hardblock)
3463 goto softblock_change;
3465 technology->hardblocked = hardblock;
3466 hardblock_changed = true;
3469 if (!apply && technology->softblocked != softblock)
3473 return technology->hardblocked;
3475 technology->softblocked = softblock;
3477 if (technology->hardblocked ||
3478 technology->softblocked) {
3479 if (technology_disabled(technology) != -EALREADY)
3480 technology_affect_devices(technology, false);
3481 } else if (!technology->hardblocked &&
3482 !technology->softblocked) {
3483 if (technology_enabled(technology) != -EALREADY)
3484 technology_affect_devices(technology, true);
3487 if (hardblock_changed) {
3488 if (technology->hardblocked) {
3489 DBG("%s is switched off.", get_name(technology->type));
3490 technology_dbus_unregister(technology);
3492 DBG("%s is switched on.", get_name(technology->type));
3493 technology_dbus_register(technology);
3495 if (global_offlinemode)
3496 __connman_rfkill_block(technology->type, true);
3500 return technology->hardblocked;
3503 int __connman_technology_add_rfkill(unsigned int index,
3504 enum connman_service_type type,
3508 struct connman_technology *technology;
3509 struct connman_rfkill *rfkill;
3511 DBG("index %u type %d soft %u hard %u", index, type,
3512 softblock, hardblock);
3514 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3518 rfkill = g_try_new0(struct connman_rfkill, 1);
3522 rfkill->index = index;
3523 rfkill->type = type;
3524 rfkill->softblock = softblock;
3525 rfkill->hardblock = hardblock;
3527 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
3530 #if defined TIZEN_EXT
3531 /* Fix Svace Issue [WGID: 1348]. */
3534 technology = technology_get(type);
3535 /* If there is no driver for this type, ignore it. */
3539 technology->rfkill_driven = true;
3541 #if !defined TIZEN_EXT
3542 /* If hardblocked, there is no need to handle softblocked state */
3543 if (technology_apply_rfkill_change(technology,
3544 softblock, hardblock, true))
3548 if (global_offlinemode)
3552 * Depending on softblocked state we unblock/block according to
3553 * offlinemode and persistente state.
3555 if (technology->softblocked &&
3556 technology->enable_persistent)
3557 return __connman_rfkill_block(type, false);
3558 else if (!technology->softblocked &&
3559 !technology->enable_persistent)
3560 return __connman_rfkill_block(type, true);
3565 int __connman_technology_update_rfkill(unsigned int index,
3566 enum connman_service_type type,
3570 struct connman_technology *technology;
3571 struct connman_rfkill *rfkill;
3573 DBG("index %u soft %u hard %u", index, softblock, hardblock);
3575 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3579 if (rfkill->softblock == softblock &&
3580 rfkill->hardblock == hardblock)
3583 rfkill->softblock = softblock;
3584 rfkill->hardblock = hardblock;
3586 technology = technology_find(type);
3587 /* If there is no driver for this type, ignore it. */
3591 technology_apply_rfkill_change(technology, softblock, hardblock,
3594 if (technology->hardblocked)
3595 DBG("%s hardblocked", get_name(technology->type));
3597 DBG("%s is%s softblocked", get_name(technology->type),
3598 technology->softblocked ? "" : " not");
3603 int __connman_technology_remove_rfkill(unsigned int index,
3604 enum connman_service_type type)
3606 struct connman_technology *technology;
3607 struct connman_rfkill *rfkill;
3609 DBG("index %u", index);
3611 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3615 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
3617 technology = technology_find(type);
3621 technology_apply_rfkill_change(technology,
3622 technology->softblocked, !technology->hardblocked, false);
3624 technology_put(technology);
3629 int __connman_technology_init(void)
3633 connection = connman_dbus_get_connection();
3635 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3638 global_offlinemode = connman_technology_load_offlinemode();
3640 /* This will create settings file if it is missing */
3641 connman_technology_save_offlinemode();
3646 void __connman_technology_cleanup(void)
3650 while (technology_list) {
3651 struct connman_technology *technology = technology_list->data;
3652 technology_list = g_slist_remove(technology_list, technology);
3653 technology_put(technology);
3656 g_hash_table_destroy(rfkill_list);
3658 dbus_connection_unref(connection);