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);
730 connman_dbus_dict_close(iter, &dict);
733 static void technology_added_signal(struct connman_technology *technology)
736 DBusMessageIter iter;
738 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
739 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
743 dbus_message_iter_init_append(signal, &iter);
744 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
746 append_properties(&iter, technology);
748 dbus_connection_send(connection, signal, NULL);
749 dbus_message_unref(signal);
752 static void technology_removed_signal(struct connman_technology *technology)
754 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
755 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
756 DBUS_TYPE_OBJECT_PATH, &technology->path,
760 static DBusMessage *get_properties(DBusConnection *conn,
761 DBusMessage *message, void *user_data)
763 struct connman_technology *technology = user_data;
765 DBusMessageIter iter;
767 reply = dbus_message_new_method_return(message);
771 dbus_message_iter_init_append(reply, &iter);
772 append_properties(&iter, technology);
777 void __connman_technology_list_struct(DBusMessageIter *array)
780 DBusMessageIter entry;
782 for (list = technology_list; list; list = list->next) {
783 struct connman_technology *technology = list->data;
785 if (!technology->path ||
786 (technology->rfkill_driven &&
787 technology->hardblocked))
790 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
792 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
794 append_properties(&entry, technology);
795 dbus_message_iter_close_container(array, &entry);
799 static gboolean technology_pending_reply(gpointer user_data)
801 struct connman_technology *technology = user_data;
804 /* Power request timed out, send ETIMEDOUT. */
805 if (technology->pending_reply) {
806 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
808 g_dbus_send_message(connection, reply);
810 dbus_message_unref(technology->pending_reply);
811 technology->pending_reply = NULL;
812 technology->pending_timeout = 0;
818 static int technology_affect_devices(struct connman_technology *technology,
821 int err = 0, err_dev;
824 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
826 __connman_technology_enabled(technology->type);
828 __connman_technology_disabled(technology->type);
832 #if defined TIZEN_EXT_WIFI_MESH
833 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
837 for (list = technology->device_list; list; list = list->next) {
838 struct connman_device *device = list->data;
841 err_dev = __connman_device_enable(device);
843 err_dev = __connman_device_disable(device);
845 if (err_dev < 0 && err_dev != -EALREADY)
852 static void powered_changed(struct connman_technology *technology)
856 if (!technology->dbus_registered)
859 if (technology->pending_reply) {
860 g_dbus_send_reply(connection,
861 technology->pending_reply, DBUS_TYPE_INVALID);
862 dbus_message_unref(technology->pending_reply);
863 technology->pending_reply = NULL;
865 g_source_remove(technology->pending_timeout);
866 technology->pending_timeout = 0;
869 __sync_synchronize();
870 enabled = technology->enabled;
871 #if defined TIZEN_EXT
872 DBG("ConnMan, Powered : %s, %s",
873 enabled ? "TRUE" : "FALSE",technology->path);
875 connman_dbus_property_changed_basic(technology->path,
876 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
877 DBUS_TYPE_BOOLEAN, &enabled);
880 static void enable_tethering(struct connman_technology *technology)
884 if (!connman_setting_get_bool("PersistentTetheringMode"))
887 ret = set_tethering(technology, true);
888 if (ret < 0 && ret != -EALREADY)
889 DBG("Cannot enable tethering yet for %s (%d/%s)",
890 get_name(technology->type),
891 -ret, strerror(-ret));
894 static int technology_enabled(struct connman_technology *technology)
896 __sync_synchronize();
897 if (technology->enabled)
900 technology->enabled = true;
902 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
903 struct connman_technology *p2p;
905 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
906 if (p2p && !p2p->enabled && p2p->enable_persistent)
907 technology_enabled(p2p);
910 if (technology->tethering_persistent)
911 enable_tethering(technology);
913 powered_changed(technology);
918 static int technology_enable(struct connman_technology *technology)
923 DBG("technology %p enable", technology);
925 __sync_synchronize();
927 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
928 struct connman_technology *wifi;
930 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
931 if (wifi && wifi->enabled)
932 return technology_enabled(technology);
936 if (technology->enabled)
939 if (technology->pending_reply)
942 if (connman_setting_get_bool("PersistentTetheringMode") &&
943 technology->tethering)
944 set_tethering(technology, true);
946 if (technology->rfkill_driven)
947 err = __connman_rfkill_block(technology->type, false);
949 err_dev = technology_affect_devices(technology, true);
951 if (!technology->rfkill_driven)
957 static int technology_disabled(struct connman_technology *technology)
959 __sync_synchronize();
960 if (!technology->enabled)
963 technology->enabled = false;
965 powered_changed(technology);
970 static int technology_disable(struct connman_technology *technology)
974 DBG("technology %p disable", technology);
976 __sync_synchronize();
978 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
979 technology->enable_persistent = false;
980 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
981 __connman_peer_disconnect_all();
982 return technology_disabled(technology);
983 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
984 struct connman_technology *p2p;
986 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
987 if (p2p && p2p->enabled) {
988 p2p->enable_persistent = true;
989 technology_disabled(p2p);
993 if (!technology->enabled)
996 if (technology->pending_reply)
999 if (technology->tethering)
1000 set_tethering(technology, false);
1002 err = technology_affect_devices(technology, false);
1004 if (technology->rfkill_driven)
1005 err = __connman_rfkill_block(technology->type, true);
1010 static DBusMessage *set_powered(struct connman_technology *technology,
1011 DBusMessage *msg, bool powered)
1013 DBusMessage *reply = NULL;
1016 if (technology->rfkill_driven && technology->hardblocked) {
1022 err = technology_enable(technology);
1024 err = technology_disable(technology);
1026 if (err != -EBUSY) {
1027 technology->enable_persistent = powered;
1028 technology_save(technology);
1032 if (err == -EINPROGRESS) {
1033 technology->pending_reply = dbus_message_ref(msg);
1034 technology->pending_timeout = g_timeout_add_seconds(10,
1035 technology_pending_reply, technology);
1036 } else if (err == -EALREADY) {
1038 reply = __connman_error_already_enabled(msg);
1040 reply = __connman_error_already_disabled(msg);
1042 reply = __connman_error_failed(msg, -err);
1044 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1049 #if defined TIZEN_EXT
1050 int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
1052 static int bssid_len;
1053 static const char *def_ifname = "default";
1054 static GSList *bssid_list = NULL;
1056 const char *local_ifname = ifname;
1058 struct connman_bssid_pending *bssid_info;
1060 DBG("mode: %d, ifname: %s", mode, ifname);
1063 local_ifname = def_ifname;
1065 for (list = bssid_list; list; list = list->next) {
1066 bssid_info = list->data;
1068 if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
1074 if (mode == CHECK_BSSID) {
1081 if (mode == GET_BSSID && bssid) {
1083 memcpy(bssid, bssid_info->bssid, 6);
1089 if (mode == RESET_BSSID) {
1091 bssid_list = g_slist_remove(bssid_list, bssid_info);
1092 g_free(bssid_info->ifname);
1098 if (mode != SET_BSSID || !bssid) {
1099 DBG("Invalid parameter");
1104 bssid_list = g_slist_remove(bssid_list, bssid_info);
1105 g_free(bssid_info->ifname);
1109 bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
1111 DBG("Failed to allocate memory");
1115 unsigned char *bssid_data = bssid_info->bssid;
1117 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1118 &bssid_data[0], &bssid_data[1], &bssid_data[2],
1119 &bssid_data[3], &bssid_data[4], &bssid_data[5]);
1120 if (bssid_len != 6) {
1121 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
1126 DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
1128 bssid_data[0], bssid_data[1], bssid_data[2],
1129 bssid_data[3], bssid_data[4], bssid_data[5],
1132 bssid_info->ifname = g_strdup(ifname);
1133 bssid_list = g_slist_prepend(bssid_list, bssid_info);
1138 void connman_technology_mac_policy_notify(struct connman_technology *technology,
1139 unsigned int policy)
1141 DBG("Mac polict set to %u", policy);
1143 technology->mac_policy = policy;
1144 technology_save(technology);
1147 void __connman_technology_notify_mac_policy_by_device(struct connman_device *device,
1148 int result, unsigned int policy)
1150 struct connman_technology *technology;
1151 enum connman_service_type type;
1153 type = __connman_device_get_service_type(device);
1154 technology = technology_find(type);
1159 connman_technology_mac_policy_notify(technology, policy);
1162 static DBusMessage *set_mac_policy(struct connman_technology *technology,
1163 DBusMessage *msg, unsigned int policy)
1165 DBusMessage *reply = NULL;
1167 unsigned int last_policy = technology->mac_policy;
1169 if (technology->rfkill_driven && technology->hardblocked) {
1174 for (GSList *list = technology->device_list; list; list = list->next) {
1175 struct connman_device *device = list->data;
1177 err = connman_device_set_mac_policy(device, policy);
1184 if (err != -EACCES && err != -EOPNOTSUPP) {
1185 for (GSList *list = technology->device_list; list; list = list->next) {
1186 struct connman_device *device = list->data;
1188 connman_device_set_mac_policy(device, last_policy);
1192 reply = __connman_error_failed(msg, -err);
1194 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1200 void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology,
1201 unsigned int policy)
1203 DBG("Preassoc mac polict set to %u", policy);
1205 technology->preassoc_mac_policy = policy;
1206 technology_save(technology);
1209 void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device,
1210 int result, unsigned int policy)
1212 struct connman_technology *technology;
1213 enum connman_service_type type;
1215 type = __connman_device_get_service_type(device);
1216 technology = technology_find(type);
1221 connman_technology_preassoc_mac_policy_notify(technology, policy);
1224 static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology,
1225 DBusMessage *msg, unsigned int policy)
1227 DBusMessage *reply = NULL;
1229 unsigned int last_policy = technology->preassoc_mac_policy;
1231 if (technology->rfkill_driven && technology->hardblocked) {
1236 for (GSList *list = technology->device_list; list; list = list->next) {
1237 struct connman_device *device = list->data;
1239 err = connman_device_set_preassoc_mac_policy(device, policy);
1246 if (err != -EACCES && err != -EOPNOTSUPP) {
1247 for (GSList *list = technology->device_list; list; list = list->next) {
1248 struct connman_device *device = list->data;
1250 connman_device_set_preassoc_mac_policy(device, last_policy);
1254 reply = __connman_error_failed(msg, -err);
1256 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1262 void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology,
1263 unsigned int lifetime)
1265 DBG("Random mac lifetime set to %u", lifetime);
1267 technology->random_mac_lifetime = lifetime;
1268 technology_save(technology);
1271 void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device,
1272 int result, unsigned int lifetime)
1274 struct connman_technology *technology;
1275 enum connman_service_type type;
1277 type = __connman_device_get_service_type(device);
1278 technology = technology_find(type);
1283 connman_technology_random_mac_lifetime_notify(technology, lifetime);
1286 static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology,
1287 DBusMessage *msg, unsigned int lifetime)
1289 DBusMessage *reply = NULL;
1291 unsigned int last_lifetime = technology->random_mac_lifetime;
1293 if (technology->rfkill_driven && technology->hardblocked) {
1298 for (GSList *list = technology->device_list; list; list = list->next) {
1299 struct connman_device *device = list->data;
1301 err = connman_device_set_random_mac_lifetime(device, lifetime);
1306 if (err != -EACCES && err != -EOPNOTSUPP) {
1307 for (GSList *list = technology->device_list; list; list = list->next) {
1308 struct connman_device *device = list->data;
1310 connman_device_set_random_mac_lifetime(device, last_lifetime);
1314 reply = __connman_error_failed(msg, -err);
1316 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1323 static DBusMessage *set_property(DBusConnection *conn,
1324 DBusMessage *msg, void *data)
1326 struct connman_technology *technology = data;
1327 DBusMessageIter iter, value;
1331 DBG("conn %p", conn);
1333 if (!dbus_message_iter_init(msg, &iter))
1334 return __connman_error_invalid_arguments(msg);
1336 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1337 return __connman_error_invalid_arguments(msg);
1339 dbus_message_iter_get_basic(&iter, &name);
1340 dbus_message_iter_next(&iter);
1342 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1343 return __connman_error_invalid_arguments(msg);
1345 dbus_message_iter_recurse(&iter, &value);
1347 type = dbus_message_iter_get_arg_type(&value);
1349 DBG("property %s", name);
1351 if (g_str_equal(name, "Tethering")) {
1352 dbus_bool_t tethering;
1355 if (type != DBUS_TYPE_BOOLEAN)
1356 return __connman_error_invalid_arguments(msg);
1358 if (!connman_technology_is_tethering_allowed(technology->type)) {
1359 DBG("%s tethering not allowed by config file",
1360 __connman_service_type2string(technology->type));
1361 return __connman_error_not_supported(msg);
1364 dbus_message_iter_get_basic(&value, &tethering);
1366 if (technology->tethering == tethering) {
1368 return __connman_error_already_disabled(msg);
1370 return __connman_error_already_enabled(msg);
1373 err = set_tethering(technology, tethering);
1375 return __connman_error_failed(msg, -err);
1377 technology->tethering_persistent = tethering;
1379 technology_save(technology);
1381 } else if (g_str_equal(name, "TetheringIdentifier")) {
1384 dbus_message_iter_get_basic(&value, &str);
1386 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1387 return __connman_error_not_supported(msg);
1389 if (strlen(str) < 1 || strlen(str) > 32)
1390 return __connman_error_invalid_arguments(msg);
1392 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1393 g_free(technology->tethering_ident);
1394 technology->tethering_ident = g_strdup(str);
1395 technology_save(technology);
1397 connman_dbus_property_changed_basic(technology->path,
1398 CONNMAN_TECHNOLOGY_INTERFACE,
1399 "TetheringIdentifier",
1401 &technology->tethering_ident);
1403 } else if (g_str_equal(name, "TetheringPassphrase")) {
1406 dbus_message_iter_get_basic(&value, &str);
1408 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1409 return __connman_error_not_supported(msg);
1411 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1414 return __connman_error_passphrase_required(msg);
1416 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1417 g_free(technology->tethering_passphrase);
1418 technology->tethering_passphrase = g_strdup(str);
1419 technology_save(technology);
1421 connman_dbus_property_changed_basic(technology->path,
1422 CONNMAN_TECHNOLOGY_INTERFACE,
1423 "TetheringPassphrase",
1425 &technology->tethering_passphrase);
1427 } else if (g_str_equal(name, "Powered")) {
1430 if (type != DBUS_TYPE_BOOLEAN)
1431 return __connman_error_invalid_arguments(msg);
1433 dbus_message_iter_get_basic(&value, &enable);
1435 return set_powered(technology, msg, enable);
1436 #if defined TIZEN_EXT
1437 } else if (g_str_equal(name, "SetBSSID")) {
1440 if (type != DBUS_TYPE_STRING)
1441 return __connman_error_invalid_arguments(msg);
1443 dbus_message_iter_get_basic(&value, &key);
1444 DBG("BSSID %s", key);
1445 set_connman_bssid(SET_BSSID, key, NULL);
1446 } else if (g_str_equal(name, "MacPolicy")) {
1447 dbus_uint32_t mac_policy;
1449 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1450 return __connman_error_not_supported(msg);
1452 if (type != DBUS_TYPE_UINT32)
1453 return __connman_error_invalid_arguments(msg);
1455 dbus_message_iter_get_basic(&value, &mac_policy);
1457 if (mac_policy <= 2)
1458 return set_mac_policy(technology, msg, mac_policy);
1460 return __connman_error_invalid_arguments(msg);
1462 } else if (g_str_equal(name, "PreassocMacPolicy")) {
1463 dbus_uint32_t preassoc_mac_policy;
1465 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1466 return __connman_error_not_supported(msg);
1468 if (type != DBUS_TYPE_UINT32)
1469 return __connman_error_invalid_arguments(msg);
1471 dbus_message_iter_get_basic(&value, &preassoc_mac_policy);
1473 if (preassoc_mac_policy <= 2)
1474 return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy);
1476 return __connman_error_invalid_arguments(msg);
1478 } else if (g_str_equal(name, "RandomMacLifetime")) {
1479 dbus_uint32_t random_mac_lifetime;
1481 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1482 return __connman_error_not_supported(msg);
1484 if (type != DBUS_TYPE_UINT32)
1485 return __connman_error_invalid_arguments(msg);
1487 dbus_message_iter_get_basic(&value, &random_mac_lifetime);
1489 if (random_mac_lifetime > 0)
1490 return set_random_mac_lifetime(technology, msg, random_mac_lifetime);
1492 return __connman_error_invalid_arguments(msg);
1495 return __connman_error_invalid_property(msg);
1497 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1500 static void reply_scan_pending(struct connman_technology *technology, int err)
1504 DBG("technology %p err %d", technology, err);
1506 while (technology->scan_pending) {
1507 #if defined TIZEN_EXT
1508 struct connman_scan_pending *pending_data = technology->scan_pending->data;
1509 DBusMessage *msg = pending_data->msg;
1511 DBusMessage *msg = technology->scan_pending->data;
1513 DBG("reply to %s", dbus_message_get_sender(msg));
1516 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1518 reply = __connman_error_failed(msg, -err);
1519 g_dbus_send_message(connection, reply);
1520 dbus_message_unref(msg);
1522 technology->scan_pending =
1523 g_slist_delete_link(technology->scan_pending,
1524 technology->scan_pending);
1525 #if defined TIZEN_EXT
1526 g_free(pending_data->ifname);
1527 g_free(pending_data);
1532 #if defined TIZEN_EXT
1533 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1536 DBusMessage *signal;
1537 DBusMessageIter iter;
1538 dbus_bool_t result = FALSE;
1540 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1541 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1545 dbus_message_iter_init_append(signal, &iter);
1547 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1549 connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
1551 result = dbus_connection_send(connection, signal, NULL);
1552 dbus_message_unref(signal);
1554 DBG("Successfuly sent signal");
1559 void __connman_technology_notify_scan_done(const char *ifname, int val)
1562 DBusMessage *signal;
1563 DBusMessageIter iter;
1565 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1566 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1570 dbus_message_iter_init_append(signal, &iter);
1572 connman_dbus_property_append_basic(&iter, ifname,
1573 DBUS_TYPE_INT32, &val);
1575 connman_dbus_property_append_basic(&iter, "",
1576 DBUS_TYPE_INT32, &val);
1578 dbus_connection_send(connection, signal, NULL);
1579 dbus_message_unref(signal);
1581 DBG("Successfuly sent ScanDone signal");
1584 static void reply_scan_pending_device(
1585 struct connman_technology *technology, const char *ifname, int count)
1589 dbus_bool_t status = 0;
1590 connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
1592 DBG("technology %p ifname %s count %d", technology, ifname, count);
1594 list = technology->scan_pending;
1597 struct connman_scan_pending *pending_data = list->data;
1598 DBusMessage *msg = pending_data->msg;
1601 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1602 scan_type = pending_data->scan_type;
1604 if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
1607 scan_type = pending_data->scan_type;
1609 DBG("reply to %s", dbus_message_get_sender(msg));
1610 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1612 g_dbus_send_message(connection, reply);
1613 dbus_message_unref(msg);
1615 technology->scan_pending =
1616 g_slist_remove(technology->scan_pending, pending_data);
1618 g_free(pending_data->ifname);
1619 g_free(pending_data);
1622 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1623 scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1625 __connman_technology_notify_scan_changed(ifname, &status);
1626 __connman_technology_notify_scan_done(ifname, scan_type);
1629 static void __connman_technology_notify_device_detected(
1630 struct connman_technology *technology, const char *ifname, bool val)
1633 DBusMessage *signal;
1634 DBusMessageIter iter;
1635 dbus_bool_t detected = val;
1640 signal = dbus_message_new_signal(technology->path,
1641 CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
1645 dbus_message_iter_init_append(signal, &iter);
1646 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
1647 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
1649 dbus_connection_send(connection, signal, NULL);
1650 dbus_message_unref(signal);
1652 DBG("Successfuly sent DeviceDetected signal");
1656 void __connman_technology_scan_started(struct connman_device *device)
1658 DBG("device %p", device);
1659 #if defined TIZEN_EXT
1660 dbus_bool_t status = 1;
1661 const char *ifname = connman_device_get_string(device, "Interface");
1663 __connman_technology_notify_scan_changed(ifname, &status);
1667 void __connman_technology_scan_stopped(struct connman_device *device,
1668 enum connman_service_type type)
1671 struct connman_technology *technology;
1674 technology = technology_find(type);
1676 DBG("technology %p device %p", technology, device);
1681 for (list = technology->device_list; list; list = list->next) {
1682 struct connman_device *other_device = list->data;
1684 if (device == other_device)
1687 if (connman_device_get_scanning(other_device, type))
1691 #if defined TIZEN_EXT
1692 const char *ifname = connman_device_get_string(device, "Interface");
1693 reply_scan_pending_device(technology, ifname, count);
1698 reply_scan_pending(technology, 0);
1702 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1703 int result, const char *alpha2)
1705 bool regdom_set = false;
1706 struct connman_technology *technology;
1707 enum connman_service_type type;
1708 GSList *tech_drivers;
1710 type = __connman_device_get_service_type(device);
1711 technology = technology_find(type);
1718 for (tech_drivers = technology->driver_list;
1720 tech_drivers = g_slist_next(tech_drivers)) {
1721 struct connman_technology_driver *driver =
1724 if (driver->set_regdom) {
1725 driver->set_regdom(technology, alpha2);
1735 connman_technology_regdom_notify(technology, alpha2);
1738 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1740 struct connman_technology *technology = data;
1743 DBG("technology %p request from %s", technology,
1744 dbus_message_get_sender(msg));
1746 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1747 !technology->enabled)
1748 return __connman_error_permission_denied(msg);
1750 #if !defined TIZEN_EXT
1751 dbus_message_ref(msg);
1752 technology->scan_pending =
1753 g_slist_prepend(technology->scan_pending, msg);
1756 err = __connman_device_request_scan_full(technology->type);
1758 #if defined TIZEN_EXT
1759 return __connman_error_failed(msg, -err);
1761 reply_scan_pending(technology, err);
1764 #if defined TIZEN_EXT
1765 struct connman_scan_pending *pending_data =
1766 g_try_malloc0(sizeof(struct connman_scan_pending));
1768 return __connman_error_failed(msg, ENOMEM);
1770 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1771 DBG("scan_type %d", pending_data->scan_type);
1773 pending_data->msg = dbus_message_ref(msg);
1775 technology->scan_pending =
1776 g_slist_prepend(technology->scan_pending, pending_data);
1781 #if defined TIZEN_EXT
1782 static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
1784 struct connman_technology *technology = data;
1785 DBusMessageIter iter;
1789 DBG("technology %p request from %s", technology,
1790 dbus_message_get_sender(msg));
1792 if (!dbus_message_iter_init(msg, &iter))
1793 return __connman_error_invalid_arguments(msg);
1795 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1796 return __connman_error_invalid_arguments(msg);
1798 dbus_message_iter_get_basic(&iter, &ifname);
1799 DBG("Interface name %s", ifname);
1801 if (!ifname || strlen(ifname) == 0)
1802 return __connman_error_invalid_arguments(msg);
1804 err = connman_device_request_device_scan(technology->type, ifname, true);
1806 return __connman_error_failed(msg, -err);
1808 struct connman_scan_pending *pending_data =
1809 g_try_malloc0(sizeof(struct connman_scan_pending));
1811 return __connman_error_failed(msg, ENOMEM);
1813 pending_data->ifname = g_strdup(ifname);
1814 if (pending_data->ifname == NULL) {
1815 g_free(pending_data);
1816 return __connman_error_failed(msg, ENOMEM);
1819 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1820 DBG("scan_type %d", pending_data->scan_type);
1822 pending_data->msg = dbus_message_ref(msg);
1824 technology->scan_pending =
1825 g_slist_prepend(technology->scan_pending, pending_data);
1830 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1832 struct connman_technology *technology = data;
1833 GSList *specific_scan_list = NULL;
1835 const char *name = NULL;
1836 const char *freq = NULL;
1837 const char *ifname = NULL;
1838 DBusMessageIter iter, dict;
1841 DBG("technology %p request from %s", technology,
1842 dbus_message_get_sender(msg));
1844 if (!dbus_message_iter_init(msg, &iter))
1845 return __connman_error_invalid_arguments(msg);
1847 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1848 return __connman_error_invalid_arguments(msg);
1850 dbus_message_iter_recurse(&iter, &dict);
1851 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1852 DBusMessageIter entry, value2;
1856 dbus_message_iter_recurse(&dict, &entry);
1857 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1858 g_slist_free_full(specific_scan_list, g_free);
1859 return __connman_error_invalid_arguments(msg);
1862 dbus_message_iter_get_basic(&entry, &key);
1863 dbus_message_iter_next(&entry);
1865 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1866 g_slist_free_full(specific_scan_list, g_free);
1867 return __connman_error_invalid_arguments(msg);
1870 dbus_message_iter_recurse(&entry, &value2);
1871 type = dbus_message_iter_get_arg_type(&value2);
1872 if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
1874 dbus_message_iter_get_basic(&value2, &ifname);
1875 DBG("ifname %s", ifname);
1876 } else if (g_str_equal(key, "SSID")) {
1877 if (type != DBUS_TYPE_STRING) {
1878 g_slist_free_full(specific_scan_list, g_free);
1879 return __connman_error_invalid_arguments(msg);
1882 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1883 dbus_message_iter_get_basic(&value2, &name);
1884 DBG("name %s", name);
1885 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1886 } else if (g_str_equal(key, "Frequency")) {
1887 if (type != DBUS_TYPE_STRING) {
1888 g_slist_free_full(specific_scan_list, g_free);
1889 return __connman_error_invalid_arguments(msg);
1892 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1893 dbus_message_iter_get_basic(&value2, &freq);
1894 DBG("freq %s", freq);
1895 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1896 } else if (g_str_equal(key, "SSID_Mixed")) {
1897 if (type != DBUS_TYPE_STRING) {
1898 g_slist_free_full(specific_scan_list, g_free);
1899 return __connman_error_invalid_arguments(msg);
1902 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1903 dbus_message_iter_get_basic(&value2, &name);
1905 connman_multi_scan_ap_s *ap =
1906 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1908 g_strlcpy(ap->str, name, strlen(name) + 1);
1910 specific_scan_list = g_slist_append(specific_scan_list, ap);
1912 DBG("Failed to allocate memory");
1914 } else if (g_str_equal(key, "Frequency_Mixed")) {
1915 if (type != DBUS_TYPE_STRING) {
1916 g_slist_free_full(specific_scan_list, g_free);
1917 return __connman_error_invalid_arguments(msg);
1920 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1921 dbus_message_iter_get_basic(&value2, &freq);
1923 connman_multi_scan_ap_s *ap =
1924 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1926 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1928 specific_scan_list = g_slist_append(specific_scan_list, ap);
1930 DBG("Failed to allocate memory");
1932 dbus_message_iter_next(&dict);
1935 err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
1937 return __connman_error_failed(msg, -err);
1939 guint list_size = g_slist_length(specific_scan_list);
1941 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1942 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
1943 g_slist_free_full(specific_scan_list, g_free);
1945 struct connman_scan_pending *pending_data =
1946 g_try_malloc0(sizeof(struct connman_scan_pending));
1948 return __connman_error_failed(msg, ENOMEM);
1951 pending_data->ifname = g_strdup(ifname);
1952 if (pending_data->ifname == NULL) {
1953 g_free(pending_data);
1954 return __connman_error_failed(msg, ENOMEM);
1959 pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1961 pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1962 DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
1964 pending_data->msg = dbus_message_ref(msg);
1966 technology->scan_pending =
1967 g_slist_prepend(technology->scan_pending, pending_data);
1972 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
1975 DBusMessageIter iter, dict;
1977 struct connman_technology *technology = data;
1978 dbus_bool_t supported = false;
1979 const char *ifname = NULL;
1981 DBG("technology %p", technology);
1983 reply = dbus_message_new_method_return(msg);
1987 dbus_message_iter_init_append(reply, &iter);
1988 connman_dbus_dict_open(&iter, &dict);
1990 for (list = technology->device_list; list; list = list->next) {
1991 struct connman_device *device = list->data;
1993 supported = connman_device_get_wifi_5ghz_supported(device);
1994 ifname = connman_device_get_string(device, "Interface");
1996 DBG("ifname %s supported : %d", ifname, supported);
1997 connman_dbus_dict_append_basic(&dict, ifname,
2002 connman_dbus_dict_close(&iter, &dict);
2007 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
2010 DBusMessageIter iter, dict;
2012 struct connman_technology *technology = data;
2013 dbus_bool_t scanning = false;
2014 const char *ifname = NULL;
2016 DBG("technology %p", technology);
2018 reply = dbus_message_new_method_return(msg);
2022 dbus_message_iter_init_append(reply, &iter);
2023 connman_dbus_dict_open(&iter, &dict);
2025 for (list = technology->device_list; list; list = list->next) {
2026 struct connman_device *device = list->data;
2028 scanning = connman_device_get_scanning(device, technology->type);
2029 ifname = connman_device_get_string(device, "Interface");
2031 DBG("ifname %s scanning : %d", ifname, scanning);
2032 connman_dbus_dict_append_basic(&dict, ifname,
2037 connman_dbus_dict_close(&iter, &dict);
2042 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
2045 DBusMessageIter iter, dict;
2047 struct connman_technology *technology = data;
2048 dbus_int32_t max_scan_ssids = 0;
2049 const char *ifname = NULL;
2051 DBG("technology %p", technology);
2053 reply = dbus_message_new_method_return(msg);
2057 dbus_message_iter_init_append(reply, &iter);
2058 connman_dbus_dict_open(&iter, &dict);
2060 for (list = technology->device_list; list; list = list->next) {
2061 struct connman_device *device = list->data;
2063 max_scan_ssids = connman_device_get_max_scan_ssids(device);
2064 ifname = connman_device_get_string(device, "Interface");
2066 DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
2067 connman_dbus_dict_append_basic(&dict, ifname,
2072 connman_dbus_dict_close(&iter, &dict);
2077 static int technology_enable_device(struct connman_technology *technology,
2078 bool enable_device, const char *ifname, struct connman_device **device_out)
2083 for (list = technology->device_list; list; list = list->next) {
2084 struct connman_device *device = list->data;
2085 const char *str = connman_device_get_string(device, "Interface");
2087 if (g_strcmp0(str, ifname) != 0)
2091 err = __connman_device_enable(device);
2093 err = __connman_device_disable(device);
2095 *device_out = device;
2102 static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
2103 DBusMessage *msg, bool powered, const char *ifname)
2105 DBusMessage *reply = NULL;
2106 struct connman_device *device = NULL;
2109 err = technology_enable_device(technology, powered, ifname, &device);
2111 if (err == -EINPROGRESS) {
2113 connman_device_set_pending_reply(device, msg);
2115 } else if (err == -EALREADY) {
2117 reply = __connman_error_already_enabled(msg);
2119 reply = __connman_error_already_disabled(msg);
2121 reply = __connman_error_failed(msg, -err);
2123 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2128 static DBusMessage *set_device_power(DBusConnection *conn,
2129 DBusMessage *msg, void *data)
2131 struct connman_technology *technology = data;
2132 DBusMessageIter iter;
2137 DBG("conn %p", conn);
2139 if (!dbus_message_iter_init(msg, &iter))
2140 return __connman_error_invalid_arguments(msg);
2142 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2143 return __connman_error_invalid_arguments(msg);
2145 dbus_message_iter_get_basic(&iter, &name);
2146 dbus_message_iter_next(&iter);
2148 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
2149 return __connman_error_invalid_arguments(msg);
2151 DBG("interface name %s", name);
2155 if (len + 1 > IFNAMSIZ)
2156 return __connman_error_invalid_arguments(msg);
2158 dbus_message_iter_get_basic(&iter, &enable);
2159 DBG("powered %s", enable ? "TRUE" : "FALSE");
2161 return technology_set_device_powered(technology, msg, enable, name);
2164 static DBusMessage *set_bssid(DBusConnection *conn,
2165 DBusMessage *msg, void *data)
2167 DBusMessageIter iter;
2171 DBG("conn %p", conn);
2173 if (!dbus_message_iter_init(msg, &iter))
2174 return __connman_error_invalid_arguments(msg);
2176 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2177 return __connman_error_invalid_arguments(msg);
2179 dbus_message_iter_get_basic(&iter, &name);
2180 dbus_message_iter_next(&iter);
2182 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2183 return __connman_error_invalid_arguments(msg);
2185 dbus_message_iter_get_basic(&iter, &bssid);
2187 DBG("interface name %s bssid %s", name, bssid);
2191 if (len + 1 > IFNAMSIZ)
2192 return __connman_error_invalid_arguments(msg);
2194 set_connman_bssid(SET_BSSID, bssid, name);
2196 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2198 static struct connman_technology *technology_get(enum connman_service_type type);
2200 void technology_save_device(struct connman_device *device)
2202 struct connman_technology *technology;
2203 enum connman_service_type type;
2205 type = __connman_device_get_service_type(device);
2206 technology = technology_get(type);
2212 const char *name = get_name(technology->type);
2214 DBG("technology %p type %d name %s", technology, technology->type,
2219 keyfile = __connman_storage_load_global();
2221 keyfile = g_key_file_new();
2223 identifier = g_strdup_printf("%s", name);
2227 GSList *list = NULL;
2228 gchar **ifname_list = NULL;
2229 guint dev_count = g_slist_length(technology->device_list);
2231 if (dev_count > 1) {
2232 GString *ifname_str = g_string_new(NULL);
2235 for (list = technology->device_list; list; list = list->next) {
2236 struct connman_device *device = list->data;
2238 if (connman_device_get_powered(device)) {
2239 const char *ifname = connman_device_get_string(device, "Interface");
2241 if (ifname_str->len > 0)
2242 g_string_append_printf(ifname_str, " %s", ifname);
2244 g_string_append(ifname_str, ifname);
2248 if (ifname_str->len > 0) {
2249 ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
2250 dev_count = g_strv_length(ifname_list);
2251 g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
2252 (const gchar **) ifname_list, dev_count);
2254 technology->enable_persistent = true;
2256 g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
2257 technology->enable_persistent = false;
2260 g_strfreev(ifname_list);
2261 g_string_free(ifname_str, TRUE);
2265 g_key_file_set_boolean(keyfile, identifier, "Enable",
2266 technology->enable_persistent);
2268 g_key_file_set_boolean(keyfile, identifier, "Tethering",
2269 technology->tethering_persistent);
2271 if (technology->tethering_ident)
2272 g_key_file_set_string(keyfile, identifier,
2273 "Tethering.Identifier",
2274 technology->tethering_ident);
2276 if (technology->tethering_passphrase)
2277 g_key_file_set_string(keyfile, identifier,
2278 "Tethering.Passphrase",
2279 technology->tethering_passphrase);
2284 __connman_storage_save_global(keyfile);
2286 g_key_file_free(keyfile);
2290 #if defined TIZEN_EXT_WIFI_MESH
2291 bool __connman_technology_get_connected(enum connman_service_type type)
2293 struct connman_technology *technology;
2295 technology = technology_find(type);
2300 return technology->connected;
2303 void __connman_technology_mesh_interface_create_finished(
2304 enum connman_service_type type, bool success,
2308 struct connman_technology *technology;
2310 technology = technology_find(type);
2312 DBG("technology %p success %d", technology, success);
2317 msg = technology->mesh_dbus_msg;
2319 DBG("No pending dbus message");
2324 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2325 __connman_device_request_scan(technology->type);
2327 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
2328 ".MeshInterfaceAddFailed", "%s", error);
2329 g_dbus_send_message(connection, reply);
2330 dbus_message_unref(msg);
2331 technology->mesh_dbus_msg = NULL;
2334 void __connman_technology_mesh_interface_remove_finished(
2335 enum connman_service_type type, bool success)
2338 struct connman_technology *technology;
2340 technology = technology_find(type);
2342 DBG("technology %p success %d", technology, success);
2344 if (!technology || !technology->mesh_dbus_msg)
2347 msg = technology->mesh_dbus_msg;
2349 DBG("No pending dbus message");
2354 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2356 reply = __connman_error_failed(msg, EINVAL);
2357 g_dbus_send_message(connection, reply);
2358 dbus_message_unref(msg);
2359 technology->mesh_dbus_msg = NULL;
2362 void __connman_technology_notify_abort_scan(enum connman_service_type type,
2366 struct connman_technology *technology;
2368 technology = technology_find(type);
2370 DBG("technology %p result %d", technology, result);
2372 if (!technology || !technology->mesh_dbus_msg)
2375 msg = technology->mesh_dbus_msg;
2377 DBG("No pending dbus message");
2382 reply = __connman_error_scan_abort_failed(msg);
2384 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2386 g_dbus_send_message(connection, reply);
2387 dbus_message_unref(msg);
2388 technology->mesh_dbus_msg = NULL;
2391 static DBusMessage *mesh_commands(DBusConnection *conn,
2392 DBusMessage *msg, void *data)
2394 struct connman_technology *technology = data;
2395 DBusMessageIter iter, value, dict;
2396 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
2399 DBG("conn %p", conn);
2401 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
2402 return __connman_error_invalid_arguments(msg);
2404 if (!dbus_message_iter_init(msg, &iter))
2405 return __connman_error_invalid_arguments(msg);
2407 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2408 return __connman_error_invalid_arguments(msg);
2410 dbus_message_iter_get_basic(&iter, &cmd);
2411 dbus_message_iter_next(&iter);
2413 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
2414 return __connman_error_invalid_arguments(msg);
2416 dbus_message_iter_recurse(&iter, &value);
2418 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
2419 return __connman_error_invalid_arguments(msg);
2421 DBG("Mesh Command %s", cmd);
2422 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
2423 dbus_message_iter_recurse(&value, &dict);
2424 const char *bridge_ifname = NULL;
2425 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2426 DBusMessageIter entry, value2;
2430 dbus_message_iter_recurse(&dict, &entry);
2432 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2433 return __connman_error_invalid_arguments(msg);
2435 dbus_message_iter_get_basic(&entry, &key);
2436 dbus_message_iter_next(&entry);
2438 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2439 return __connman_error_invalid_arguments(msg);
2441 dbus_message_iter_recurse(&entry, &value2);
2443 type = dbus_message_iter_get_arg_type(&value2);
2445 if (g_str_equal(key, "Ifname")) {
2446 if (type != DBUS_TYPE_STRING)
2447 return __connman_error_invalid_arguments(msg);
2449 dbus_message_iter_get_basic(&value2, &ifname);
2450 } else if (g_str_equal(key, "ParentIfname")) {
2451 if (type != DBUS_TYPE_STRING)
2452 return __connman_error_invalid_arguments(msg);
2454 dbus_message_iter_get_basic(&value2, &parent_ifname);
2455 } else if (g_str_equal(key, "BridgeIfname")) {
2456 if (type != DBUS_TYPE_STRING)
2457 return __connman_error_invalid_arguments(msg);
2459 dbus_message_iter_get_basic(&value2, &bridge_ifname);
2461 dbus_message_iter_next(&dict);
2463 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
2464 bridge_ifname ? bridge_ifname : "NULL");
2465 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
2469 DBG("Failed to add virtual mesh interface");
2470 return __connman_error_failed(msg, -err);
2473 DBG("Successfully added virtual mesh interface");
2475 dbus_message_ref(msg);
2476 technology->mesh_dbus_msg = msg;
2478 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
2479 dbus_message_iter_recurse(&value, &dict);
2480 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2481 DBusMessageIter entry, value2;
2485 dbus_message_iter_recurse(&dict, &entry);
2487 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2488 return __connman_error_invalid_arguments(msg);
2490 dbus_message_iter_get_basic(&entry, &key);
2491 dbus_message_iter_next(&entry);
2493 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2494 return __connman_error_invalid_arguments(msg);
2496 dbus_message_iter_recurse(&entry, &value2);
2498 type = dbus_message_iter_get_arg_type(&value2);
2500 if (g_str_equal(key, "Ifname")) {
2501 if (type != DBUS_TYPE_STRING)
2502 return __connman_error_invalid_arguments(msg);
2504 dbus_message_iter_get_basic(&value2, &ifname);
2506 dbus_message_iter_next(&dict);
2508 DBG("Mesh Ifname %s", ifname);
2509 err = __connman_mesh_remove_virtual_interface(ifname);
2512 DBG("Failed to remove virtual mesh interface");
2513 return __connman_error_failed(msg, -err);
2516 DBG("Successfully removed virtual mesh interface");
2518 dbus_message_ref(msg);
2519 technology->mesh_dbus_msg = msg;
2521 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
2522 struct connman_mesh *connman_mesh;
2523 const char *name = NULL;
2524 const char *sec_type = NULL;
2525 const char *mesh_ifname = NULL;
2526 char *identifier, *group, *address;
2527 unsigned int freq = 0;
2528 unsigned int ieee80211w = 0;
2531 dbus_message_iter_recurse(&value, &dict);
2532 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2533 DBusMessageIter entry, value2;
2537 dbus_message_iter_recurse(&dict, &entry);
2539 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2540 return __connman_error_invalid_arguments(msg);
2542 dbus_message_iter_get_basic(&entry, &key);
2543 dbus_message_iter_next(&entry);
2545 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2546 return __connman_error_invalid_arguments(msg);
2548 dbus_message_iter_recurse(&entry, &value2);
2550 type = dbus_message_iter_get_arg_type(&value2);
2552 if (g_str_equal(key, "Name")) {
2553 if (type != DBUS_TYPE_STRING)
2554 return __connman_error_invalid_arguments(msg);
2556 dbus_message_iter_get_basic(&value2, &name);
2557 } else if (g_str_equal(key, "Frequency")) {
2558 if (type != DBUS_TYPE_UINT16)
2559 return __connman_error_invalid_arguments(msg);
2561 dbus_message_iter_get_basic(&value2, &freq);
2562 } else if (g_str_equal(key, "Security")) {
2563 if (type != DBUS_TYPE_STRING)
2564 return __connman_error_invalid_arguments(msg);
2566 dbus_message_iter_get_basic(&value2, &sec_type);
2567 } else if (g_str_equal(key, "Pmf")) {
2568 if (type != DBUS_TYPE_UINT16)
2569 return __connman_error_invalid_arguments(msg);
2571 dbus_message_iter_get_basic(&value2, &ieee80211w);
2573 dbus_message_iter_next(&dict);
2576 if (name == NULL || sec_type == NULL || freq == 0)
2577 return __connman_error_invalid_arguments(msg);
2579 DBG("Name %s Frequency %d Security type %s Pmf %u",
2580 name, freq, sec_type, ieee80211w);
2582 if (g_strcmp0(sec_type, "none") != 0 &&
2583 g_strcmp0(sec_type, "sae") != 0) {
2584 DBG("Unsupported security");
2585 return __connman_error_invalid_arguments(msg);
2588 mesh_ifname = connman_mesh_get_interface_name();
2590 if (!connman_mesh_is_interface_created()) {
2591 DBG("Mesh interface doesn't exists");
2592 return __connman_error_invalid_command(msg);
2595 str = g_string_sized_new((strlen(name) * 2) + 24);
2597 for (i = 0; name[i]; i++)
2598 g_string_append_printf(str, "%02x", name[i]);
2600 g_string_append_printf(str, "_mesh");
2602 if (g_strcmp0(sec_type, "none") == 0)
2603 g_string_append_printf(str, "_none");
2604 else if (g_strcmp0(sec_type, "sae") == 0)
2605 g_string_append_printf(str, "_sae");
2607 group = g_string_free(str, FALSE);
2609 identifier = connman_inet_ifaddr(mesh_ifname);
2610 address = connman_inet_ifname2addr(mesh_ifname);
2612 connman_mesh = connman_mesh_create(identifier, group);
2613 connman_mesh_set_name(connman_mesh, name);
2614 connman_mesh_set_address(connman_mesh, address);
2615 connman_mesh_set_security(connman_mesh, sec_type);
2616 connman_mesh_set_frequency(connman_mesh, freq);
2617 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
2618 connman_mesh_set_peer_type(connman_mesh,
2619 CONNMAN_MESH_PEER_TYPE_CREATED);
2620 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
2622 connman_mesh_register(connman_mesh);
2626 DBG("Successfully Created Mesh Network");
2627 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2629 } else if (g_str_equal(cmd, "AbortScan")) {
2630 DBG("Abort Scan method");
2631 err = __connman_device_abort_scan(technology->type);
2633 DBG("Failed to abort scan");
2634 return __connman_error_failed(msg, -err);
2637 DBG("Successfully requested to abort scan");
2638 dbus_message_ref(msg);
2639 technology->mesh_dbus_msg = msg;
2641 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
2642 const char *name = NULL;
2643 unsigned int freq = 0;
2644 dbus_message_iter_recurse(&value, &dict);
2645 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2646 DBusMessageIter entry, value2;
2650 dbus_message_iter_recurse(&dict, &entry);
2652 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2653 return __connman_error_invalid_arguments(msg);
2655 dbus_message_iter_get_basic(&entry, &key);
2656 dbus_message_iter_next(&entry);
2658 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2659 return __connman_error_invalid_arguments(msg);
2661 dbus_message_iter_recurse(&entry, &value2);
2663 type = dbus_message_iter_get_arg_type(&value2);
2665 if (g_str_equal(key, "Name")) {
2666 if (type != DBUS_TYPE_STRING)
2667 return __connman_error_invalid_arguments(msg);
2669 dbus_message_iter_get_basic(&value2, &name);
2670 } else if (g_str_equal(key, "Frequency")) {
2671 if (type != DBUS_TYPE_UINT16)
2672 return __connman_error_invalid_arguments(msg);
2674 dbus_message_iter_get_basic(&value2, &freq);
2676 dbus_message_iter_next(&dict);
2679 DBG("MeshID %s Frequency %d sender %s", name, freq,
2680 dbus_message_get_sender(msg));
2682 struct connman_scan_pending *pending_data =
2683 g_try_malloc0(sizeof(struct connman_scan_pending));
2685 return __connman_error_failed(msg, ENOMEM);
2687 pending_data->msg = dbus_message_ref(msg);
2689 technology->scan_pending =
2690 g_slist_prepend(technology->scan_pending, pending_data);
2692 err = __connman_device_request_mesh_specific_scan(technology->type,
2695 reply_scan_pending(technology, err);
2697 DBG("Successfully requested to scan specific Mesh Network");
2699 } else if (g_str_equal(cmd, "SetMeshGate")) {
2700 unsigned int hwmp_rootmode = 0;
2701 bool gate_announce = false;
2702 unsigned int stp = 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, "GateAnnounce")) {
2726 if (type != DBUS_TYPE_BOOLEAN)
2727 return __connman_error_invalid_arguments(msg);
2729 dbus_message_iter_get_basic(&value2, &gate_announce);
2730 } else if (g_str_equal(key, "HWMPRootMode")) {
2731 if (type != DBUS_TYPE_UINT16)
2732 return __connman_error_invalid_arguments(msg);
2734 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
2735 } else if (g_str_equal(key, "STP")) {
2736 if (type != DBUS_TYPE_UINT16)
2737 return __connman_error_invalid_arguments(msg);
2739 dbus_message_iter_get_basic(&value2, &stp);
2741 dbus_message_iter_next(&dict);
2744 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
2745 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
2747 err = __connman_mesh_set_stp_gate_announce(gate_announce,
2752 return __connman_error_failed(msg, -err);
2754 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2756 return __connman_error_invalid_command(msg);
2761 static const GDBusMethodTable technology_methods[] = {
2762 { GDBUS_DEPRECATED_METHOD("GetProperties",
2763 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
2765 { GDBUS_ASYNC_METHOD("SetProperty",
2766 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2767 NULL, set_property) },
2768 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
2769 #if defined TIZEN_EXT
2770 { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
2771 NULL, scan_device) },
2772 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
2773 NULL, specific_scan) },
2774 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
2776 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2777 get_5ghz_supported) },
2778 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2779 get_max_scan_ssid) },
2780 { GDBUS_ASYNC_METHOD("SetDevicePower",
2781 GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
2782 NULL, set_device_power) },
2783 { GDBUS_ASYNC_METHOD("SetBSSID",
2784 GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
2787 #if defined TIZEN_EXT_WIFI_MESH
2788 { GDBUS_ASYNC_METHOD("MeshCommands",
2789 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2790 NULL, mesh_commands) },
2795 static const GDBusSignalTable technology_signals[] = {
2796 { GDBUS_SIGNAL("PropertyChanged",
2797 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2798 #if defined TIZEN_EXT
2799 { GDBUS_SIGNAL("DeviceChanged",
2800 GDBUS_ARGS({ "device_property", "a{sv}" })) },
2801 { GDBUS_SIGNAL("DeviceDetected",
2802 GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
2807 static bool technology_dbus_register(struct connman_technology *technology)
2809 if (technology->dbus_registered ||
2810 (technology->rfkill_driven &&
2811 technology->hardblocked))
2814 if (!g_dbus_register_interface(connection, technology->path,
2815 CONNMAN_TECHNOLOGY_INTERFACE,
2816 technology_methods, technology_signals,
2817 NULL, technology, NULL)) {
2818 connman_error("Failed to register %s", technology->path);
2822 technology_added_signal(technology);
2823 technology->dbus_registered = true;
2828 static void technology_dbus_unregister(struct connman_technology *technology)
2830 if (!technology->dbus_registered)
2833 technology_removed_signal(technology);
2834 g_dbus_unregister_interface(connection, technology->path,
2835 CONNMAN_TECHNOLOGY_INTERFACE);
2837 technology->dbus_registered = false;
2840 static void technology_put(struct connman_technology *technology)
2842 DBG("technology %p", technology);
2844 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2847 reply_scan_pending(technology, -EINTR);
2849 while (technology->driver_list) {
2850 struct connman_technology_driver *driver;
2852 driver = technology->driver_list->data;
2855 driver->remove(technology);
2857 technology->driver_list =
2858 g_slist_delete_link(technology->driver_list,
2859 technology->driver_list);
2862 technology_list = g_slist_remove(technology_list, technology);
2864 technology_dbus_unregister(technology);
2866 g_slist_free(technology->device_list);
2868 if (technology->pending_reply) {
2869 dbus_message_unref(technology->pending_reply);
2870 technology->pending_reply = NULL;
2871 g_source_remove(technology->pending_timeout);
2872 technology->pending_timeout = 0;
2875 g_strfreev(technology->enabled_devices);
2877 g_free(technology->path);
2878 g_free(technology->regdom);
2879 g_free(technology->tethering_ident);
2880 g_free(technology->tethering_passphrase);
2884 static struct connman_technology *technology_get(enum connman_service_type type)
2886 GSList *tech_drivers = NULL;
2887 struct connman_technology_driver *driver;
2888 struct connman_technology *technology;
2892 DBG("type %d", type);
2894 str = __connman_service_type2string(type);
2898 technology = technology_find(type);
2900 #if defined TIZEN_EXT_WIFI_MESH
2901 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2902 type != CONNMAN_SERVICE_TYPE_MESH)
2904 if (type != CONNMAN_SERVICE_TYPE_P2P)
2906 __sync_fetch_and_add(&technology->refcount, 1);
2910 /* First check if we have a driver for this technology type */
2911 for (list = driver_list; list; list = list->next) {
2912 driver = list->data;
2914 if (driver->type == type) {
2915 DBG("technology %p driver %p", technology, driver);
2916 tech_drivers = g_slist_append(tech_drivers, driver);
2920 if (!tech_drivers) {
2921 DBG("No matching drivers found for %s.",
2922 __connman_service_type2string(type));
2926 technology = g_try_new0(struct connman_technology, 1);
2930 technology->refcount = 1;
2931 technology->type = type;
2932 technology->path = g_strdup_printf("%s/technology/%s",
2935 #if defined TIZEN_EXT_WIFI_MESH
2936 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2937 struct connman_technology *wifi;
2939 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2941 technology->enabled = wifi->enabled;
2945 technology_load(technology);
2946 technology_list = g_slist_prepend(technology_list, technology);
2947 technology->driver_list = tech_drivers;
2949 for (list = tech_drivers; list; list = list->next) {
2950 driver = list->data;
2952 if (driver->probe && driver->probe(technology) < 0)
2953 DBG("Driver probe failed for technology %p",
2957 if (!technology_dbus_register(technology)) {
2958 technology_put(technology);
2962 if (type == CONNMAN_SERVICE_TYPE_P2P) {
2963 struct connman_technology *wifi;
2966 enable = technology->enable_persistent;
2968 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2970 enable = wifi->enabled;
2972 technology_affect_devices(technology, enable);
2975 DBG("technology %p %s", technology, get_name(technology->type));
2980 int connman_technology_driver_register(struct connman_technology_driver *driver)
2983 struct connman_device *device;
2984 enum connman_service_type type;
2986 for (list = driver_list; list; list = list->next) {
2987 if (list->data == driver)
2991 DBG("Registering %s driver", driver->name);
2993 driver_list = g_slist_insert_sorted(driver_list, driver,
2997 * Check for technology less devices if this driver
2998 * can service any of them.
3000 for (list = techless_device_list; list; list = list->next) {
3001 device = list->data;
3003 type = __connman_device_get_service_type(device);
3004 if (type != driver->type)
3007 techless_device_list = g_slist_remove(techless_device_list,
3010 __connman_technology_add_device(device);
3013 /* Check for orphaned rfkill switches. */
3014 g_hash_table_foreach(rfkill_list, rfkill_check,
3015 GINT_TO_POINTER(driver->type));
3018 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3019 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
3023 #if defined TIZEN_EXT_WIFI_MESH
3024 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3025 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
3033 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
3035 GSList *list, *tech_drivers;
3036 struct connman_technology *technology;
3037 struct connman_technology_driver *current;
3039 DBG("Unregistering driver %p name %s", driver, driver->name);
3041 for (list = technology_list; list; list = list->next) {
3042 technology = list->data;
3044 for (tech_drivers = technology->driver_list; tech_drivers;
3045 tech_drivers = g_slist_next(tech_drivers)) {
3046 current = tech_drivers->data;
3047 if (driver != current)
3051 driver->remove(technology);
3053 technology->driver_list =
3054 g_slist_remove(technology->driver_list,
3060 driver_list = g_slist_remove(driver_list, driver);
3062 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3063 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
3065 technology_put(technology);
3067 #if defined TIZEN_EXT_WIFI_MESH
3068 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3069 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
3071 technology_put(technology);
3076 void __connman_technology_add_interface(enum connman_service_type type,
3077 int index, const char *ident)
3079 struct connman_technology *technology;
3080 GSList *tech_drivers;
3081 struct connman_technology_driver *driver;
3085 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3086 case CONNMAN_SERVICE_TYPE_SYSTEM:
3088 case CONNMAN_SERVICE_TYPE_ETHERNET:
3089 case CONNMAN_SERVICE_TYPE_WIFI:
3090 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3091 case CONNMAN_SERVICE_TYPE_CELLULAR:
3092 case CONNMAN_SERVICE_TYPE_GPS:
3093 case CONNMAN_SERVICE_TYPE_VPN:
3094 case CONNMAN_SERVICE_TYPE_GADGET:
3095 case CONNMAN_SERVICE_TYPE_P2P:
3096 #if defined TIZEN_EXT_WIFI_MESH
3097 case CONNMAN_SERVICE_TYPE_MESH:
3102 name = connman_inet_ifname(index);
3103 connman_info("Adding interface %s [ %s ]", name,
3104 __connman_service_type2string(type));
3106 technology = technology_find(type);
3111 for (tech_drivers = technology->driver_list; tech_drivers;
3112 tech_drivers = g_slist_next(tech_drivers)) {
3113 driver = tech_drivers->data;
3115 if (driver->add_interface)
3116 driver->add_interface(technology, index, name, ident);
3120 * At this point we can try to enable tethering automatically as
3121 * now the interfaces are set properly.
3123 if (technology->tethering_persistent)
3124 enable_tethering(technology);
3130 void __connman_technology_remove_interface(enum connman_service_type type,
3131 int index, const char *ident)
3133 struct connman_technology *technology;
3134 GSList *tech_drivers;
3135 struct connman_technology_driver *driver;
3139 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3140 case CONNMAN_SERVICE_TYPE_SYSTEM:
3142 case CONNMAN_SERVICE_TYPE_ETHERNET:
3143 case CONNMAN_SERVICE_TYPE_WIFI:
3144 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3145 case CONNMAN_SERVICE_TYPE_CELLULAR:
3146 case CONNMAN_SERVICE_TYPE_GPS:
3147 case CONNMAN_SERVICE_TYPE_VPN:
3148 case CONNMAN_SERVICE_TYPE_GADGET:
3149 case CONNMAN_SERVICE_TYPE_P2P:
3150 #if defined TIZEN_EXT_WIFI_MESH
3151 case CONNMAN_SERVICE_TYPE_MESH:
3156 name = connman_inet_ifname(index);
3157 connman_info("Remove interface %s [ %s ]", name,
3158 __connman_service_type2string(type));
3161 technology = technology_find(type);
3166 for (tech_drivers = technology->driver_list; tech_drivers;
3167 tech_drivers = g_slist_next(tech_drivers)) {
3168 driver = tech_drivers->data;
3170 if (driver->remove_interface)
3171 driver->remove_interface(technology, index);
3175 int __connman_technology_add_device(struct connman_device *device)
3177 struct connman_technology *technology;
3178 enum connman_service_type type;
3180 type = __connman_device_get_service_type(device);
3182 DBG("device %p type %s", device, get_name(type));
3184 technology = technology_get(type);
3187 * Since no driver can be found for this device at the moment we
3188 * add it to the techless device list.
3190 techless_device_list = g_slist_prepend(techless_device_list,
3196 __sync_synchronize();
3197 if (technology->rfkill_driven) {
3198 if (technology->enabled)
3199 __connman_device_enable(device);
3201 __connman_device_disable(device);
3206 if (technology->enable_persistent &&
3207 !global_offlinemode) {
3208 #if defined TIZEN_EXT
3211 if (technology->enabled_devices) {
3214 const char *ifname = connman_device_get_string(device, "Interface");
3216 while (technology->enabled_devices[i]) {
3217 if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
3226 err = __connman_device_enable(device);
3228 int err = __connman_device_enable(device);
3231 * connman_technology_add_device() calls __connman_device_enable()
3232 * but since the device is already enabled, the call does not
3233 * propagate through to connman_technology_enabled via
3234 * connman_device_set_powered.
3236 if (err == -EALREADY)
3237 __connman_technology_enabled(type);
3239 /* if technology persistent state is offline */
3240 if (!technology->enable_persistent)
3241 __connman_device_disable(device);
3244 technology->device_list = g_slist_prepend(technology->device_list,
3247 #if defined TIZEN_EXT
3248 const char *ifname = connman_device_get_string(device, "Interface");
3249 __connman_technology_notify_device_detected(technology, ifname, true);
3251 connman_device_set_mac_policy(device, technology->mac_policy);
3252 connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy);
3253 connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime);
3258 int __connman_technology_remove_device(struct connman_device *device)
3260 struct connman_technology *technology;
3261 enum connman_service_type type;
3263 DBG("device %p", device);
3265 type = __connman_device_get_service_type(device);
3267 technology = technology_find(type);
3269 techless_device_list = g_slist_remove(techless_device_list,
3274 technology->device_list = g_slist_remove(technology->device_list,
3277 #if defined TIZEN_EXT
3278 const char *ifname = connman_device_get_string(device, "Interface");
3279 __connman_technology_notify_device_detected(technology, ifname, false);
3282 if (technology->tethering)
3283 set_tethering(technology, false);
3285 technology_put(technology);
3290 int __connman_technology_enabled(enum connman_service_type type)
3292 struct connman_technology *technology;
3294 technology = technology_find(type);
3298 DBG("technology %p type %s rfkill %d enabled %d", technology,
3299 get_name(type), technology->rfkill_driven,
3300 technology->enabled);
3302 #if !defined TIZEN_EXT
3303 if (technology->rfkill_driven) {
3304 if (technology->tethering_persistent)
3305 enable_tethering(technology);
3310 return technology_enabled(technology);
3313 int __connman_technology_disabled(enum connman_service_type type)
3315 struct connman_technology *technology;
3318 technology = technology_find(type);
3322 #if !defined TIZEN_EXT
3323 if (technology->rfkill_driven)
3327 for (list = technology->device_list; list; list = list->next) {
3328 struct connman_device *device = list->data;
3330 if (connman_device_get_powered(device))
3334 return technology_disabled(technology);
3337 int __connman_technology_set_offlinemode(bool offlinemode)
3340 int err = -EINVAL, enabled_tech_count = 0;
3342 if (global_offlinemode == offlinemode)
3345 DBG("offlinemode %s", offlinemode ? "On" : "Off");
3348 * This is a bit tricky. When you set offlinemode, there is no
3349 * way to differentiate between attempting offline mode and
3350 * resuming offlinemode from last saved profile. We need that
3351 * information in rfkill_update, otherwise it falls back on the
3352 * technology's persistent state. Hence we set the offline mode here
3353 * but save it & call the notifier only if it is successful.
3356 global_offlinemode = offlinemode;
3358 /* Traverse technology list, enable/disable each technology. */
3359 for (list = technology_list; list; list = list->next) {
3360 struct connman_technology *technology = list->data;
3363 err = technology_disable(technology);
3365 if (technology->hardblocked)
3368 if (technology->enable_persistent) {
3369 err = technology_enable(technology);
3370 enabled_tech_count++;
3375 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
3376 (err == -EINVAL && enabled_tech_count == 0)) {
3377 connman_technology_save_offlinemode();
3378 __connman_notifier_offlinemode(offlinemode);
3380 global_offlinemode = connman_technology_load_offlinemode();
3385 #if defined TIZEN_EXT_WIFI_MESH
3386 static gboolean __add_ethernet_to_bridge(gpointer data)
3389 __connman_mesh_add_ethernet_to_bridge();
3394 void __connman_technology_set_connected(enum connman_service_type type,
3397 struct connman_technology *technology;
3400 technology = technology_find(type);
3404 DBG("technology %p connected %d", technology, connected);
3406 technology->connected = connected;
3408 #if defined TIZEN_EXT_WIFI_MESH
3409 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
3410 g_idle_add(__add_ethernet_to_bridge, NULL);
3414 connman_dbus_property_changed_basic(technology->path,
3415 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
3416 DBUS_TYPE_BOOLEAN, &val);
3419 static bool technology_apply_rfkill_change(struct connman_technology *technology,
3424 bool hardblock_changed = false;
3426 GList *start, *list;
3428 DBG("technology %p --> %d/%d vs %d/%d",
3429 technology, softblock, hardblock,
3430 technology->softblocked, technology->hardblocked);
3432 if (technology->hardblocked == hardblock)
3433 goto softblock_change;
3435 if (!(new_rfkill && !hardblock)) {
3436 start = g_hash_table_get_values(rfkill_list);
3438 for (list = start; list; list = list->next) {
3439 struct connman_rfkill *rfkill = list->data;
3441 if (rfkill->type != technology->type)
3444 if (rfkill->hardblock != hardblock)
3452 goto softblock_change;
3454 technology->hardblocked = hardblock;
3455 hardblock_changed = true;
3458 if (!apply && technology->softblocked != softblock)
3462 return technology->hardblocked;
3464 technology->softblocked = softblock;
3466 if (technology->hardblocked ||
3467 technology->softblocked) {
3468 if (technology_disabled(technology) != -EALREADY)
3469 technology_affect_devices(technology, false);
3470 } else if (!technology->hardblocked &&
3471 !technology->softblocked) {
3472 if (technology_enabled(technology) != -EALREADY)
3473 technology_affect_devices(technology, true);
3476 if (hardblock_changed) {
3477 if (technology->hardblocked) {
3478 DBG("%s is switched off.", get_name(technology->type));
3479 technology_dbus_unregister(technology);
3481 DBG("%s is switched on.", get_name(technology->type));
3482 technology_dbus_register(technology);
3484 if (global_offlinemode)
3485 __connman_rfkill_block(technology->type, true);
3489 return technology->hardblocked;
3492 int __connman_technology_add_rfkill(unsigned int index,
3493 enum connman_service_type type,
3497 struct connman_technology *technology;
3498 struct connman_rfkill *rfkill;
3500 DBG("index %u type %d soft %u hard %u", index, type,
3501 softblock, hardblock);
3503 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3507 rfkill = g_try_new0(struct connman_rfkill, 1);
3511 rfkill->index = index;
3512 rfkill->type = type;
3513 rfkill->softblock = softblock;
3514 rfkill->hardblock = hardblock;
3516 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
3519 #if defined TIZEN_EXT
3520 /* Fix Svace Issue [WGID: 1348]. */
3523 technology = technology_get(type);
3524 /* If there is no driver for this type, ignore it. */
3528 technology->rfkill_driven = true;
3530 #if !defined TIZEN_EXT
3531 /* If hardblocked, there is no need to handle softblocked state */
3532 if (technology_apply_rfkill_change(technology,
3533 softblock, hardblock, true))
3537 if (global_offlinemode)
3541 * Depending on softblocked state we unblock/block according to
3542 * offlinemode and persistente state.
3544 if (technology->softblocked &&
3545 technology->enable_persistent)
3546 return __connman_rfkill_block(type, false);
3547 else if (!technology->softblocked &&
3548 !technology->enable_persistent)
3549 return __connman_rfkill_block(type, true);
3554 int __connman_technology_update_rfkill(unsigned int index,
3555 enum connman_service_type type,
3559 struct connman_technology *technology;
3560 struct connman_rfkill *rfkill;
3562 DBG("index %u soft %u hard %u", index, softblock, hardblock);
3564 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3568 if (rfkill->softblock == softblock &&
3569 rfkill->hardblock == hardblock)
3572 rfkill->softblock = softblock;
3573 rfkill->hardblock = hardblock;
3575 technology = technology_find(type);
3576 /* If there is no driver for this type, ignore it. */
3580 technology_apply_rfkill_change(technology, softblock, hardblock,
3583 if (technology->hardblocked)
3584 DBG("%s hardblocked", get_name(technology->type));
3586 DBG("%s is%s softblocked", get_name(technology->type),
3587 technology->softblocked ? "" : " not");
3592 int __connman_technology_remove_rfkill(unsigned int index,
3593 enum connman_service_type type)
3595 struct connman_technology *technology;
3596 struct connman_rfkill *rfkill;
3598 DBG("index %u", index);
3600 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3604 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
3606 technology = technology_find(type);
3610 technology_apply_rfkill_change(technology,
3611 technology->softblocked, !technology->hardblocked, false);
3613 technology_put(technology);
3618 int __connman_technology_init(void)
3622 connection = connman_dbus_get_connection();
3624 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3627 global_offlinemode = connman_technology_load_offlinemode();
3629 /* This will create settings file if it is missing */
3630 connman_technology_save_offlinemode();
3635 void __connman_technology_cleanup(void)
3639 while (technology_list) {
3640 struct connman_technology *technology = technology_list->data;
3641 technology_list = g_slist_remove(technology_list, technology);
3642 technology_put(technology);
3645 g_hash_table_destroy(rfkill_list);
3647 dbus_connection_unref(connection);