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 #if defined TIZEN_EXT
715 connman_dbus_dict_append_basic(&dict, "MacPolicy",
717 &(technology->mac_policy));
719 connman_dbus_dict_append_basic(&dict, "PreassocMacPolicy",
721 &(technology->preassoc_mac_policy));
723 connman_dbus_dict_append_basic(&dict, "RandomMacLifetime",
725 &(technology->random_mac_lifetime));
727 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
728 connman_dbus_dict_append_dict(&dict, "Device.List",
729 append_devices, technology);
730 if (technology->regdom)
731 connman_dbus_dict_append_basic(&dict, "CountryCode",
733 &technology->regdom);
735 connman_dbus_dict_close(iter, &dict);
738 static void technology_added_signal(struct connman_technology *technology)
741 DBusMessageIter iter;
743 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
744 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
748 dbus_message_iter_init_append(signal, &iter);
749 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
751 append_properties(&iter, technology);
753 dbus_connection_send(connection, signal, NULL);
754 dbus_message_unref(signal);
757 static void technology_removed_signal(struct connman_technology *technology)
759 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
760 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
761 DBUS_TYPE_OBJECT_PATH, &technology->path,
765 static DBusMessage *get_properties(DBusConnection *conn,
766 DBusMessage *message, void *user_data)
768 struct connman_technology *technology = user_data;
770 DBusMessageIter iter;
772 reply = dbus_message_new_method_return(message);
776 dbus_message_iter_init_append(reply, &iter);
777 append_properties(&iter, technology);
782 void __connman_technology_list_struct(DBusMessageIter *array)
785 DBusMessageIter entry;
787 for (list = technology_list; list; list = list->next) {
788 struct connman_technology *technology = list->data;
790 if (!technology->path ||
791 (technology->rfkill_driven &&
792 technology->hardblocked))
795 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
797 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
799 append_properties(&entry, technology);
800 dbus_message_iter_close_container(array, &entry);
804 static gboolean technology_pending_reply(gpointer user_data)
806 struct connman_technology *technology = user_data;
809 /* Power request timed out, send ETIMEDOUT. */
810 if (technology->pending_reply) {
811 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
813 g_dbus_send_message(connection, reply);
815 dbus_message_unref(technology->pending_reply);
816 technology->pending_reply = NULL;
817 technology->pending_timeout = 0;
823 static int technology_affect_devices(struct connman_technology *technology,
826 int err = 0, err_dev;
829 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
831 __connman_technology_enabled(technology->type);
833 __connman_technology_disabled(technology->type);
837 #if defined TIZEN_EXT_WIFI_MESH
838 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
842 for (list = technology->device_list; list; list = list->next) {
843 struct connman_device *device = list->data;
846 err_dev = __connman_device_enable(device);
848 err_dev = __connman_device_disable(device);
850 if (err_dev < 0 && err_dev != -EALREADY)
857 static void powered_changed(struct connman_technology *technology)
861 if (!technology->dbus_registered)
864 if (technology->pending_reply) {
865 g_dbus_send_reply(connection,
866 technology->pending_reply, DBUS_TYPE_INVALID);
867 dbus_message_unref(technology->pending_reply);
868 technology->pending_reply = NULL;
870 g_source_remove(technology->pending_timeout);
871 technology->pending_timeout = 0;
874 __sync_synchronize();
875 enabled = technology->enabled;
876 #if defined TIZEN_EXT
877 DBG("ConnMan, Powered : %s, %s",
878 enabled ? "TRUE" : "FALSE",technology->path);
880 connman_dbus_property_changed_basic(technology->path,
881 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
882 DBUS_TYPE_BOOLEAN, &enabled);
885 static void enable_tethering(struct connman_technology *technology)
889 if (!connman_setting_get_bool("PersistentTetheringMode"))
892 ret = set_tethering(technology, true);
893 if (ret < 0 && ret != -EALREADY)
894 DBG("Cannot enable tethering yet for %s (%d/%s)",
895 get_name(technology->type),
896 -ret, strerror(-ret));
899 static int technology_enabled(struct connman_technology *technology)
901 __sync_synchronize();
902 if (technology->enabled)
905 technology->enabled = true;
907 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
908 struct connman_technology *p2p;
910 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
911 if (p2p && !p2p->enabled && p2p->enable_persistent)
912 technology_enabled(p2p);
915 if (technology->tethering_persistent)
916 enable_tethering(technology);
918 powered_changed(technology);
923 static int technology_enable(struct connman_technology *technology)
928 DBG("technology %p enable", technology);
930 __sync_synchronize();
932 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
933 struct connman_technology *wifi;
935 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
936 if (wifi && wifi->enabled)
937 return technology_enabled(technology);
941 if (technology->enabled)
944 if (technology->pending_reply)
947 if (connman_setting_get_bool("PersistentTetheringMode") &&
948 technology->tethering)
949 set_tethering(technology, true);
951 if (technology->rfkill_driven)
952 err = __connman_rfkill_block(technology->type, false);
954 err_dev = technology_affect_devices(technology, true);
956 if (!technology->rfkill_driven)
962 static int technology_disabled(struct connman_technology *technology)
964 __sync_synchronize();
965 if (!technology->enabled)
968 technology->enabled = false;
970 powered_changed(technology);
975 static int technology_disable(struct connman_technology *technology)
979 DBG("technology %p disable", technology);
981 __sync_synchronize();
983 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
984 technology->enable_persistent = false;
985 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
986 __connman_peer_disconnect_all();
987 return technology_disabled(technology);
988 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
989 struct connman_technology *p2p;
991 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
992 if (p2p && p2p->enabled) {
993 p2p->enable_persistent = true;
994 technology_disabled(p2p);
998 if (!technology->enabled)
1001 if (technology->pending_reply)
1004 if (technology->tethering)
1005 set_tethering(technology, false);
1007 err = technology_affect_devices(technology, false);
1009 if (technology->rfkill_driven)
1010 err = __connman_rfkill_block(technology->type, true);
1015 static DBusMessage *set_powered(struct connman_technology *technology,
1016 DBusMessage *msg, bool powered)
1018 DBusMessage *reply = NULL;
1021 if (technology->rfkill_driven && technology->hardblocked) {
1027 err = technology_enable(technology);
1029 err = technology_disable(technology);
1031 if (err != -EBUSY) {
1032 technology->enable_persistent = powered;
1033 technology_save(technology);
1037 if (err == -EINPROGRESS) {
1038 technology->pending_reply = dbus_message_ref(msg);
1039 technology->pending_timeout = g_timeout_add_seconds(10,
1040 technology_pending_reply, technology);
1041 } else if (err == -EALREADY) {
1043 reply = __connman_error_already_enabled(msg);
1045 reply = __connman_error_already_disabled(msg);
1047 reply = __connman_error_failed(msg, -err);
1049 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1054 #if defined TIZEN_EXT
1055 int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
1057 static int bssid_len;
1058 static const char *def_ifname = "default";
1059 static GSList *bssid_list = NULL;
1061 const char *local_ifname = ifname;
1063 struct connman_bssid_pending *bssid_info;
1065 DBG("mode: %d, ifname: %s", mode, ifname);
1068 local_ifname = def_ifname;
1070 for (list = bssid_list; list; list = list->next) {
1071 bssid_info = list->data;
1073 if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
1079 if (mode == CHECK_BSSID) {
1086 if (mode == GET_BSSID && bssid) {
1088 memcpy(bssid, bssid_info->bssid, 6);
1094 if (mode == RESET_BSSID) {
1096 bssid_list = g_slist_remove(bssid_list, bssid_info);
1097 g_free(bssid_info->ifname);
1103 if (mode != SET_BSSID || !bssid) {
1104 DBG("Invalid parameter");
1109 bssid_list = g_slist_remove(bssid_list, bssid_info);
1110 g_free(bssid_info->ifname);
1114 bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
1116 DBG("Failed to allocate memory");
1120 unsigned char *bssid_data = bssid_info->bssid;
1122 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1123 &bssid_data[0], &bssid_data[1], &bssid_data[2],
1124 &bssid_data[3], &bssid_data[4], &bssid_data[5]);
1125 if (bssid_len != 6) {
1126 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
1131 DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
1133 bssid_data[0], bssid_data[1], bssid_data[2],
1134 bssid_data[3], bssid_data[4], bssid_data[5],
1137 bssid_info->ifname = g_strdup(ifname);
1138 bssid_list = g_slist_prepend(bssid_list, bssid_info);
1143 void connman_technology_mac_policy_notify(struct connman_technology *technology,
1144 unsigned int policy)
1146 DBG("Mac polict set to %u", policy);
1148 technology->mac_policy = policy;
1149 technology_save(technology);
1152 void __connman_technology_notify_mac_policy_by_device(struct connman_device *device,
1153 int result, unsigned int policy)
1155 struct connman_technology *technology;
1156 enum connman_service_type type;
1158 type = __connman_device_get_service_type(device);
1159 technology = technology_find(type);
1164 connman_technology_mac_policy_notify(technology, policy);
1167 static DBusMessage *set_mac_policy(struct connman_technology *technology,
1168 DBusMessage *msg, unsigned int policy)
1170 DBusMessage *reply = NULL;
1172 unsigned int last_policy = technology->mac_policy;
1174 if (technology->rfkill_driven && technology->hardblocked) {
1179 for (GSList *list = technology->device_list; list; list = list->next) {
1180 struct connman_device *device = list->data;
1182 err = connman_device_set_mac_policy(device, policy);
1189 if (err != -EACCES && err != -EOPNOTSUPP) {
1190 for (GSList *list = technology->device_list; list; list = list->next) {
1191 struct connman_device *device = list->data;
1193 connman_device_set_mac_policy(device, last_policy);
1197 reply = __connman_error_failed(msg, -err);
1199 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1205 void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology,
1206 unsigned int policy)
1208 DBG("Preassoc mac polict set to %u", policy);
1210 technology->preassoc_mac_policy = policy;
1211 technology_save(technology);
1214 void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device,
1215 int result, unsigned int policy)
1217 struct connman_technology *technology;
1218 enum connman_service_type type;
1220 type = __connman_device_get_service_type(device);
1221 technology = technology_find(type);
1226 connman_technology_preassoc_mac_policy_notify(technology, policy);
1229 static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology,
1230 DBusMessage *msg, unsigned int policy)
1232 DBusMessage *reply = NULL;
1234 unsigned int last_policy = technology->preassoc_mac_policy;
1236 if (technology->rfkill_driven && technology->hardblocked) {
1241 for (GSList *list = technology->device_list; list; list = list->next) {
1242 struct connman_device *device = list->data;
1244 err = connman_device_set_preassoc_mac_policy(device, policy);
1251 if (err != -EACCES && err != -EOPNOTSUPP) {
1252 for (GSList *list = technology->device_list; list; list = list->next) {
1253 struct connman_device *device = list->data;
1255 connman_device_set_preassoc_mac_policy(device, last_policy);
1259 reply = __connman_error_failed(msg, -err);
1261 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1267 void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology,
1268 unsigned int lifetime)
1270 DBG("Random mac lifetime set to %u", lifetime);
1272 technology->random_mac_lifetime = lifetime;
1273 technology_save(technology);
1276 void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device,
1277 int result, unsigned int lifetime)
1279 struct connman_technology *technology;
1280 enum connman_service_type type;
1282 type = __connman_device_get_service_type(device);
1283 technology = technology_find(type);
1288 connman_technology_random_mac_lifetime_notify(technology, lifetime);
1291 static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology,
1292 DBusMessage *msg, unsigned int lifetime)
1294 DBusMessage *reply = NULL;
1296 unsigned int last_lifetime = technology->random_mac_lifetime;
1298 if (technology->rfkill_driven && technology->hardblocked) {
1303 for (GSList *list = technology->device_list; list; list = list->next) {
1304 struct connman_device *device = list->data;
1306 err = connman_device_set_random_mac_lifetime(device, lifetime);
1311 if (err != -EACCES && err != -EOPNOTSUPP) {
1312 for (GSList *list = technology->device_list; list; list = list->next) {
1313 struct connman_device *device = list->data;
1315 connman_device_set_random_mac_lifetime(device, last_lifetime);
1319 reply = __connman_error_failed(msg, -err);
1321 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1328 static DBusMessage *set_property(DBusConnection *conn,
1329 DBusMessage *msg, void *data)
1331 struct connman_technology *technology = data;
1332 DBusMessageIter iter, value;
1336 DBG("conn %p", conn);
1338 if (!dbus_message_iter_init(msg, &iter))
1339 return __connman_error_invalid_arguments(msg);
1341 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1342 return __connman_error_invalid_arguments(msg);
1344 dbus_message_iter_get_basic(&iter, &name);
1345 dbus_message_iter_next(&iter);
1347 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1348 return __connman_error_invalid_arguments(msg);
1350 dbus_message_iter_recurse(&iter, &value);
1352 type = dbus_message_iter_get_arg_type(&value);
1354 DBG("property %s", name);
1356 if (g_str_equal(name, "Tethering")) {
1357 dbus_bool_t tethering;
1360 if (type != DBUS_TYPE_BOOLEAN)
1361 return __connman_error_invalid_arguments(msg);
1363 if (!connman_technology_is_tethering_allowed(technology->type)) {
1364 DBG("%s tethering not allowed by config file",
1365 __connman_service_type2string(technology->type));
1366 return __connman_error_not_supported(msg);
1369 dbus_message_iter_get_basic(&value, &tethering);
1371 if (technology->tethering == tethering) {
1373 return __connman_error_already_disabled(msg);
1375 return __connman_error_already_enabled(msg);
1378 err = set_tethering(technology, tethering);
1380 return __connman_error_failed(msg, -err);
1382 technology->tethering_persistent = tethering;
1384 technology_save(technology);
1386 } else if (g_str_equal(name, "TetheringIdentifier")) {
1389 dbus_message_iter_get_basic(&value, &str);
1391 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1392 return __connman_error_not_supported(msg);
1394 if (strlen(str) < 1 || strlen(str) > 32)
1395 return __connman_error_invalid_arguments(msg);
1397 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1398 g_free(technology->tethering_ident);
1399 technology->tethering_ident = g_strdup(str);
1400 technology_save(technology);
1402 connman_dbus_property_changed_basic(technology->path,
1403 CONNMAN_TECHNOLOGY_INTERFACE,
1404 "TetheringIdentifier",
1406 &technology->tethering_ident);
1408 } else if (g_str_equal(name, "TetheringPassphrase")) {
1411 dbus_message_iter_get_basic(&value, &str);
1413 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1414 return __connman_error_not_supported(msg);
1416 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1419 return __connman_error_passphrase_required(msg);
1421 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1422 g_free(technology->tethering_passphrase);
1423 technology->tethering_passphrase = g_strdup(str);
1424 technology_save(technology);
1426 connman_dbus_property_changed_basic(technology->path,
1427 CONNMAN_TECHNOLOGY_INTERFACE,
1428 "TetheringPassphrase",
1430 &technology->tethering_passphrase);
1432 } else if (g_str_equal(name, "Powered")) {
1435 if (type != DBUS_TYPE_BOOLEAN)
1436 return __connman_error_invalid_arguments(msg);
1438 dbus_message_iter_get_basic(&value, &enable);
1440 return set_powered(technology, msg, enable);
1441 #if defined TIZEN_EXT
1442 } else if (g_str_equal(name, "SetBSSID")) {
1445 if (type != DBUS_TYPE_STRING)
1446 return __connman_error_invalid_arguments(msg);
1448 dbus_message_iter_get_basic(&value, &key);
1449 DBG("BSSID %s", key);
1450 set_connman_bssid(SET_BSSID, key, NULL);
1451 } else if (g_str_equal(name, "MacPolicy")) {
1452 dbus_uint32_t mac_policy;
1454 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1455 return __connman_error_not_supported(msg);
1457 if (type != DBUS_TYPE_UINT32)
1458 return __connman_error_invalid_arguments(msg);
1460 dbus_message_iter_get_basic(&value, &mac_policy);
1462 if (mac_policy <= 2)
1463 return set_mac_policy(technology, msg, mac_policy);
1465 return __connman_error_invalid_arguments(msg);
1467 } else if (g_str_equal(name, "PreassocMacPolicy")) {
1468 dbus_uint32_t preassoc_mac_policy;
1470 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1471 return __connman_error_not_supported(msg);
1473 if (type != DBUS_TYPE_UINT32)
1474 return __connman_error_invalid_arguments(msg);
1476 dbus_message_iter_get_basic(&value, &preassoc_mac_policy);
1478 if (preassoc_mac_policy <= 2)
1479 return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy);
1481 return __connman_error_invalid_arguments(msg);
1483 } else if (g_str_equal(name, "RandomMacLifetime")) {
1484 dbus_uint32_t random_mac_lifetime;
1486 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1487 return __connman_error_not_supported(msg);
1489 if (type != DBUS_TYPE_UINT32)
1490 return __connman_error_invalid_arguments(msg);
1492 dbus_message_iter_get_basic(&value, &random_mac_lifetime);
1494 if (random_mac_lifetime > 0)
1495 return set_random_mac_lifetime(technology, msg, random_mac_lifetime);
1497 return __connman_error_invalid_arguments(msg);
1499 } else if (g_str_equal(name, "CountryCode")) {
1502 dbus_message_iter_get_basic(&value, &str);
1503 DBG("country code %s", str);
1504 connman_technology_set_regdom(str);
1507 return __connman_error_invalid_property(msg);
1509 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1512 static void reply_scan_pending(struct connman_technology *technology, int err)
1516 DBG("technology %p err %d", technology, err);
1518 while (technology->scan_pending) {
1519 #if defined TIZEN_EXT
1520 struct connman_scan_pending *pending_data = technology->scan_pending->data;
1521 DBusMessage *msg = pending_data->msg;
1523 DBusMessage *msg = technology->scan_pending->data;
1525 DBG("reply to %s", dbus_message_get_sender(msg));
1528 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1530 reply = __connman_error_failed(msg, -err);
1531 g_dbus_send_message(connection, reply);
1532 dbus_message_unref(msg);
1534 technology->scan_pending =
1535 g_slist_delete_link(technology->scan_pending,
1536 technology->scan_pending);
1537 #if defined TIZEN_EXT
1538 g_free(pending_data->ifname);
1539 g_free(pending_data);
1544 #if defined TIZEN_EXT
1545 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1548 DBusMessage *signal;
1549 DBusMessageIter iter;
1550 dbus_bool_t result = FALSE;
1552 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1553 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1557 dbus_message_iter_init_append(signal, &iter);
1559 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1561 connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
1563 result = dbus_connection_send(connection, signal, NULL);
1564 dbus_message_unref(signal);
1566 DBG("Successfuly sent signal");
1571 void __connman_technology_notify_scan_done(const char *ifname, int val)
1574 DBusMessage *signal;
1575 DBusMessageIter iter;
1577 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1578 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1582 dbus_message_iter_init_append(signal, &iter);
1584 connman_dbus_property_append_basic(&iter, ifname,
1585 DBUS_TYPE_INT32, &val);
1587 connman_dbus_property_append_basic(&iter, "",
1588 DBUS_TYPE_INT32, &val);
1590 dbus_connection_send(connection, signal, NULL);
1591 dbus_message_unref(signal);
1593 DBG("Successfuly sent ScanDone signal");
1596 static void reply_scan_pending_device(
1597 struct connman_technology *technology, const char *ifname, int count)
1601 dbus_bool_t status = 0;
1602 connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
1604 DBG("technology %p ifname %s count %d", technology, ifname, count);
1606 list = technology->scan_pending;
1609 struct connman_scan_pending *pending_data = list->data;
1610 DBusMessage *msg = pending_data->msg;
1613 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1614 scan_type = pending_data->scan_type;
1616 if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
1619 scan_type = pending_data->scan_type;
1621 DBG("reply to %s", dbus_message_get_sender(msg));
1622 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1624 g_dbus_send_message(connection, reply);
1625 dbus_message_unref(msg);
1627 technology->scan_pending =
1628 g_slist_remove(technology->scan_pending, pending_data);
1630 g_free(pending_data->ifname);
1631 g_free(pending_data);
1634 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1635 scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1637 __connman_technology_notify_scan_changed(ifname, &status);
1638 __connman_technology_notify_scan_done(ifname, scan_type);
1641 static void __connman_technology_notify_device_detected(
1642 struct connman_technology *technology, const char *ifname, bool val)
1645 DBusMessage *signal;
1646 DBusMessageIter iter;
1647 dbus_bool_t detected = val;
1652 signal = dbus_message_new_signal(technology->path,
1653 CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
1657 dbus_message_iter_init_append(signal, &iter);
1658 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
1659 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
1661 dbus_connection_send(connection, signal, NULL);
1662 dbus_message_unref(signal);
1664 DBG("Successfuly sent DeviceDetected signal");
1668 void __connman_technology_scan_started(struct connman_device *device)
1670 DBG("device %p", device);
1671 #if defined TIZEN_EXT
1672 dbus_bool_t status = 1;
1673 const char *ifname = connman_device_get_string(device, "Interface");
1675 __connman_technology_notify_scan_changed(ifname, &status);
1679 void __connman_technology_scan_stopped(struct connman_device *device,
1680 enum connman_service_type type)
1683 struct connman_technology *technology;
1686 technology = technology_find(type);
1688 DBG("technology %p device %p", technology, device);
1693 for (list = technology->device_list; list; list = list->next) {
1694 struct connman_device *other_device = list->data;
1696 if (device == other_device)
1699 if (connman_device_get_scanning(other_device, type))
1703 #if defined TIZEN_EXT
1704 const char *ifname = connman_device_get_string(device, "Interface");
1705 reply_scan_pending_device(technology, ifname, count);
1710 reply_scan_pending(technology, 0);
1714 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1715 int result, const char *alpha2)
1717 bool regdom_set = false;
1718 struct connman_technology *technology;
1719 enum connman_service_type type;
1720 GSList *tech_drivers;
1722 type = __connman_device_get_service_type(device);
1723 technology = technology_find(type);
1730 for (tech_drivers = technology->driver_list;
1732 tech_drivers = g_slist_next(tech_drivers)) {
1733 struct connman_technology_driver *driver =
1736 if (driver->set_regdom) {
1737 driver->set_regdom(technology, alpha2);
1747 connman_technology_regdom_notify(technology, alpha2);
1750 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1752 struct connman_technology *technology = data;
1755 DBG("technology %p request from %s", technology,
1756 dbus_message_get_sender(msg));
1758 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1759 !technology->enabled)
1760 return __connman_error_permission_denied(msg);
1762 #if !defined TIZEN_EXT
1763 dbus_message_ref(msg);
1764 technology->scan_pending =
1765 g_slist_prepend(technology->scan_pending, msg);
1768 err = __connman_device_request_scan_full(technology->type);
1770 #if defined TIZEN_EXT
1771 return __connman_error_failed(msg, -err);
1773 reply_scan_pending(technology, err);
1776 #if defined TIZEN_EXT
1777 struct connman_scan_pending *pending_data =
1778 g_try_malloc0(sizeof(struct connman_scan_pending));
1780 return __connman_error_failed(msg, ENOMEM);
1782 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1783 DBG("scan_type %d", pending_data->scan_type);
1785 pending_data->msg = dbus_message_ref(msg);
1787 technology->scan_pending =
1788 g_slist_prepend(technology->scan_pending, pending_data);
1793 #if defined TIZEN_EXT
1794 static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
1796 struct connman_technology *technology = data;
1797 DBusMessageIter iter;
1801 DBG("technology %p request from %s", technology,
1802 dbus_message_get_sender(msg));
1804 if (!dbus_message_iter_init(msg, &iter))
1805 return __connman_error_invalid_arguments(msg);
1807 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1808 return __connman_error_invalid_arguments(msg);
1810 dbus_message_iter_get_basic(&iter, &ifname);
1811 DBG("Interface name %s", ifname);
1813 if (!ifname || strlen(ifname) == 0)
1814 return __connman_error_invalid_arguments(msg);
1816 err = connman_device_request_device_scan(technology->type, ifname, true);
1818 return __connman_error_failed(msg, -err);
1820 struct connman_scan_pending *pending_data =
1821 g_try_malloc0(sizeof(struct connman_scan_pending));
1823 return __connman_error_failed(msg, ENOMEM);
1825 pending_data->ifname = g_strdup(ifname);
1826 if (pending_data->ifname == NULL) {
1827 g_free(pending_data);
1828 return __connman_error_failed(msg, ENOMEM);
1831 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1832 DBG("scan_type %d", pending_data->scan_type);
1834 pending_data->msg = dbus_message_ref(msg);
1836 technology->scan_pending =
1837 g_slist_prepend(technology->scan_pending, pending_data);
1842 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1844 struct connman_technology *technology = data;
1845 GSList *specific_scan_list = NULL;
1847 const char *name = NULL;
1848 const char *freq = NULL;
1849 const char *ifname = NULL;
1850 DBusMessageIter iter, dict;
1853 DBG("technology %p request from %s", technology,
1854 dbus_message_get_sender(msg));
1856 if (!dbus_message_iter_init(msg, &iter))
1857 return __connman_error_invalid_arguments(msg);
1859 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1860 return __connman_error_invalid_arguments(msg);
1862 dbus_message_iter_recurse(&iter, &dict);
1863 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1864 DBusMessageIter entry, value2;
1868 dbus_message_iter_recurse(&dict, &entry);
1869 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1870 g_slist_free_full(specific_scan_list, g_free);
1871 return __connman_error_invalid_arguments(msg);
1874 dbus_message_iter_get_basic(&entry, &key);
1875 dbus_message_iter_next(&entry);
1877 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1878 g_slist_free_full(specific_scan_list, g_free);
1879 return __connman_error_invalid_arguments(msg);
1882 dbus_message_iter_recurse(&entry, &value2);
1883 type = dbus_message_iter_get_arg_type(&value2);
1884 if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
1886 dbus_message_iter_get_basic(&value2, &ifname);
1887 DBG("ifname %s", ifname);
1888 } else if (g_str_equal(key, "SSID")) {
1889 if (type != DBUS_TYPE_STRING) {
1890 g_slist_free_full(specific_scan_list, g_free);
1891 return __connman_error_invalid_arguments(msg);
1894 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1895 dbus_message_iter_get_basic(&value2, &name);
1896 DBG("name %s", name);
1897 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1898 } else if (g_str_equal(key, "Frequency")) {
1899 if (type != DBUS_TYPE_STRING) {
1900 g_slist_free_full(specific_scan_list, g_free);
1901 return __connman_error_invalid_arguments(msg);
1904 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1905 dbus_message_iter_get_basic(&value2, &freq);
1906 DBG("freq %s", freq);
1907 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1908 } else if (g_str_equal(key, "SSID_Mixed")) {
1909 if (type != DBUS_TYPE_STRING) {
1910 g_slist_free_full(specific_scan_list, g_free);
1911 return __connman_error_invalid_arguments(msg);
1914 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1915 dbus_message_iter_get_basic(&value2, &name);
1917 connman_multi_scan_ap_s *ap =
1918 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1920 g_strlcpy(ap->str, name, strlen(name) + 1);
1922 specific_scan_list = g_slist_append(specific_scan_list, ap);
1924 DBG("Failed to allocate memory");
1926 } else if (g_str_equal(key, "Frequency_Mixed")) {
1927 if (type != DBUS_TYPE_STRING) {
1928 g_slist_free_full(specific_scan_list, g_free);
1929 return __connman_error_invalid_arguments(msg);
1932 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1933 dbus_message_iter_get_basic(&value2, &freq);
1935 connman_multi_scan_ap_s *ap =
1936 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1938 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1940 specific_scan_list = g_slist_append(specific_scan_list, ap);
1942 DBG("Failed to allocate memory");
1944 dbus_message_iter_next(&dict);
1947 err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
1949 return __connman_error_failed(msg, -err);
1951 guint list_size = g_slist_length(specific_scan_list);
1953 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1954 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
1955 g_slist_free_full(specific_scan_list, g_free);
1957 struct connman_scan_pending *pending_data =
1958 g_try_malloc0(sizeof(struct connman_scan_pending));
1960 return __connman_error_failed(msg, ENOMEM);
1963 pending_data->ifname = g_strdup(ifname);
1964 if (pending_data->ifname == NULL) {
1965 g_free(pending_data);
1966 return __connman_error_failed(msg, ENOMEM);
1971 pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1973 pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1974 DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
1976 pending_data->msg = dbus_message_ref(msg);
1978 technology->scan_pending =
1979 g_slist_prepend(technology->scan_pending, pending_data);
1984 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
1987 DBusMessageIter iter, dict;
1989 struct connman_technology *technology = data;
1990 dbus_bool_t supported = false;
1991 const char *ifname = NULL;
1993 DBG("technology %p", technology);
1995 reply = dbus_message_new_method_return(msg);
1999 dbus_message_iter_init_append(reply, &iter);
2000 connman_dbus_dict_open(&iter, &dict);
2002 for (list = technology->device_list; list; list = list->next) {
2003 struct connman_device *device = list->data;
2005 supported = connman_device_get_wifi_5ghz_supported(device);
2006 ifname = connman_device_get_string(device, "Interface");
2008 DBG("ifname %s supported : %d", ifname, supported);
2009 connman_dbus_dict_append_basic(&dict, ifname,
2014 connman_dbus_dict_close(&iter, &dict);
2019 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
2022 DBusMessageIter iter, dict;
2024 struct connman_technology *technology = data;
2025 dbus_bool_t scanning = false;
2026 const char *ifname = NULL;
2028 DBG("technology %p", technology);
2030 reply = dbus_message_new_method_return(msg);
2034 dbus_message_iter_init_append(reply, &iter);
2035 connman_dbus_dict_open(&iter, &dict);
2037 for (list = technology->device_list; list; list = list->next) {
2038 struct connman_device *device = list->data;
2040 scanning = connman_device_get_scanning(device, technology->type);
2041 ifname = connman_device_get_string(device, "Interface");
2043 DBG("ifname %s scanning : %d", ifname, scanning);
2044 connman_dbus_dict_append_basic(&dict, ifname,
2049 connman_dbus_dict_close(&iter, &dict);
2054 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
2057 DBusMessageIter iter, dict;
2059 struct connman_technology *technology = data;
2060 dbus_int32_t max_scan_ssids = 0;
2061 const char *ifname = NULL;
2063 DBG("technology %p", technology);
2065 reply = dbus_message_new_method_return(msg);
2069 dbus_message_iter_init_append(reply, &iter);
2070 connman_dbus_dict_open(&iter, &dict);
2072 for (list = technology->device_list; list; list = list->next) {
2073 struct connman_device *device = list->data;
2075 max_scan_ssids = connman_device_get_max_scan_ssids(device);
2076 ifname = connman_device_get_string(device, "Interface");
2078 DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
2079 connman_dbus_dict_append_basic(&dict, ifname,
2084 connman_dbus_dict_close(&iter, &dict);
2089 static int technology_enable_device(struct connman_technology *technology,
2090 bool enable_device, const char *ifname, struct connman_device **device_out)
2095 for (list = technology->device_list; list; list = list->next) {
2096 struct connman_device *device = list->data;
2097 const char *str = connman_device_get_string(device, "Interface");
2099 if (g_strcmp0(str, ifname) != 0)
2103 err = __connman_device_enable(device);
2105 err = __connman_device_disable(device);
2107 *device_out = device;
2114 static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
2115 DBusMessage *msg, bool powered, const char *ifname)
2117 DBusMessage *reply = NULL;
2118 struct connman_device *device = NULL;
2121 err = technology_enable_device(technology, powered, ifname, &device);
2123 if (err == -EINPROGRESS) {
2125 connman_device_set_pending_reply(device, msg);
2127 } else if (err == -EALREADY) {
2129 reply = __connman_error_already_enabled(msg);
2131 reply = __connman_error_already_disabled(msg);
2133 reply = __connman_error_failed(msg, -err);
2135 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2140 static DBusMessage *set_device_power(DBusConnection *conn,
2141 DBusMessage *msg, void *data)
2143 struct connman_technology *technology = data;
2144 DBusMessageIter iter;
2149 DBG("conn %p", conn);
2151 if (!dbus_message_iter_init(msg, &iter))
2152 return __connman_error_invalid_arguments(msg);
2154 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2155 return __connman_error_invalid_arguments(msg);
2157 dbus_message_iter_get_basic(&iter, &name);
2158 dbus_message_iter_next(&iter);
2160 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
2161 return __connman_error_invalid_arguments(msg);
2163 DBG("interface name %s", name);
2167 if (len + 1 > IFNAMSIZ)
2168 return __connman_error_invalid_arguments(msg);
2170 dbus_message_iter_get_basic(&iter, &enable);
2171 DBG("powered %s", enable ? "TRUE" : "FALSE");
2173 return technology_set_device_powered(technology, msg, enable, name);
2176 static DBusMessage *set_bssid(DBusConnection *conn,
2177 DBusMessage *msg, void *data)
2179 DBusMessageIter iter;
2183 DBG("conn %p", conn);
2185 if (!dbus_message_iter_init(msg, &iter))
2186 return __connman_error_invalid_arguments(msg);
2188 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2189 return __connman_error_invalid_arguments(msg);
2191 dbus_message_iter_get_basic(&iter, &name);
2192 dbus_message_iter_next(&iter);
2194 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2195 return __connman_error_invalid_arguments(msg);
2197 dbus_message_iter_get_basic(&iter, &bssid);
2199 DBG("interface name %s bssid %s", name, bssid);
2203 if (len + 1 > IFNAMSIZ)
2204 return __connman_error_invalid_arguments(msg);
2206 set_connman_bssid(SET_BSSID, bssid, name);
2208 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2210 static struct connman_technology *technology_get(enum connman_service_type type);
2212 void technology_save_device(struct connman_device *device)
2214 struct connman_technology *technology;
2215 enum connman_service_type type;
2217 type = __connman_device_get_service_type(device);
2219 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2222 technology = technology_get(type);
2226 if (!g_slist_find(technology->device_list, device))
2231 const char *name = get_name(technology->type);
2233 DBG("technology %p type %d name %s", technology, technology->type,
2238 keyfile = __connman_storage_load_global();
2240 keyfile = g_key_file_new();
2242 identifier = g_strdup_printf("%s", name);
2246 GSList *list = NULL;
2247 gchar **ifname_list = NULL;
2248 guint dev_count = g_slist_length(technology->device_list);
2250 if (dev_count >= 1) {
2251 GString *ifname_str = g_string_new(NULL);
2254 for (list = technology->device_list; list; list = list->next) {
2255 struct connman_device *device = list->data;
2257 if (connman_device_get_powered(device)) {
2258 const char *ifname = connman_device_get_string(device, "Interface");
2260 if (ifname_str->len > 0)
2261 g_string_append_printf(ifname_str, " %s", ifname);
2263 g_string_append(ifname_str, ifname);
2267 if (ifname_str->len > 0) {
2268 ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
2269 dev_count = g_strv_length(ifname_list);
2270 g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
2271 (const gchar **) ifname_list, dev_count);
2273 technology->enable_persistent = true;
2275 g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
2276 technology->enable_persistent = false;
2279 g_strfreev(ifname_list);
2280 g_string_free(ifname_str, TRUE);
2284 g_key_file_set_boolean(keyfile, identifier, "Enable",
2285 technology->enable_persistent);
2287 g_key_file_set_boolean(keyfile, identifier, "Tethering",
2288 technology->tethering_persistent);
2290 if (technology->tethering_ident)
2291 g_key_file_set_string(keyfile, identifier,
2292 "Tethering.Identifier",
2293 technology->tethering_ident);
2295 if (technology->tethering_passphrase)
2296 g_key_file_set_string(keyfile, identifier,
2297 "Tethering.Passphrase",
2298 technology->tethering_passphrase);
2303 __connman_storage_save_global(keyfile);
2305 g_key_file_free(keyfile);
2309 #if defined TIZEN_EXT_WIFI_MESH
2310 bool __connman_technology_get_connected(enum connman_service_type type)
2312 struct connman_technology *technology;
2314 technology = technology_find(type);
2319 return technology->connected;
2322 void __connman_technology_mesh_interface_create_finished(
2323 enum connman_service_type type, bool success,
2327 struct connman_technology *technology;
2329 technology = technology_find(type);
2331 DBG("technology %p success %d", technology, success);
2336 msg = technology->mesh_dbus_msg;
2338 DBG("No pending dbus message");
2343 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2344 __connman_device_request_scan(technology->type);
2346 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
2347 ".MeshInterfaceAddFailed", "%s", error);
2348 g_dbus_send_message(connection, reply);
2349 dbus_message_unref(msg);
2350 technology->mesh_dbus_msg = NULL;
2353 void __connman_technology_mesh_interface_remove_finished(
2354 enum connman_service_type type, bool success)
2357 struct connman_technology *technology;
2359 technology = technology_find(type);
2361 DBG("technology %p success %d", technology, success);
2363 if (!technology || !technology->mesh_dbus_msg)
2366 msg = technology->mesh_dbus_msg;
2368 DBG("No pending dbus message");
2373 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2375 reply = __connman_error_failed(msg, EINVAL);
2376 g_dbus_send_message(connection, reply);
2377 dbus_message_unref(msg);
2378 technology->mesh_dbus_msg = NULL;
2381 void __connman_technology_notify_abort_scan(enum connman_service_type type,
2385 struct connman_technology *technology;
2387 technology = technology_find(type);
2389 DBG("technology %p result %d", technology, result);
2391 if (!technology || !technology->mesh_dbus_msg)
2394 msg = technology->mesh_dbus_msg;
2396 DBG("No pending dbus message");
2401 reply = __connman_error_scan_abort_failed(msg);
2403 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2405 g_dbus_send_message(connection, reply);
2406 dbus_message_unref(msg);
2407 technology->mesh_dbus_msg = NULL;
2410 static DBusMessage *mesh_commands(DBusConnection *conn,
2411 DBusMessage *msg, void *data)
2413 struct connman_technology *technology = data;
2414 DBusMessageIter iter, value, dict;
2415 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
2418 DBG("conn %p", conn);
2420 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
2421 return __connman_error_invalid_arguments(msg);
2423 if (!dbus_message_iter_init(msg, &iter))
2424 return __connman_error_invalid_arguments(msg);
2426 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2427 return __connman_error_invalid_arguments(msg);
2429 dbus_message_iter_get_basic(&iter, &cmd);
2430 dbus_message_iter_next(&iter);
2432 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
2433 return __connman_error_invalid_arguments(msg);
2435 dbus_message_iter_recurse(&iter, &value);
2437 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
2438 return __connman_error_invalid_arguments(msg);
2440 DBG("Mesh Command %s", cmd);
2441 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
2442 dbus_message_iter_recurse(&value, &dict);
2443 const char *bridge_ifname = NULL;
2444 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2445 DBusMessageIter entry, value2;
2449 dbus_message_iter_recurse(&dict, &entry);
2451 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2452 return __connman_error_invalid_arguments(msg);
2454 dbus_message_iter_get_basic(&entry, &key);
2455 dbus_message_iter_next(&entry);
2457 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2458 return __connman_error_invalid_arguments(msg);
2460 dbus_message_iter_recurse(&entry, &value2);
2462 type = dbus_message_iter_get_arg_type(&value2);
2464 if (g_str_equal(key, "Ifname")) {
2465 if (type != DBUS_TYPE_STRING)
2466 return __connman_error_invalid_arguments(msg);
2468 dbus_message_iter_get_basic(&value2, &ifname);
2469 } else if (g_str_equal(key, "ParentIfname")) {
2470 if (type != DBUS_TYPE_STRING)
2471 return __connman_error_invalid_arguments(msg);
2473 dbus_message_iter_get_basic(&value2, &parent_ifname);
2474 } else if (g_str_equal(key, "BridgeIfname")) {
2475 if (type != DBUS_TYPE_STRING)
2476 return __connman_error_invalid_arguments(msg);
2478 dbus_message_iter_get_basic(&value2, &bridge_ifname);
2480 dbus_message_iter_next(&dict);
2482 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
2483 bridge_ifname ? bridge_ifname : "NULL");
2484 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
2488 DBG("Failed to add virtual mesh interface");
2489 return __connman_error_failed(msg, -err);
2492 DBG("Successfully added virtual mesh interface");
2494 dbus_message_ref(msg);
2495 technology->mesh_dbus_msg = msg;
2497 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
2498 dbus_message_iter_recurse(&value, &dict);
2499 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2500 DBusMessageIter entry, value2;
2504 dbus_message_iter_recurse(&dict, &entry);
2506 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2507 return __connman_error_invalid_arguments(msg);
2509 dbus_message_iter_get_basic(&entry, &key);
2510 dbus_message_iter_next(&entry);
2512 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2513 return __connman_error_invalid_arguments(msg);
2515 dbus_message_iter_recurse(&entry, &value2);
2517 type = dbus_message_iter_get_arg_type(&value2);
2519 if (g_str_equal(key, "Ifname")) {
2520 if (type != DBUS_TYPE_STRING)
2521 return __connman_error_invalid_arguments(msg);
2523 dbus_message_iter_get_basic(&value2, &ifname);
2525 dbus_message_iter_next(&dict);
2527 DBG("Mesh Ifname %s", ifname);
2528 err = __connman_mesh_remove_virtual_interface(ifname);
2531 DBG("Failed to remove virtual mesh interface");
2532 return __connman_error_failed(msg, -err);
2535 DBG("Successfully removed virtual mesh interface");
2537 dbus_message_ref(msg);
2538 technology->mesh_dbus_msg = msg;
2540 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
2541 struct connman_mesh *connman_mesh;
2542 const char *name = NULL;
2543 const char *sec_type = NULL;
2544 const char *mesh_ifname = NULL;
2545 char *identifier, *group, *address;
2546 unsigned int freq = 0;
2547 unsigned int ieee80211w = 0;
2550 dbus_message_iter_recurse(&value, &dict);
2551 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2552 DBusMessageIter entry, value2;
2556 dbus_message_iter_recurse(&dict, &entry);
2558 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2559 return __connman_error_invalid_arguments(msg);
2561 dbus_message_iter_get_basic(&entry, &key);
2562 dbus_message_iter_next(&entry);
2564 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2565 return __connman_error_invalid_arguments(msg);
2567 dbus_message_iter_recurse(&entry, &value2);
2569 type = dbus_message_iter_get_arg_type(&value2);
2571 if (g_str_equal(key, "Name")) {
2572 if (type != DBUS_TYPE_STRING)
2573 return __connman_error_invalid_arguments(msg);
2575 dbus_message_iter_get_basic(&value2, &name);
2576 } else if (g_str_equal(key, "Frequency")) {
2577 if (type != DBUS_TYPE_UINT16)
2578 return __connman_error_invalid_arguments(msg);
2580 dbus_message_iter_get_basic(&value2, &freq);
2581 } else if (g_str_equal(key, "Security")) {
2582 if (type != DBUS_TYPE_STRING)
2583 return __connman_error_invalid_arguments(msg);
2585 dbus_message_iter_get_basic(&value2, &sec_type);
2586 } else if (g_str_equal(key, "Pmf")) {
2587 if (type != DBUS_TYPE_UINT16)
2588 return __connman_error_invalid_arguments(msg);
2590 dbus_message_iter_get_basic(&value2, &ieee80211w);
2592 dbus_message_iter_next(&dict);
2595 if (name == NULL || sec_type == NULL || freq == 0)
2596 return __connman_error_invalid_arguments(msg);
2598 DBG("Name %s Frequency %d Security type %s Pmf %u",
2599 name, freq, sec_type, ieee80211w);
2601 if (g_strcmp0(sec_type, "none") != 0 &&
2602 g_strcmp0(sec_type, "sae") != 0) {
2603 DBG("Unsupported security");
2604 return __connman_error_invalid_arguments(msg);
2607 mesh_ifname = connman_mesh_get_interface_name();
2609 if (!connman_mesh_is_interface_created()) {
2610 DBG("Mesh interface doesn't exists");
2611 return __connman_error_invalid_command(msg);
2614 str = g_string_sized_new((strlen(name) * 2) + 24);
2616 for (i = 0; name[i]; i++)
2617 g_string_append_printf(str, "%02x", name[i]);
2619 g_string_append_printf(str, "_mesh");
2621 if (g_strcmp0(sec_type, "none") == 0)
2622 g_string_append_printf(str, "_none");
2623 else if (g_strcmp0(sec_type, "sae") == 0)
2624 g_string_append_printf(str, "_sae");
2626 group = g_string_free(str, FALSE);
2628 identifier = connman_inet_ifaddr(mesh_ifname);
2629 address = connman_inet_ifname2addr(mesh_ifname);
2631 connman_mesh = connman_mesh_create(identifier, group);
2632 connman_mesh_set_name(connman_mesh, name);
2633 connman_mesh_set_address(connman_mesh, address);
2634 connman_mesh_set_security(connman_mesh, sec_type);
2635 connman_mesh_set_frequency(connman_mesh, freq);
2636 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
2637 connman_mesh_set_peer_type(connman_mesh,
2638 CONNMAN_MESH_PEER_TYPE_CREATED);
2639 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
2641 connman_mesh_register(connman_mesh);
2645 DBG("Successfully Created Mesh Network");
2646 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2648 } else if (g_str_equal(cmd, "AbortScan")) {
2649 DBG("Abort Scan method");
2650 err = __connman_device_abort_scan(technology->type);
2652 DBG("Failed to abort scan");
2653 return __connman_error_failed(msg, -err);
2656 DBG("Successfully requested to abort scan");
2657 dbus_message_ref(msg);
2658 technology->mesh_dbus_msg = msg;
2660 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
2661 const char *name = NULL;
2662 unsigned int freq = 0;
2663 dbus_message_iter_recurse(&value, &dict);
2664 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2665 DBusMessageIter entry, value2;
2669 dbus_message_iter_recurse(&dict, &entry);
2671 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2672 return __connman_error_invalid_arguments(msg);
2674 dbus_message_iter_get_basic(&entry, &key);
2675 dbus_message_iter_next(&entry);
2677 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2678 return __connman_error_invalid_arguments(msg);
2680 dbus_message_iter_recurse(&entry, &value2);
2682 type = dbus_message_iter_get_arg_type(&value2);
2684 if (g_str_equal(key, "Name")) {
2685 if (type != DBUS_TYPE_STRING)
2686 return __connman_error_invalid_arguments(msg);
2688 dbus_message_iter_get_basic(&value2, &name);
2689 } else if (g_str_equal(key, "Frequency")) {
2690 if (type != DBUS_TYPE_UINT16)
2691 return __connman_error_invalid_arguments(msg);
2693 dbus_message_iter_get_basic(&value2, &freq);
2695 dbus_message_iter_next(&dict);
2698 DBG("MeshID %s Frequency %d sender %s", name, freq,
2699 dbus_message_get_sender(msg));
2701 struct connman_scan_pending *pending_data =
2702 g_try_malloc0(sizeof(struct connman_scan_pending));
2704 return __connman_error_failed(msg, ENOMEM);
2706 pending_data->msg = dbus_message_ref(msg);
2708 technology->scan_pending =
2709 g_slist_prepend(technology->scan_pending, pending_data);
2711 err = __connman_device_request_mesh_specific_scan(technology->type,
2714 reply_scan_pending(technology, err);
2716 DBG("Successfully requested to scan specific Mesh Network");
2718 } else if (g_str_equal(cmd, "SetMeshGate")) {
2719 unsigned int hwmp_rootmode = 0;
2720 bool gate_announce = false;
2721 unsigned int stp = 0;
2723 dbus_message_iter_recurse(&value, &dict);
2724 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2725 DBusMessageIter entry, value2;
2729 dbus_message_iter_recurse(&dict, &entry);
2731 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2732 return __connman_error_invalid_arguments(msg);
2734 dbus_message_iter_get_basic(&entry, &key);
2735 dbus_message_iter_next(&entry);
2737 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2738 return __connman_error_invalid_arguments(msg);
2740 dbus_message_iter_recurse(&entry, &value2);
2742 type = dbus_message_iter_get_arg_type(&value2);
2744 if (g_str_equal(key, "GateAnnounce")) {
2745 if (type != DBUS_TYPE_BOOLEAN)
2746 return __connman_error_invalid_arguments(msg);
2748 dbus_message_iter_get_basic(&value2, &gate_announce);
2749 } else if (g_str_equal(key, "HWMPRootMode")) {
2750 if (type != DBUS_TYPE_UINT16)
2751 return __connman_error_invalid_arguments(msg);
2753 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
2754 } else if (g_str_equal(key, "STP")) {
2755 if (type != DBUS_TYPE_UINT16)
2756 return __connman_error_invalid_arguments(msg);
2758 dbus_message_iter_get_basic(&value2, &stp);
2760 dbus_message_iter_next(&dict);
2763 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
2764 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
2766 err = __connman_mesh_set_stp_gate_announce(gate_announce,
2771 return __connman_error_failed(msg, -err);
2773 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2775 return __connman_error_invalid_command(msg);
2780 static const GDBusMethodTable technology_methods[] = {
2781 { GDBUS_DEPRECATED_METHOD("GetProperties",
2782 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
2784 { GDBUS_ASYNC_METHOD("SetProperty",
2785 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2786 NULL, set_property) },
2787 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
2788 #if defined TIZEN_EXT
2789 { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
2790 NULL, scan_device) },
2791 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
2792 NULL, specific_scan) },
2793 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
2795 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2796 get_5ghz_supported) },
2797 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2798 get_max_scan_ssid) },
2799 { GDBUS_ASYNC_METHOD("SetDevicePower",
2800 GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
2801 NULL, set_device_power) },
2802 { GDBUS_ASYNC_METHOD("SetBSSID",
2803 GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
2806 #if defined TIZEN_EXT_WIFI_MESH
2807 { GDBUS_ASYNC_METHOD("MeshCommands",
2808 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2809 NULL, mesh_commands) },
2814 static const GDBusSignalTable technology_signals[] = {
2815 { GDBUS_SIGNAL("PropertyChanged",
2816 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2817 #if defined TIZEN_EXT
2818 { GDBUS_SIGNAL("DeviceChanged",
2819 GDBUS_ARGS({ "device_property", "a{sv}" })) },
2820 { GDBUS_SIGNAL("DeviceDetected",
2821 GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
2826 static bool technology_dbus_register(struct connman_technology *technology)
2828 if (technology->dbus_registered ||
2829 (technology->rfkill_driven &&
2830 technology->hardblocked))
2833 if (!g_dbus_register_interface(connection, technology->path,
2834 CONNMAN_TECHNOLOGY_INTERFACE,
2835 technology_methods, technology_signals,
2836 NULL, technology, NULL)) {
2837 connman_error("Failed to register %s", technology->path);
2841 technology_added_signal(technology);
2842 technology->dbus_registered = true;
2847 static void technology_dbus_unregister(struct connman_technology *technology)
2849 if (!technology->dbus_registered)
2852 technology_removed_signal(technology);
2853 g_dbus_unregister_interface(connection, technology->path,
2854 CONNMAN_TECHNOLOGY_INTERFACE);
2856 technology->dbus_registered = false;
2859 static void technology_put(struct connman_technology *technology)
2861 DBG("technology %p", technology);
2863 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2866 reply_scan_pending(technology, -EINTR);
2868 while (technology->driver_list) {
2869 struct connman_technology_driver *driver;
2871 driver = technology->driver_list->data;
2874 driver->remove(technology);
2876 technology->driver_list =
2877 g_slist_delete_link(technology->driver_list,
2878 technology->driver_list);
2881 technology_list = g_slist_remove(technology_list, technology);
2883 technology_dbus_unregister(technology);
2885 g_slist_free(technology->device_list);
2887 if (technology->pending_reply) {
2888 dbus_message_unref(technology->pending_reply);
2889 technology->pending_reply = NULL;
2890 g_source_remove(technology->pending_timeout);
2891 technology->pending_timeout = 0;
2894 g_strfreev(technology->enabled_devices);
2896 g_free(technology->path);
2897 g_free(technology->regdom);
2898 g_free(technology->tethering_ident);
2899 g_free(technology->tethering_passphrase);
2903 static struct connman_technology *technology_get(enum connman_service_type type)
2905 GSList *tech_drivers = NULL;
2906 struct connman_technology_driver *driver;
2907 struct connman_technology *technology;
2911 DBG("type %d", type);
2913 str = __connman_service_type2string(type);
2917 technology = technology_find(type);
2919 #if defined TIZEN_EXT_WIFI_MESH
2920 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2921 type != CONNMAN_SERVICE_TYPE_MESH)
2923 if (type != CONNMAN_SERVICE_TYPE_P2P)
2925 __sync_fetch_and_add(&technology->refcount, 1);
2929 /* First check if we have a driver for this technology type */
2930 for (list = driver_list; list; list = list->next) {
2931 driver = list->data;
2933 if (driver->type == type) {
2934 DBG("technology %p driver %p", technology, driver);
2935 tech_drivers = g_slist_append(tech_drivers, driver);
2939 if (!tech_drivers) {
2940 DBG("No matching drivers found for %s.",
2941 __connman_service_type2string(type));
2945 technology = g_try_new0(struct connman_technology, 1);
2949 technology->refcount = 1;
2950 technology->type = type;
2951 technology->path = g_strdup_printf("%s/technology/%s",
2954 #if defined TIZEN_EXT_WIFI_MESH
2955 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2956 struct connman_technology *wifi;
2958 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2960 technology->enabled = wifi->enabled;
2964 technology_load(technology);
2965 technology_list = g_slist_prepend(technology_list, technology);
2966 technology->driver_list = tech_drivers;
2968 for (list = tech_drivers; list; list = list->next) {
2969 driver = list->data;
2971 if (driver->probe && driver->probe(technology) < 0)
2972 DBG("Driver probe failed for technology %p",
2976 if (!technology_dbus_register(technology)) {
2977 technology_put(technology);
2981 if (type == CONNMAN_SERVICE_TYPE_P2P) {
2982 struct connman_technology *wifi;
2985 enable = technology->enable_persistent;
2987 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2989 enable = wifi->enabled;
2991 technology_affect_devices(technology, enable);
2994 DBG("technology %p %s", technology, get_name(technology->type));
2999 int connman_technology_driver_register(struct connman_technology_driver *driver)
3002 struct connman_device *device;
3003 enum connman_service_type type;
3005 for (list = driver_list; list; list = list->next) {
3006 if (list->data == driver)
3010 DBG("Registering %s driver", driver->name);
3012 driver_list = g_slist_insert_sorted(driver_list, driver,
3016 * Check for technology less devices if this driver
3017 * can service any of them.
3019 for (list = techless_device_list; list; list = list->next) {
3020 device = list->data;
3022 type = __connman_device_get_service_type(device);
3023 if (type != driver->type)
3026 techless_device_list = g_slist_remove(techless_device_list,
3029 __connman_technology_add_device(device);
3032 /* Check for orphaned rfkill switches. */
3033 g_hash_table_foreach(rfkill_list, rfkill_check,
3034 GINT_TO_POINTER(driver->type));
3037 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3038 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
3042 #if defined TIZEN_EXT_WIFI_MESH
3043 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3044 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
3052 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
3054 GSList *list, *tech_drivers;
3055 struct connman_technology *technology;
3056 struct connman_technology_driver *current;
3058 DBG("Unregistering driver %p name %s", driver, driver->name);
3060 for (list = technology_list; list; list = list->next) {
3061 technology = list->data;
3063 for (tech_drivers = technology->driver_list; tech_drivers;
3064 tech_drivers = g_slist_next(tech_drivers)) {
3065 current = tech_drivers->data;
3066 if (driver != current)
3070 driver->remove(technology);
3072 technology->driver_list =
3073 g_slist_remove(technology->driver_list,
3079 driver_list = g_slist_remove(driver_list, driver);
3081 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3082 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
3084 technology_put(technology);
3086 #if defined TIZEN_EXT_WIFI_MESH
3087 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3088 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
3090 technology_put(technology);
3095 void __connman_technology_add_interface(enum connman_service_type type,
3096 int index, const char *ident)
3098 struct connman_technology *technology;
3099 GSList *tech_drivers;
3100 struct connman_technology_driver *driver;
3104 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3105 case CONNMAN_SERVICE_TYPE_SYSTEM:
3107 case CONNMAN_SERVICE_TYPE_ETHERNET:
3108 case CONNMAN_SERVICE_TYPE_WIFI:
3109 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3110 case CONNMAN_SERVICE_TYPE_CELLULAR:
3111 case CONNMAN_SERVICE_TYPE_GPS:
3112 case CONNMAN_SERVICE_TYPE_VPN:
3113 case CONNMAN_SERVICE_TYPE_GADGET:
3114 case CONNMAN_SERVICE_TYPE_P2P:
3115 #if defined TIZEN_EXT_WIFI_MESH
3116 case CONNMAN_SERVICE_TYPE_MESH:
3121 name = connman_inet_ifname(index);
3122 connman_info("Adding interface %s [ %s ]", name,
3123 __connman_service_type2string(type));
3125 technology = technology_find(type);
3130 for (tech_drivers = technology->driver_list; tech_drivers;
3131 tech_drivers = g_slist_next(tech_drivers)) {
3132 driver = tech_drivers->data;
3134 if (driver->add_interface)
3135 driver->add_interface(technology, index, name, ident);
3139 * At this point we can try to enable tethering automatically as
3140 * now the interfaces are set properly.
3142 if (technology->tethering_persistent)
3143 enable_tethering(technology);
3149 void __connman_technology_remove_interface(enum connman_service_type type,
3150 int index, const char *ident)
3152 struct connman_technology *technology;
3153 GSList *tech_drivers;
3154 struct connman_technology_driver *driver;
3158 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3159 case CONNMAN_SERVICE_TYPE_SYSTEM:
3161 case CONNMAN_SERVICE_TYPE_ETHERNET:
3162 case CONNMAN_SERVICE_TYPE_WIFI:
3163 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3164 case CONNMAN_SERVICE_TYPE_CELLULAR:
3165 case CONNMAN_SERVICE_TYPE_GPS:
3166 case CONNMAN_SERVICE_TYPE_VPN:
3167 case CONNMAN_SERVICE_TYPE_GADGET:
3168 case CONNMAN_SERVICE_TYPE_P2P:
3169 #if defined TIZEN_EXT_WIFI_MESH
3170 case CONNMAN_SERVICE_TYPE_MESH:
3175 name = connman_inet_ifname(index);
3176 connman_info("Remove interface %s [ %s ]", name,
3177 __connman_service_type2string(type));
3180 technology = technology_find(type);
3185 for (tech_drivers = technology->driver_list; tech_drivers;
3186 tech_drivers = g_slist_next(tech_drivers)) {
3187 driver = tech_drivers->data;
3189 if (driver->remove_interface)
3190 driver->remove_interface(technology, index);
3194 int __connman_technology_add_device(struct connman_device *device)
3196 struct connman_technology *technology;
3197 enum connman_service_type type;
3199 type = __connman_device_get_service_type(device);
3201 DBG("device %p type %s", device, get_name(type));
3203 technology = technology_get(type);
3206 * Since no driver can be found for this device at the moment we
3207 * add it to the techless device list.
3209 techless_device_list = g_slist_prepend(techless_device_list,
3215 __sync_synchronize();
3216 if (technology->rfkill_driven) {
3217 if (technology->enabled)
3218 __connman_device_enable(device);
3220 __connman_device_disable(device);
3225 if (technology->enable_persistent &&
3226 !global_offlinemode) {
3227 #if defined TIZEN_EXT
3230 if (technology->enabled_devices && type == CONNMAN_SERVICE_TYPE_WIFI) {
3233 const char *ifname = connman_device_get_string(device, "Interface");
3235 while (technology->enabled_devices[i]) {
3236 if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
3245 err = __connman_device_enable(device);
3247 int err = __connman_device_enable(device);
3250 * connman_technology_add_device() calls __connman_device_enable()
3251 * but since the device is already enabled, the call does not
3252 * propagate through to connman_technology_enabled via
3253 * connman_device_set_powered.
3255 if (err == -EALREADY)
3256 __connman_technology_enabled(type);
3258 /* if technology persistent state is offline */
3259 if (!technology->enable_persistent)
3260 __connman_device_disable(device);
3263 technology->device_list = g_slist_prepend(technology->device_list,
3266 #if defined TIZEN_EXT
3267 technology_save_device(device);
3269 const char *ifname = connman_device_get_string(device, "Interface");
3270 __connman_technology_notify_device_detected(technology, ifname, true);
3272 connman_device_set_mac_policy(device, technology->mac_policy);
3273 connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy);
3274 connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime);
3279 int __connman_technology_remove_device(struct connman_device *device)
3281 struct connman_technology *technology;
3282 enum connman_service_type type;
3284 DBG("device %p", device);
3286 type = __connman_device_get_service_type(device);
3288 technology = technology_find(type);
3290 techless_device_list = g_slist_remove(techless_device_list,
3295 technology->device_list = g_slist_remove(technology->device_list,
3298 #if defined TIZEN_EXT
3299 technology_save_device(device);
3301 const char *ifname = connman_device_get_string(device, "Interface");
3302 __connman_technology_notify_device_detected(technology, ifname, false);
3305 if (technology->tethering)
3306 set_tethering(technology, false);
3308 technology_put(technology);
3313 int __connman_technology_enabled(enum connman_service_type type)
3315 struct connman_technology *technology;
3317 technology = technology_find(type);
3321 DBG("technology %p type %s rfkill %d enabled %d", technology,
3322 get_name(type), technology->rfkill_driven,
3323 technology->enabled);
3325 #if !defined TIZEN_EXT
3326 if (technology->rfkill_driven) {
3327 if (technology->tethering_persistent)
3328 enable_tethering(technology);
3333 return technology_enabled(technology);
3336 int __connman_technology_disabled(enum connman_service_type type)
3338 struct connman_technology *technology;
3341 technology = technology_find(type);
3345 #if !defined TIZEN_EXT
3346 if (technology->rfkill_driven)
3350 for (list = technology->device_list; list; list = list->next) {
3351 struct connman_device *device = list->data;
3353 if (connman_device_get_powered(device))
3357 return technology_disabled(technology);
3360 int __connman_technology_set_offlinemode(bool offlinemode)
3363 int err = -EINVAL, enabled_tech_count = 0;
3365 if (global_offlinemode == offlinemode)
3368 DBG("offlinemode %s", offlinemode ? "On" : "Off");
3371 * This is a bit tricky. When you set offlinemode, there is no
3372 * way to differentiate between attempting offline mode and
3373 * resuming offlinemode from last saved profile. We need that
3374 * information in rfkill_update, otherwise it falls back on the
3375 * technology's persistent state. Hence we set the offline mode here
3376 * but save it & call the notifier only if it is successful.
3379 global_offlinemode = offlinemode;
3381 /* Traverse technology list, enable/disable each technology. */
3382 for (list = technology_list; list; list = list->next) {
3383 struct connman_technology *technology = list->data;
3386 err = technology_disable(technology);
3388 if (technology->hardblocked)
3391 if (technology->enable_persistent) {
3392 err = technology_enable(technology);
3393 enabled_tech_count++;
3398 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
3399 (err == -EINVAL && enabled_tech_count == 0)) {
3400 connman_technology_save_offlinemode();
3401 __connman_notifier_offlinemode(offlinemode);
3403 global_offlinemode = connman_technology_load_offlinemode();
3408 #if defined TIZEN_EXT_WIFI_MESH
3409 static gboolean __add_ethernet_to_bridge(gpointer data)
3412 __connman_mesh_add_ethernet_to_bridge();
3417 void __connman_technology_set_connected(enum connman_service_type type,
3420 struct connman_technology *technology;
3423 technology = technology_find(type);
3427 DBG("technology %p connected %d", technology, connected);
3429 technology->connected = connected;
3431 #if defined TIZEN_EXT_WIFI_MESH
3432 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
3433 g_idle_add(__add_ethernet_to_bridge, NULL);
3437 connman_dbus_property_changed_basic(technology->path,
3438 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
3439 DBUS_TYPE_BOOLEAN, &val);
3442 static bool technology_apply_rfkill_change(struct connman_technology *technology,
3447 bool hardblock_changed = false;
3449 GList *start, *list;
3451 DBG("technology %p --> %d/%d vs %d/%d",
3452 technology, softblock, hardblock,
3453 technology->softblocked, technology->hardblocked);
3455 if (technology->hardblocked == hardblock)
3456 goto softblock_change;
3458 if (!(new_rfkill && !hardblock)) {
3459 start = g_hash_table_get_values(rfkill_list);
3461 for (list = start; list; list = list->next) {
3462 struct connman_rfkill *rfkill = list->data;
3464 if (rfkill->type != technology->type)
3467 if (rfkill->hardblock != hardblock)
3475 goto softblock_change;
3477 technology->hardblocked = hardblock;
3478 hardblock_changed = true;
3481 if (!apply && technology->softblocked != softblock)
3485 return technology->hardblocked;
3487 technology->softblocked = softblock;
3489 if (technology->hardblocked ||
3490 technology->softblocked) {
3491 if (technology_disabled(technology) != -EALREADY)
3492 technology_affect_devices(technology, false);
3493 } else if (!technology->hardblocked &&
3494 !technology->softblocked) {
3495 if (technology_enabled(technology) != -EALREADY)
3496 technology_affect_devices(technology, true);
3499 if (hardblock_changed) {
3500 if (technology->hardblocked) {
3501 DBG("%s is switched off.", get_name(technology->type));
3502 technology_dbus_unregister(technology);
3504 DBG("%s is switched on.", get_name(technology->type));
3505 technology_dbus_register(technology);
3507 if (global_offlinemode)
3508 __connman_rfkill_block(technology->type, true);
3512 return technology->hardblocked;
3515 int __connman_technology_add_rfkill(unsigned int index,
3516 enum connman_service_type type,
3520 struct connman_technology *technology;
3521 struct connman_rfkill *rfkill;
3523 DBG("index %u type %d soft %u hard %u", index, type,
3524 softblock, hardblock);
3526 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3530 rfkill = g_try_new0(struct connman_rfkill, 1);
3534 rfkill->index = index;
3535 rfkill->type = type;
3536 rfkill->softblock = softblock;
3537 rfkill->hardblock = hardblock;
3539 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
3542 #if defined TIZEN_EXT
3543 /* Fix Svace Issue [WGID: 1348]. */
3546 technology = technology_get(type);
3547 /* If there is no driver for this type, ignore it. */
3551 technology->rfkill_driven = true;
3553 #if !defined TIZEN_EXT
3554 /* If hardblocked, there is no need to handle softblocked state */
3555 if (technology_apply_rfkill_change(technology,
3556 softblock, hardblock, true))
3560 if (global_offlinemode)
3564 * Depending on softblocked state we unblock/block according to
3565 * offlinemode and persistente state.
3567 if (technology->softblocked &&
3568 technology->enable_persistent)
3569 return __connman_rfkill_block(type, false);
3570 else if (!technology->softblocked &&
3571 !technology->enable_persistent)
3572 return __connman_rfkill_block(type, true);
3577 int __connman_technology_update_rfkill(unsigned int index,
3578 enum connman_service_type type,
3582 struct connman_technology *technology;
3583 struct connman_rfkill *rfkill;
3585 DBG("index %u soft %u hard %u", index, softblock, hardblock);
3587 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3591 if (rfkill->softblock == softblock &&
3592 rfkill->hardblock == hardblock)
3595 rfkill->softblock = softblock;
3596 rfkill->hardblock = hardblock;
3598 technology = technology_find(type);
3599 /* If there is no driver for this type, ignore it. */
3603 technology_apply_rfkill_change(technology, softblock, hardblock,
3606 if (technology->hardblocked)
3607 DBG("%s hardblocked", get_name(technology->type));
3609 DBG("%s is%s softblocked", get_name(technology->type),
3610 technology->softblocked ? "" : " not");
3615 int __connman_technology_remove_rfkill(unsigned int index,
3616 enum connman_service_type type)
3618 struct connman_technology *technology;
3619 struct connman_rfkill *rfkill;
3621 DBG("index %u", index);
3623 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3627 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
3629 technology = technology_find(type);
3633 technology_apply_rfkill_change(technology,
3634 technology->softblocked, !technology->hardblocked, false);
3636 technology_put(technology);
3641 int __connman_technology_init(void)
3645 connection = connman_dbus_get_connection();
3647 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3650 global_offlinemode = connman_technology_load_offlinemode();
3652 /* This will create settings file if it is missing */
3653 connman_technology_save_offlinemode();
3658 void __connman_technology_cleanup(void)
3662 while (technology_list) {
3663 struct connman_technology *technology = technology_list->data;
3664 technology_list = g_slist_remove(technology_list, technology);
3665 technology_put(technology);
3668 g_hash_table_destroy(rfkill_list);
3670 dbus_connection_unref(connection);