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);
1494 } else if (g_str_equal(name, "CountryCode")) {
1497 dbus_message_iter_get_basic(&value, &str);
1498 DBG("country code %s", str);
1499 connman_technology_set_regdom(str);
1502 return __connman_error_invalid_property(msg);
1504 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1507 static void reply_scan_pending(struct connman_technology *technology, int err)
1511 DBG("technology %p err %d", technology, err);
1513 while (technology->scan_pending) {
1514 #if defined TIZEN_EXT
1515 struct connman_scan_pending *pending_data = technology->scan_pending->data;
1516 DBusMessage *msg = pending_data->msg;
1518 DBusMessage *msg = technology->scan_pending->data;
1520 DBG("reply to %s", dbus_message_get_sender(msg));
1523 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1525 reply = __connman_error_failed(msg, -err);
1526 g_dbus_send_message(connection, reply);
1527 dbus_message_unref(msg);
1529 technology->scan_pending =
1530 g_slist_delete_link(technology->scan_pending,
1531 technology->scan_pending);
1532 #if defined TIZEN_EXT
1533 g_free(pending_data->ifname);
1534 g_free(pending_data);
1539 #if defined TIZEN_EXT
1540 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1543 DBusMessage *signal;
1544 DBusMessageIter iter;
1545 dbus_bool_t result = FALSE;
1547 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1548 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1552 dbus_message_iter_init_append(signal, &iter);
1554 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1556 connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
1558 result = dbus_connection_send(connection, signal, NULL);
1559 dbus_message_unref(signal);
1561 DBG("Successfuly sent signal");
1566 void __connman_technology_notify_scan_done(const char *ifname, int val)
1569 DBusMessage *signal;
1570 DBusMessageIter iter;
1572 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1573 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1577 dbus_message_iter_init_append(signal, &iter);
1579 connman_dbus_property_append_basic(&iter, ifname,
1580 DBUS_TYPE_INT32, &val);
1582 connman_dbus_property_append_basic(&iter, "",
1583 DBUS_TYPE_INT32, &val);
1585 dbus_connection_send(connection, signal, NULL);
1586 dbus_message_unref(signal);
1588 DBG("Successfuly sent ScanDone signal");
1591 static void reply_scan_pending_device(
1592 struct connman_technology *technology, const char *ifname, int count)
1596 dbus_bool_t status = 0;
1597 connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
1599 DBG("technology %p ifname %s count %d", technology, ifname, count);
1601 list = technology->scan_pending;
1604 struct connman_scan_pending *pending_data = list->data;
1605 DBusMessage *msg = pending_data->msg;
1608 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1609 scan_type = pending_data->scan_type;
1611 if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
1614 scan_type = pending_data->scan_type;
1616 DBG("reply to %s", dbus_message_get_sender(msg));
1617 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1619 g_dbus_send_message(connection, reply);
1620 dbus_message_unref(msg);
1622 technology->scan_pending =
1623 g_slist_remove(technology->scan_pending, pending_data);
1625 g_free(pending_data->ifname);
1626 g_free(pending_data);
1629 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1630 scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1632 __connman_technology_notify_scan_changed(ifname, &status);
1633 __connman_technology_notify_scan_done(ifname, scan_type);
1636 static void __connman_technology_notify_device_detected(
1637 struct connman_technology *technology, const char *ifname, bool val)
1640 DBusMessage *signal;
1641 DBusMessageIter iter;
1642 dbus_bool_t detected = val;
1647 signal = dbus_message_new_signal(technology->path,
1648 CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
1652 dbus_message_iter_init_append(signal, &iter);
1653 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
1654 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
1656 dbus_connection_send(connection, signal, NULL);
1657 dbus_message_unref(signal);
1659 DBG("Successfuly sent DeviceDetected signal");
1663 void __connman_technology_scan_started(struct connman_device *device)
1665 DBG("device %p", device);
1666 #if defined TIZEN_EXT
1667 dbus_bool_t status = 1;
1668 const char *ifname = connman_device_get_string(device, "Interface");
1670 __connman_technology_notify_scan_changed(ifname, &status);
1674 void __connman_technology_scan_stopped(struct connman_device *device,
1675 enum connman_service_type type)
1678 struct connman_technology *technology;
1681 technology = technology_find(type);
1683 DBG("technology %p device %p", technology, device);
1688 for (list = technology->device_list; list; list = list->next) {
1689 struct connman_device *other_device = list->data;
1691 if (device == other_device)
1694 if (connman_device_get_scanning(other_device, type))
1698 #if defined TIZEN_EXT
1699 const char *ifname = connman_device_get_string(device, "Interface");
1700 reply_scan_pending_device(technology, ifname, count);
1705 reply_scan_pending(technology, 0);
1709 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1710 int result, const char *alpha2)
1712 bool regdom_set = false;
1713 struct connman_technology *technology;
1714 enum connman_service_type type;
1715 GSList *tech_drivers;
1717 type = __connman_device_get_service_type(device);
1718 technology = technology_find(type);
1725 for (tech_drivers = technology->driver_list;
1727 tech_drivers = g_slist_next(tech_drivers)) {
1728 struct connman_technology_driver *driver =
1731 if (driver->set_regdom) {
1732 driver->set_regdom(technology, alpha2);
1742 connman_technology_regdom_notify(technology, alpha2);
1745 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1747 struct connman_technology *technology = data;
1750 DBG("technology %p request from %s", technology,
1751 dbus_message_get_sender(msg));
1753 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1754 !technology->enabled)
1755 return __connman_error_permission_denied(msg);
1757 #if !defined TIZEN_EXT
1758 dbus_message_ref(msg);
1759 technology->scan_pending =
1760 g_slist_prepend(technology->scan_pending, msg);
1763 err = __connman_device_request_scan_full(technology->type);
1765 #if defined TIZEN_EXT
1766 return __connman_error_failed(msg, -err);
1768 reply_scan_pending(technology, err);
1771 #if defined TIZEN_EXT
1772 struct connman_scan_pending *pending_data =
1773 g_try_malloc0(sizeof(struct connman_scan_pending));
1775 return __connman_error_failed(msg, ENOMEM);
1777 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1778 DBG("scan_type %d", pending_data->scan_type);
1780 pending_data->msg = dbus_message_ref(msg);
1782 technology->scan_pending =
1783 g_slist_prepend(technology->scan_pending, pending_data);
1788 #if defined TIZEN_EXT
1789 static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
1791 struct connman_technology *technology = data;
1792 DBusMessageIter iter;
1796 DBG("technology %p request from %s", technology,
1797 dbus_message_get_sender(msg));
1799 if (!dbus_message_iter_init(msg, &iter))
1800 return __connman_error_invalid_arguments(msg);
1802 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1803 return __connman_error_invalid_arguments(msg);
1805 dbus_message_iter_get_basic(&iter, &ifname);
1806 DBG("Interface name %s", ifname);
1808 if (!ifname || strlen(ifname) == 0)
1809 return __connman_error_invalid_arguments(msg);
1811 err = connman_device_request_device_scan(technology->type, ifname, true);
1813 return __connman_error_failed(msg, -err);
1815 struct connman_scan_pending *pending_data =
1816 g_try_malloc0(sizeof(struct connman_scan_pending));
1818 return __connman_error_failed(msg, ENOMEM);
1820 pending_data->ifname = g_strdup(ifname);
1821 if (pending_data->ifname == NULL) {
1822 g_free(pending_data);
1823 return __connman_error_failed(msg, ENOMEM);
1826 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1827 DBG("scan_type %d", pending_data->scan_type);
1829 pending_data->msg = dbus_message_ref(msg);
1831 technology->scan_pending =
1832 g_slist_prepend(technology->scan_pending, pending_data);
1837 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1839 struct connman_technology *technology = data;
1840 GSList *specific_scan_list = NULL;
1842 const char *name = NULL;
1843 const char *freq = NULL;
1844 const char *ifname = NULL;
1845 DBusMessageIter iter, dict;
1848 DBG("technology %p request from %s", technology,
1849 dbus_message_get_sender(msg));
1851 if (!dbus_message_iter_init(msg, &iter))
1852 return __connman_error_invalid_arguments(msg);
1854 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1855 return __connman_error_invalid_arguments(msg);
1857 dbus_message_iter_recurse(&iter, &dict);
1858 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1859 DBusMessageIter entry, value2;
1863 dbus_message_iter_recurse(&dict, &entry);
1864 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1865 g_slist_free_full(specific_scan_list, g_free);
1866 return __connman_error_invalid_arguments(msg);
1869 dbus_message_iter_get_basic(&entry, &key);
1870 dbus_message_iter_next(&entry);
1872 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1873 g_slist_free_full(specific_scan_list, g_free);
1874 return __connman_error_invalid_arguments(msg);
1877 dbus_message_iter_recurse(&entry, &value2);
1878 type = dbus_message_iter_get_arg_type(&value2);
1879 if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
1881 dbus_message_iter_get_basic(&value2, &ifname);
1882 DBG("ifname %s", ifname);
1883 } else if (g_str_equal(key, "SSID")) {
1884 if (type != DBUS_TYPE_STRING) {
1885 g_slist_free_full(specific_scan_list, g_free);
1886 return __connman_error_invalid_arguments(msg);
1889 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1890 dbus_message_iter_get_basic(&value2, &name);
1891 DBG("name %s", name);
1892 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1893 } else if (g_str_equal(key, "Frequency")) {
1894 if (type != DBUS_TYPE_STRING) {
1895 g_slist_free_full(specific_scan_list, g_free);
1896 return __connman_error_invalid_arguments(msg);
1899 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1900 dbus_message_iter_get_basic(&value2, &freq);
1901 DBG("freq %s", freq);
1902 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1903 } else if (g_str_equal(key, "SSID_Mixed")) {
1904 if (type != DBUS_TYPE_STRING) {
1905 g_slist_free_full(specific_scan_list, g_free);
1906 return __connman_error_invalid_arguments(msg);
1909 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1910 dbus_message_iter_get_basic(&value2, &name);
1912 connman_multi_scan_ap_s *ap =
1913 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1915 g_strlcpy(ap->str, name, strlen(name) + 1);
1917 specific_scan_list = g_slist_append(specific_scan_list, ap);
1919 DBG("Failed to allocate memory");
1921 } else if (g_str_equal(key, "Frequency_Mixed")) {
1922 if (type != DBUS_TYPE_STRING) {
1923 g_slist_free_full(specific_scan_list, g_free);
1924 return __connman_error_invalid_arguments(msg);
1927 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1928 dbus_message_iter_get_basic(&value2, &freq);
1930 connman_multi_scan_ap_s *ap =
1931 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1933 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1935 specific_scan_list = g_slist_append(specific_scan_list, ap);
1937 DBG("Failed to allocate memory");
1939 dbus_message_iter_next(&dict);
1942 err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
1944 return __connman_error_failed(msg, -err);
1946 guint list_size = g_slist_length(specific_scan_list);
1948 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1949 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
1950 g_slist_free_full(specific_scan_list, g_free);
1952 struct connman_scan_pending *pending_data =
1953 g_try_malloc0(sizeof(struct connman_scan_pending));
1955 return __connman_error_failed(msg, ENOMEM);
1958 pending_data->ifname = g_strdup(ifname);
1959 if (pending_data->ifname == NULL) {
1960 g_free(pending_data);
1961 return __connman_error_failed(msg, ENOMEM);
1966 pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1968 pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1969 DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
1971 pending_data->msg = dbus_message_ref(msg);
1973 technology->scan_pending =
1974 g_slist_prepend(technology->scan_pending, pending_data);
1979 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
1982 DBusMessageIter iter, dict;
1984 struct connman_technology *technology = data;
1985 dbus_bool_t supported = false;
1986 const char *ifname = NULL;
1988 DBG("technology %p", technology);
1990 reply = dbus_message_new_method_return(msg);
1994 dbus_message_iter_init_append(reply, &iter);
1995 connman_dbus_dict_open(&iter, &dict);
1997 for (list = technology->device_list; list; list = list->next) {
1998 struct connman_device *device = list->data;
2000 supported = connman_device_get_wifi_5ghz_supported(device);
2001 ifname = connman_device_get_string(device, "Interface");
2003 DBG("ifname %s supported : %d", ifname, supported);
2004 connman_dbus_dict_append_basic(&dict, ifname,
2009 connman_dbus_dict_close(&iter, &dict);
2014 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
2017 DBusMessageIter iter, dict;
2019 struct connman_technology *technology = data;
2020 dbus_bool_t scanning = false;
2021 const char *ifname = NULL;
2023 DBG("technology %p", technology);
2025 reply = dbus_message_new_method_return(msg);
2029 dbus_message_iter_init_append(reply, &iter);
2030 connman_dbus_dict_open(&iter, &dict);
2032 for (list = technology->device_list; list; list = list->next) {
2033 struct connman_device *device = list->data;
2035 scanning = connman_device_get_scanning(device, technology->type);
2036 ifname = connman_device_get_string(device, "Interface");
2038 DBG("ifname %s scanning : %d", ifname, scanning);
2039 connman_dbus_dict_append_basic(&dict, ifname,
2044 connman_dbus_dict_close(&iter, &dict);
2049 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
2052 DBusMessageIter iter, dict;
2054 struct connman_technology *technology = data;
2055 dbus_int32_t max_scan_ssids = 0;
2056 const char *ifname = NULL;
2058 DBG("technology %p", technology);
2060 reply = dbus_message_new_method_return(msg);
2064 dbus_message_iter_init_append(reply, &iter);
2065 connman_dbus_dict_open(&iter, &dict);
2067 for (list = technology->device_list; list; list = list->next) {
2068 struct connman_device *device = list->data;
2070 max_scan_ssids = connman_device_get_max_scan_ssids(device);
2071 ifname = connman_device_get_string(device, "Interface");
2073 DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
2074 connman_dbus_dict_append_basic(&dict, ifname,
2079 connman_dbus_dict_close(&iter, &dict);
2084 static int technology_enable_device(struct connman_technology *technology,
2085 bool enable_device, const char *ifname, struct connman_device **device_out)
2090 for (list = technology->device_list; list; list = list->next) {
2091 struct connman_device *device = list->data;
2092 const char *str = connman_device_get_string(device, "Interface");
2094 if (g_strcmp0(str, ifname) != 0)
2098 err = __connman_device_enable(device);
2100 err = __connman_device_disable(device);
2102 *device_out = device;
2109 static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
2110 DBusMessage *msg, bool powered, const char *ifname)
2112 DBusMessage *reply = NULL;
2113 struct connman_device *device = NULL;
2116 err = technology_enable_device(technology, powered, ifname, &device);
2118 if (err == -EINPROGRESS) {
2120 connman_device_set_pending_reply(device, msg);
2122 } else if (err == -EALREADY) {
2124 reply = __connman_error_already_enabled(msg);
2126 reply = __connman_error_already_disabled(msg);
2128 reply = __connman_error_failed(msg, -err);
2130 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2135 static DBusMessage *set_device_power(DBusConnection *conn,
2136 DBusMessage *msg, void *data)
2138 struct connman_technology *technology = data;
2139 DBusMessageIter iter;
2144 DBG("conn %p", conn);
2146 if (!dbus_message_iter_init(msg, &iter))
2147 return __connman_error_invalid_arguments(msg);
2149 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2150 return __connman_error_invalid_arguments(msg);
2152 dbus_message_iter_get_basic(&iter, &name);
2153 dbus_message_iter_next(&iter);
2155 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
2156 return __connman_error_invalid_arguments(msg);
2158 DBG("interface name %s", name);
2162 if (len + 1 > IFNAMSIZ)
2163 return __connman_error_invalid_arguments(msg);
2165 dbus_message_iter_get_basic(&iter, &enable);
2166 DBG("powered %s", enable ? "TRUE" : "FALSE");
2168 return technology_set_device_powered(technology, msg, enable, name);
2171 static DBusMessage *set_bssid(DBusConnection *conn,
2172 DBusMessage *msg, void *data)
2174 DBusMessageIter iter;
2178 DBG("conn %p", conn);
2180 if (!dbus_message_iter_init(msg, &iter))
2181 return __connman_error_invalid_arguments(msg);
2183 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2184 return __connman_error_invalid_arguments(msg);
2186 dbus_message_iter_get_basic(&iter, &name);
2187 dbus_message_iter_next(&iter);
2189 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2190 return __connman_error_invalid_arguments(msg);
2192 dbus_message_iter_get_basic(&iter, &bssid);
2194 DBG("interface name %s bssid %s", name, bssid);
2198 if (len + 1 > IFNAMSIZ)
2199 return __connman_error_invalid_arguments(msg);
2201 set_connman_bssid(SET_BSSID, bssid, name);
2203 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2205 static struct connman_technology *technology_get(enum connman_service_type type);
2207 void technology_save_device(struct connman_device *device)
2209 struct connman_technology *technology;
2210 enum connman_service_type type;
2212 type = __connman_device_get_service_type(device);
2213 technology = technology_get(type);
2219 const char *name = get_name(technology->type);
2221 DBG("technology %p type %d name %s", technology, technology->type,
2226 keyfile = __connman_storage_load_global();
2228 keyfile = g_key_file_new();
2230 identifier = g_strdup_printf("%s", name);
2234 GSList *list = NULL;
2235 gchar **ifname_list = NULL;
2236 guint dev_count = g_slist_length(technology->device_list);
2238 if (dev_count > 1) {
2239 GString *ifname_str = g_string_new(NULL);
2242 for (list = technology->device_list; list; list = list->next) {
2243 struct connman_device *device = list->data;
2245 if (connman_device_get_powered(device)) {
2246 const char *ifname = connman_device_get_string(device, "Interface");
2248 if (ifname_str->len > 0)
2249 g_string_append_printf(ifname_str, " %s", ifname);
2251 g_string_append(ifname_str, ifname);
2255 if (ifname_str->len > 0) {
2256 ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
2257 dev_count = g_strv_length(ifname_list);
2258 g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
2259 (const gchar **) ifname_list, dev_count);
2261 technology->enable_persistent = true;
2263 g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
2264 technology->enable_persistent = false;
2267 g_strfreev(ifname_list);
2268 g_string_free(ifname_str, TRUE);
2272 g_key_file_set_boolean(keyfile, identifier, "Enable",
2273 technology->enable_persistent);
2275 g_key_file_set_boolean(keyfile, identifier, "Tethering",
2276 technology->tethering_persistent);
2278 if (technology->tethering_ident)
2279 g_key_file_set_string(keyfile, identifier,
2280 "Tethering.Identifier",
2281 technology->tethering_ident);
2283 if (technology->tethering_passphrase)
2284 g_key_file_set_string(keyfile, identifier,
2285 "Tethering.Passphrase",
2286 technology->tethering_passphrase);
2291 __connman_storage_save_global(keyfile);
2293 g_key_file_free(keyfile);
2297 #if defined TIZEN_EXT_WIFI_MESH
2298 bool __connman_technology_get_connected(enum connman_service_type type)
2300 struct connman_technology *technology;
2302 technology = technology_find(type);
2307 return technology->connected;
2310 void __connman_technology_mesh_interface_create_finished(
2311 enum connman_service_type type, bool success,
2315 struct connman_technology *technology;
2317 technology = technology_find(type);
2319 DBG("technology %p success %d", technology, success);
2324 msg = technology->mesh_dbus_msg;
2326 DBG("No pending dbus message");
2331 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2332 __connman_device_request_scan(technology->type);
2334 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
2335 ".MeshInterfaceAddFailed", "%s", error);
2336 g_dbus_send_message(connection, reply);
2337 dbus_message_unref(msg);
2338 technology->mesh_dbus_msg = NULL;
2341 void __connman_technology_mesh_interface_remove_finished(
2342 enum connman_service_type type, bool success)
2345 struct connman_technology *technology;
2347 technology = technology_find(type);
2349 DBG("technology %p success %d", technology, success);
2351 if (!technology || !technology->mesh_dbus_msg)
2354 msg = technology->mesh_dbus_msg;
2356 DBG("No pending dbus message");
2361 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2363 reply = __connman_error_failed(msg, EINVAL);
2364 g_dbus_send_message(connection, reply);
2365 dbus_message_unref(msg);
2366 technology->mesh_dbus_msg = NULL;
2369 void __connman_technology_notify_abort_scan(enum connman_service_type type,
2373 struct connman_technology *technology;
2375 technology = technology_find(type);
2377 DBG("technology %p result %d", technology, result);
2379 if (!technology || !technology->mesh_dbus_msg)
2382 msg = technology->mesh_dbus_msg;
2384 DBG("No pending dbus message");
2389 reply = __connman_error_scan_abort_failed(msg);
2391 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2393 g_dbus_send_message(connection, reply);
2394 dbus_message_unref(msg);
2395 technology->mesh_dbus_msg = NULL;
2398 static DBusMessage *mesh_commands(DBusConnection *conn,
2399 DBusMessage *msg, void *data)
2401 struct connman_technology *technology = data;
2402 DBusMessageIter iter, value, dict;
2403 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
2406 DBG("conn %p", conn);
2408 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
2409 return __connman_error_invalid_arguments(msg);
2411 if (!dbus_message_iter_init(msg, &iter))
2412 return __connman_error_invalid_arguments(msg);
2414 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2415 return __connman_error_invalid_arguments(msg);
2417 dbus_message_iter_get_basic(&iter, &cmd);
2418 dbus_message_iter_next(&iter);
2420 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
2421 return __connman_error_invalid_arguments(msg);
2423 dbus_message_iter_recurse(&iter, &value);
2425 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
2426 return __connman_error_invalid_arguments(msg);
2428 DBG("Mesh Command %s", cmd);
2429 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
2430 dbus_message_iter_recurse(&value, &dict);
2431 const char *bridge_ifname = NULL;
2432 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2433 DBusMessageIter entry, value2;
2437 dbus_message_iter_recurse(&dict, &entry);
2439 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2440 return __connman_error_invalid_arguments(msg);
2442 dbus_message_iter_get_basic(&entry, &key);
2443 dbus_message_iter_next(&entry);
2445 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2446 return __connman_error_invalid_arguments(msg);
2448 dbus_message_iter_recurse(&entry, &value2);
2450 type = dbus_message_iter_get_arg_type(&value2);
2452 if (g_str_equal(key, "Ifname")) {
2453 if (type != DBUS_TYPE_STRING)
2454 return __connman_error_invalid_arguments(msg);
2456 dbus_message_iter_get_basic(&value2, &ifname);
2457 } else if (g_str_equal(key, "ParentIfname")) {
2458 if (type != DBUS_TYPE_STRING)
2459 return __connman_error_invalid_arguments(msg);
2461 dbus_message_iter_get_basic(&value2, &parent_ifname);
2462 } else if (g_str_equal(key, "BridgeIfname")) {
2463 if (type != DBUS_TYPE_STRING)
2464 return __connman_error_invalid_arguments(msg);
2466 dbus_message_iter_get_basic(&value2, &bridge_ifname);
2468 dbus_message_iter_next(&dict);
2470 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
2471 bridge_ifname ? bridge_ifname : "NULL");
2472 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
2476 DBG("Failed to add virtual mesh interface");
2477 return __connman_error_failed(msg, -err);
2480 DBG("Successfully added virtual mesh interface");
2482 dbus_message_ref(msg);
2483 technology->mesh_dbus_msg = msg;
2485 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
2486 dbus_message_iter_recurse(&value, &dict);
2487 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2488 DBusMessageIter entry, value2;
2492 dbus_message_iter_recurse(&dict, &entry);
2494 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2495 return __connman_error_invalid_arguments(msg);
2497 dbus_message_iter_get_basic(&entry, &key);
2498 dbus_message_iter_next(&entry);
2500 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2501 return __connman_error_invalid_arguments(msg);
2503 dbus_message_iter_recurse(&entry, &value2);
2505 type = dbus_message_iter_get_arg_type(&value2);
2507 if (g_str_equal(key, "Ifname")) {
2508 if (type != DBUS_TYPE_STRING)
2509 return __connman_error_invalid_arguments(msg);
2511 dbus_message_iter_get_basic(&value2, &ifname);
2513 dbus_message_iter_next(&dict);
2515 DBG("Mesh Ifname %s", ifname);
2516 err = __connman_mesh_remove_virtual_interface(ifname);
2519 DBG("Failed to remove virtual mesh interface");
2520 return __connman_error_failed(msg, -err);
2523 DBG("Successfully removed virtual mesh interface");
2525 dbus_message_ref(msg);
2526 technology->mesh_dbus_msg = msg;
2528 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
2529 struct connman_mesh *connman_mesh;
2530 const char *name = NULL;
2531 const char *sec_type = NULL;
2532 const char *mesh_ifname = NULL;
2533 char *identifier, *group, *address;
2534 unsigned int freq = 0;
2535 unsigned int ieee80211w = 0;
2538 dbus_message_iter_recurse(&value, &dict);
2539 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2540 DBusMessageIter entry, value2;
2544 dbus_message_iter_recurse(&dict, &entry);
2546 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2547 return __connman_error_invalid_arguments(msg);
2549 dbus_message_iter_get_basic(&entry, &key);
2550 dbus_message_iter_next(&entry);
2552 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2553 return __connman_error_invalid_arguments(msg);
2555 dbus_message_iter_recurse(&entry, &value2);
2557 type = dbus_message_iter_get_arg_type(&value2);
2559 if (g_str_equal(key, "Name")) {
2560 if (type != DBUS_TYPE_STRING)
2561 return __connman_error_invalid_arguments(msg);
2563 dbus_message_iter_get_basic(&value2, &name);
2564 } else if (g_str_equal(key, "Frequency")) {
2565 if (type != DBUS_TYPE_UINT16)
2566 return __connman_error_invalid_arguments(msg);
2568 dbus_message_iter_get_basic(&value2, &freq);
2569 } else if (g_str_equal(key, "Security")) {
2570 if (type != DBUS_TYPE_STRING)
2571 return __connman_error_invalid_arguments(msg);
2573 dbus_message_iter_get_basic(&value2, &sec_type);
2574 } else if (g_str_equal(key, "Pmf")) {
2575 if (type != DBUS_TYPE_UINT16)
2576 return __connman_error_invalid_arguments(msg);
2578 dbus_message_iter_get_basic(&value2, &ieee80211w);
2580 dbus_message_iter_next(&dict);
2583 if (name == NULL || sec_type == NULL || freq == 0)
2584 return __connman_error_invalid_arguments(msg);
2586 DBG("Name %s Frequency %d Security type %s Pmf %u",
2587 name, freq, sec_type, ieee80211w);
2589 if (g_strcmp0(sec_type, "none") != 0 &&
2590 g_strcmp0(sec_type, "sae") != 0) {
2591 DBG("Unsupported security");
2592 return __connman_error_invalid_arguments(msg);
2595 mesh_ifname = connman_mesh_get_interface_name();
2597 if (!connman_mesh_is_interface_created()) {
2598 DBG("Mesh interface doesn't exists");
2599 return __connman_error_invalid_command(msg);
2602 str = g_string_sized_new((strlen(name) * 2) + 24);
2604 for (i = 0; name[i]; i++)
2605 g_string_append_printf(str, "%02x", name[i]);
2607 g_string_append_printf(str, "_mesh");
2609 if (g_strcmp0(sec_type, "none") == 0)
2610 g_string_append_printf(str, "_none");
2611 else if (g_strcmp0(sec_type, "sae") == 0)
2612 g_string_append_printf(str, "_sae");
2614 group = g_string_free(str, FALSE);
2616 identifier = connman_inet_ifaddr(mesh_ifname);
2617 address = connman_inet_ifname2addr(mesh_ifname);
2619 connman_mesh = connman_mesh_create(identifier, group);
2620 connman_mesh_set_name(connman_mesh, name);
2621 connman_mesh_set_address(connman_mesh, address);
2622 connman_mesh_set_security(connman_mesh, sec_type);
2623 connman_mesh_set_frequency(connman_mesh, freq);
2624 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
2625 connman_mesh_set_peer_type(connman_mesh,
2626 CONNMAN_MESH_PEER_TYPE_CREATED);
2627 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
2629 connman_mesh_register(connman_mesh);
2633 DBG("Successfully Created Mesh Network");
2634 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2636 } else if (g_str_equal(cmd, "AbortScan")) {
2637 DBG("Abort Scan method");
2638 err = __connman_device_abort_scan(technology->type);
2640 DBG("Failed to abort scan");
2641 return __connman_error_failed(msg, -err);
2644 DBG("Successfully requested to abort scan");
2645 dbus_message_ref(msg);
2646 technology->mesh_dbus_msg = msg;
2648 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
2649 const char *name = NULL;
2650 unsigned int freq = 0;
2651 dbus_message_iter_recurse(&value, &dict);
2652 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2653 DBusMessageIter entry, value2;
2657 dbus_message_iter_recurse(&dict, &entry);
2659 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2660 return __connman_error_invalid_arguments(msg);
2662 dbus_message_iter_get_basic(&entry, &key);
2663 dbus_message_iter_next(&entry);
2665 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2666 return __connman_error_invalid_arguments(msg);
2668 dbus_message_iter_recurse(&entry, &value2);
2670 type = dbus_message_iter_get_arg_type(&value2);
2672 if (g_str_equal(key, "Name")) {
2673 if (type != DBUS_TYPE_STRING)
2674 return __connman_error_invalid_arguments(msg);
2676 dbus_message_iter_get_basic(&value2, &name);
2677 } else if (g_str_equal(key, "Frequency")) {
2678 if (type != DBUS_TYPE_UINT16)
2679 return __connman_error_invalid_arguments(msg);
2681 dbus_message_iter_get_basic(&value2, &freq);
2683 dbus_message_iter_next(&dict);
2686 DBG("MeshID %s Frequency %d sender %s", name, freq,
2687 dbus_message_get_sender(msg));
2689 struct connman_scan_pending *pending_data =
2690 g_try_malloc0(sizeof(struct connman_scan_pending));
2692 return __connman_error_failed(msg, ENOMEM);
2694 pending_data->msg = dbus_message_ref(msg);
2696 technology->scan_pending =
2697 g_slist_prepend(technology->scan_pending, pending_data);
2699 err = __connman_device_request_mesh_specific_scan(technology->type,
2702 reply_scan_pending(technology, err);
2704 DBG("Successfully requested to scan specific Mesh Network");
2706 } else if (g_str_equal(cmd, "SetMeshGate")) {
2707 unsigned int hwmp_rootmode = 0;
2708 bool gate_announce = false;
2709 unsigned int stp = 0;
2711 dbus_message_iter_recurse(&value, &dict);
2712 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2713 DBusMessageIter entry, value2;
2717 dbus_message_iter_recurse(&dict, &entry);
2719 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2720 return __connman_error_invalid_arguments(msg);
2722 dbus_message_iter_get_basic(&entry, &key);
2723 dbus_message_iter_next(&entry);
2725 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2726 return __connman_error_invalid_arguments(msg);
2728 dbus_message_iter_recurse(&entry, &value2);
2730 type = dbus_message_iter_get_arg_type(&value2);
2732 if (g_str_equal(key, "GateAnnounce")) {
2733 if (type != DBUS_TYPE_BOOLEAN)
2734 return __connman_error_invalid_arguments(msg);
2736 dbus_message_iter_get_basic(&value2, &gate_announce);
2737 } else if (g_str_equal(key, "HWMPRootMode")) {
2738 if (type != DBUS_TYPE_UINT16)
2739 return __connman_error_invalid_arguments(msg);
2741 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
2742 } else if (g_str_equal(key, "STP")) {
2743 if (type != DBUS_TYPE_UINT16)
2744 return __connman_error_invalid_arguments(msg);
2746 dbus_message_iter_get_basic(&value2, &stp);
2748 dbus_message_iter_next(&dict);
2751 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
2752 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
2754 err = __connman_mesh_set_stp_gate_announce(gate_announce,
2759 return __connman_error_failed(msg, -err);
2761 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2763 return __connman_error_invalid_command(msg);
2768 static const GDBusMethodTable technology_methods[] = {
2769 { GDBUS_DEPRECATED_METHOD("GetProperties",
2770 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
2772 { GDBUS_ASYNC_METHOD("SetProperty",
2773 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2774 NULL, set_property) },
2775 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
2776 #if defined TIZEN_EXT
2777 { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
2778 NULL, scan_device) },
2779 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
2780 NULL, specific_scan) },
2781 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
2783 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2784 get_5ghz_supported) },
2785 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2786 get_max_scan_ssid) },
2787 { GDBUS_ASYNC_METHOD("SetDevicePower",
2788 GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
2789 NULL, set_device_power) },
2790 { GDBUS_ASYNC_METHOD("SetBSSID",
2791 GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
2794 #if defined TIZEN_EXT_WIFI_MESH
2795 { GDBUS_ASYNC_METHOD("MeshCommands",
2796 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2797 NULL, mesh_commands) },
2802 static const GDBusSignalTable technology_signals[] = {
2803 { GDBUS_SIGNAL("PropertyChanged",
2804 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2805 #if defined TIZEN_EXT
2806 { GDBUS_SIGNAL("DeviceChanged",
2807 GDBUS_ARGS({ "device_property", "a{sv}" })) },
2808 { GDBUS_SIGNAL("DeviceDetected",
2809 GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
2814 static bool technology_dbus_register(struct connman_technology *technology)
2816 if (technology->dbus_registered ||
2817 (technology->rfkill_driven &&
2818 technology->hardblocked))
2821 if (!g_dbus_register_interface(connection, technology->path,
2822 CONNMAN_TECHNOLOGY_INTERFACE,
2823 technology_methods, technology_signals,
2824 NULL, technology, NULL)) {
2825 connman_error("Failed to register %s", technology->path);
2829 technology_added_signal(technology);
2830 technology->dbus_registered = true;
2835 static void technology_dbus_unregister(struct connman_technology *technology)
2837 if (!technology->dbus_registered)
2840 technology_removed_signal(technology);
2841 g_dbus_unregister_interface(connection, technology->path,
2842 CONNMAN_TECHNOLOGY_INTERFACE);
2844 technology->dbus_registered = false;
2847 static void technology_put(struct connman_technology *technology)
2849 DBG("technology %p", technology);
2851 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2854 reply_scan_pending(technology, -EINTR);
2856 while (technology->driver_list) {
2857 struct connman_technology_driver *driver;
2859 driver = technology->driver_list->data;
2862 driver->remove(technology);
2864 technology->driver_list =
2865 g_slist_delete_link(technology->driver_list,
2866 technology->driver_list);
2869 technology_list = g_slist_remove(technology_list, technology);
2871 technology_dbus_unregister(technology);
2873 g_slist_free(technology->device_list);
2875 if (technology->pending_reply) {
2876 dbus_message_unref(technology->pending_reply);
2877 technology->pending_reply = NULL;
2878 g_source_remove(technology->pending_timeout);
2879 technology->pending_timeout = 0;
2882 g_strfreev(technology->enabled_devices);
2884 g_free(technology->path);
2885 g_free(technology->regdom);
2886 g_free(technology->tethering_ident);
2887 g_free(technology->tethering_passphrase);
2891 static struct connman_technology *technology_get(enum connman_service_type type)
2893 GSList *tech_drivers = NULL;
2894 struct connman_technology_driver *driver;
2895 struct connman_technology *technology;
2899 DBG("type %d", type);
2901 str = __connman_service_type2string(type);
2905 technology = technology_find(type);
2907 #if defined TIZEN_EXT_WIFI_MESH
2908 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2909 type != CONNMAN_SERVICE_TYPE_MESH)
2911 if (type != CONNMAN_SERVICE_TYPE_P2P)
2913 __sync_fetch_and_add(&technology->refcount, 1);
2917 /* First check if we have a driver for this technology type */
2918 for (list = driver_list; list; list = list->next) {
2919 driver = list->data;
2921 if (driver->type == type) {
2922 DBG("technology %p driver %p", technology, driver);
2923 tech_drivers = g_slist_append(tech_drivers, driver);
2927 if (!tech_drivers) {
2928 DBG("No matching drivers found for %s.",
2929 __connman_service_type2string(type));
2933 technology = g_try_new0(struct connman_technology, 1);
2937 technology->refcount = 1;
2938 technology->type = type;
2939 technology->path = g_strdup_printf("%s/technology/%s",
2942 #if defined TIZEN_EXT_WIFI_MESH
2943 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2944 struct connman_technology *wifi;
2946 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2948 technology->enabled = wifi->enabled;
2952 technology_load(technology);
2953 technology_list = g_slist_prepend(technology_list, technology);
2954 technology->driver_list = tech_drivers;
2956 for (list = tech_drivers; list; list = list->next) {
2957 driver = list->data;
2959 if (driver->probe && driver->probe(technology) < 0)
2960 DBG("Driver probe failed for technology %p",
2964 if (!technology_dbus_register(technology)) {
2965 technology_put(technology);
2969 if (type == CONNMAN_SERVICE_TYPE_P2P) {
2970 struct connman_technology *wifi;
2973 enable = technology->enable_persistent;
2975 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2977 enable = wifi->enabled;
2979 technology_affect_devices(technology, enable);
2982 DBG("technology %p %s", technology, get_name(technology->type));
2987 int connman_technology_driver_register(struct connman_technology_driver *driver)
2990 struct connman_device *device;
2991 enum connman_service_type type;
2993 for (list = driver_list; list; list = list->next) {
2994 if (list->data == driver)
2998 DBG("Registering %s driver", driver->name);
3000 driver_list = g_slist_insert_sorted(driver_list, driver,
3004 * Check for technology less devices if this driver
3005 * can service any of them.
3007 for (list = techless_device_list; list; list = list->next) {
3008 device = list->data;
3010 type = __connman_device_get_service_type(device);
3011 if (type != driver->type)
3014 techless_device_list = g_slist_remove(techless_device_list,
3017 __connman_technology_add_device(device);
3020 /* Check for orphaned rfkill switches. */
3021 g_hash_table_foreach(rfkill_list, rfkill_check,
3022 GINT_TO_POINTER(driver->type));
3025 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3026 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
3030 #if defined TIZEN_EXT_WIFI_MESH
3031 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3032 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
3040 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
3042 GSList *list, *tech_drivers;
3043 struct connman_technology *technology;
3044 struct connman_technology_driver *current;
3046 DBG("Unregistering driver %p name %s", driver, driver->name);
3048 for (list = technology_list; list; list = list->next) {
3049 technology = list->data;
3051 for (tech_drivers = technology->driver_list; tech_drivers;
3052 tech_drivers = g_slist_next(tech_drivers)) {
3053 current = tech_drivers->data;
3054 if (driver != current)
3058 driver->remove(technology);
3060 technology->driver_list =
3061 g_slist_remove(technology->driver_list,
3067 driver_list = g_slist_remove(driver_list, driver);
3069 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
3070 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
3072 technology_put(technology);
3074 #if defined TIZEN_EXT_WIFI_MESH
3075 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
3076 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
3078 technology_put(technology);
3083 void __connman_technology_add_interface(enum connman_service_type type,
3084 int index, const char *ident)
3086 struct connman_technology *technology;
3087 GSList *tech_drivers;
3088 struct connman_technology_driver *driver;
3092 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3093 case CONNMAN_SERVICE_TYPE_SYSTEM:
3095 case CONNMAN_SERVICE_TYPE_ETHERNET:
3096 case CONNMAN_SERVICE_TYPE_WIFI:
3097 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3098 case CONNMAN_SERVICE_TYPE_CELLULAR:
3099 case CONNMAN_SERVICE_TYPE_GPS:
3100 case CONNMAN_SERVICE_TYPE_VPN:
3101 case CONNMAN_SERVICE_TYPE_GADGET:
3102 case CONNMAN_SERVICE_TYPE_P2P:
3103 #if defined TIZEN_EXT_WIFI_MESH
3104 case CONNMAN_SERVICE_TYPE_MESH:
3109 name = connman_inet_ifname(index);
3110 connman_info("Adding interface %s [ %s ]", name,
3111 __connman_service_type2string(type));
3113 technology = technology_find(type);
3118 for (tech_drivers = technology->driver_list; tech_drivers;
3119 tech_drivers = g_slist_next(tech_drivers)) {
3120 driver = tech_drivers->data;
3122 if (driver->add_interface)
3123 driver->add_interface(technology, index, name, ident);
3127 * At this point we can try to enable tethering automatically as
3128 * now the interfaces are set properly.
3130 if (technology->tethering_persistent)
3131 enable_tethering(technology);
3137 void __connman_technology_remove_interface(enum connman_service_type type,
3138 int index, const char *ident)
3140 struct connman_technology *technology;
3141 GSList *tech_drivers;
3142 struct connman_technology_driver *driver;
3146 case CONNMAN_SERVICE_TYPE_UNKNOWN:
3147 case CONNMAN_SERVICE_TYPE_SYSTEM:
3149 case CONNMAN_SERVICE_TYPE_ETHERNET:
3150 case CONNMAN_SERVICE_TYPE_WIFI:
3151 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
3152 case CONNMAN_SERVICE_TYPE_CELLULAR:
3153 case CONNMAN_SERVICE_TYPE_GPS:
3154 case CONNMAN_SERVICE_TYPE_VPN:
3155 case CONNMAN_SERVICE_TYPE_GADGET:
3156 case CONNMAN_SERVICE_TYPE_P2P:
3157 #if defined TIZEN_EXT_WIFI_MESH
3158 case CONNMAN_SERVICE_TYPE_MESH:
3163 name = connman_inet_ifname(index);
3164 connman_info("Remove interface %s [ %s ]", name,
3165 __connman_service_type2string(type));
3168 technology = technology_find(type);
3173 for (tech_drivers = technology->driver_list; tech_drivers;
3174 tech_drivers = g_slist_next(tech_drivers)) {
3175 driver = tech_drivers->data;
3177 if (driver->remove_interface)
3178 driver->remove_interface(technology, index);
3182 int __connman_technology_add_device(struct connman_device *device)
3184 struct connman_technology *technology;
3185 enum connman_service_type type;
3187 type = __connman_device_get_service_type(device);
3189 DBG("device %p type %s", device, get_name(type));
3191 technology = technology_get(type);
3194 * Since no driver can be found for this device at the moment we
3195 * add it to the techless device list.
3197 techless_device_list = g_slist_prepend(techless_device_list,
3203 __sync_synchronize();
3204 if (technology->rfkill_driven) {
3205 if (technology->enabled)
3206 __connman_device_enable(device);
3208 __connman_device_disable(device);
3213 if (technology->enable_persistent &&
3214 !global_offlinemode) {
3215 #if defined TIZEN_EXT
3218 if (technology->enabled_devices) {
3221 const char *ifname = connman_device_get_string(device, "Interface");
3223 while (technology->enabled_devices[i]) {
3224 if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
3233 err = __connman_device_enable(device);
3235 int err = __connman_device_enable(device);
3238 * connman_technology_add_device() calls __connman_device_enable()
3239 * but since the device is already enabled, the call does not
3240 * propagate through to connman_technology_enabled via
3241 * connman_device_set_powered.
3243 if (err == -EALREADY)
3244 __connman_technology_enabled(type);
3246 /* if technology persistent state is offline */
3247 if (!technology->enable_persistent)
3248 __connman_device_disable(device);
3251 technology->device_list = g_slist_prepend(technology->device_list,
3254 #if defined TIZEN_EXT
3255 const char *ifname = connman_device_get_string(device, "Interface");
3256 __connman_technology_notify_device_detected(technology, ifname, true);
3258 connman_device_set_mac_policy(device, technology->mac_policy);
3259 connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy);
3260 connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime);
3265 int __connman_technology_remove_device(struct connman_device *device)
3267 struct connman_technology *technology;
3268 enum connman_service_type type;
3270 DBG("device %p", device);
3272 type = __connman_device_get_service_type(device);
3274 technology = technology_find(type);
3276 techless_device_list = g_slist_remove(techless_device_list,
3281 technology->device_list = g_slist_remove(technology->device_list,
3284 #if defined TIZEN_EXT
3285 const char *ifname = connman_device_get_string(device, "Interface");
3286 __connman_technology_notify_device_detected(technology, ifname, false);
3289 if (technology->tethering)
3290 set_tethering(technology, false);
3292 technology_put(technology);
3297 int __connman_technology_enabled(enum connman_service_type type)
3299 struct connman_technology *technology;
3301 technology = technology_find(type);
3305 DBG("technology %p type %s rfkill %d enabled %d", technology,
3306 get_name(type), technology->rfkill_driven,
3307 technology->enabled);
3309 #if !defined TIZEN_EXT
3310 if (technology->rfkill_driven) {
3311 if (technology->tethering_persistent)
3312 enable_tethering(technology);
3317 return technology_enabled(technology);
3320 int __connman_technology_disabled(enum connman_service_type type)
3322 struct connman_technology *technology;
3325 technology = technology_find(type);
3329 #if !defined TIZEN_EXT
3330 if (technology->rfkill_driven)
3334 for (list = technology->device_list; list; list = list->next) {
3335 struct connman_device *device = list->data;
3337 if (connman_device_get_powered(device))
3341 return technology_disabled(technology);
3344 int __connman_technology_set_offlinemode(bool offlinemode)
3347 int err = -EINVAL, enabled_tech_count = 0;
3349 if (global_offlinemode == offlinemode)
3352 DBG("offlinemode %s", offlinemode ? "On" : "Off");
3355 * This is a bit tricky. When you set offlinemode, there is no
3356 * way to differentiate between attempting offline mode and
3357 * resuming offlinemode from last saved profile. We need that
3358 * information in rfkill_update, otherwise it falls back on the
3359 * technology's persistent state. Hence we set the offline mode here
3360 * but save it & call the notifier only if it is successful.
3363 global_offlinemode = offlinemode;
3365 /* Traverse technology list, enable/disable each technology. */
3366 for (list = technology_list; list; list = list->next) {
3367 struct connman_technology *technology = list->data;
3370 err = technology_disable(technology);
3372 if (technology->hardblocked)
3375 if (technology->enable_persistent) {
3376 err = technology_enable(technology);
3377 enabled_tech_count++;
3382 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
3383 (err == -EINVAL && enabled_tech_count == 0)) {
3384 connman_technology_save_offlinemode();
3385 __connman_notifier_offlinemode(offlinemode);
3387 global_offlinemode = connman_technology_load_offlinemode();
3392 #if defined TIZEN_EXT_WIFI_MESH
3393 static gboolean __add_ethernet_to_bridge(gpointer data)
3396 __connman_mesh_add_ethernet_to_bridge();
3401 void __connman_technology_set_connected(enum connman_service_type type,
3404 struct connman_technology *technology;
3407 technology = technology_find(type);
3411 DBG("technology %p connected %d", technology, connected);
3413 technology->connected = connected;
3415 #if defined TIZEN_EXT_WIFI_MESH
3416 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
3417 g_idle_add(__add_ethernet_to_bridge, NULL);
3421 connman_dbus_property_changed_basic(technology->path,
3422 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
3423 DBUS_TYPE_BOOLEAN, &val);
3426 static bool technology_apply_rfkill_change(struct connman_technology *technology,
3431 bool hardblock_changed = false;
3433 GList *start, *list;
3435 DBG("technology %p --> %d/%d vs %d/%d",
3436 technology, softblock, hardblock,
3437 technology->softblocked, technology->hardblocked);
3439 if (technology->hardblocked == hardblock)
3440 goto softblock_change;
3442 if (!(new_rfkill && !hardblock)) {
3443 start = g_hash_table_get_values(rfkill_list);
3445 for (list = start; list; list = list->next) {
3446 struct connman_rfkill *rfkill = list->data;
3448 if (rfkill->type != technology->type)
3451 if (rfkill->hardblock != hardblock)
3459 goto softblock_change;
3461 technology->hardblocked = hardblock;
3462 hardblock_changed = true;
3465 if (!apply && technology->softblocked != softblock)
3469 return technology->hardblocked;
3471 technology->softblocked = softblock;
3473 if (technology->hardblocked ||
3474 technology->softblocked) {
3475 if (technology_disabled(technology) != -EALREADY)
3476 technology_affect_devices(technology, false);
3477 } else if (!technology->hardblocked &&
3478 !technology->softblocked) {
3479 if (technology_enabled(technology) != -EALREADY)
3480 technology_affect_devices(technology, true);
3483 if (hardblock_changed) {
3484 if (technology->hardblocked) {
3485 DBG("%s is switched off.", get_name(technology->type));
3486 technology_dbus_unregister(technology);
3488 DBG("%s is switched on.", get_name(technology->type));
3489 technology_dbus_register(technology);
3491 if (global_offlinemode)
3492 __connman_rfkill_block(technology->type, true);
3496 return technology->hardblocked;
3499 int __connman_technology_add_rfkill(unsigned int index,
3500 enum connman_service_type type,
3504 struct connman_technology *technology;
3505 struct connman_rfkill *rfkill;
3507 DBG("index %u type %d soft %u hard %u", index, type,
3508 softblock, hardblock);
3510 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3514 rfkill = g_try_new0(struct connman_rfkill, 1);
3518 rfkill->index = index;
3519 rfkill->type = type;
3520 rfkill->softblock = softblock;
3521 rfkill->hardblock = hardblock;
3523 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
3526 #if defined TIZEN_EXT
3527 /* Fix Svace Issue [WGID: 1348]. */
3530 technology = technology_get(type);
3531 /* If there is no driver for this type, ignore it. */
3535 technology->rfkill_driven = true;
3537 #if !defined TIZEN_EXT
3538 /* If hardblocked, there is no need to handle softblocked state */
3539 if (technology_apply_rfkill_change(technology,
3540 softblock, hardblock, true))
3544 if (global_offlinemode)
3548 * Depending on softblocked state we unblock/block according to
3549 * offlinemode and persistente state.
3551 if (technology->softblocked &&
3552 technology->enable_persistent)
3553 return __connman_rfkill_block(type, false);
3554 else if (!technology->softblocked &&
3555 !technology->enable_persistent)
3556 return __connman_rfkill_block(type, true);
3561 int __connman_technology_update_rfkill(unsigned int index,
3562 enum connman_service_type type,
3566 struct connman_technology *technology;
3567 struct connman_rfkill *rfkill;
3569 DBG("index %u soft %u hard %u", index, softblock, hardblock);
3571 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3575 if (rfkill->softblock == softblock &&
3576 rfkill->hardblock == hardblock)
3579 rfkill->softblock = softblock;
3580 rfkill->hardblock = hardblock;
3582 technology = technology_find(type);
3583 /* If there is no driver for this type, ignore it. */
3587 technology_apply_rfkill_change(technology, softblock, hardblock,
3590 if (technology->hardblocked)
3591 DBG("%s hardblocked", get_name(technology->type));
3593 DBG("%s is%s softblocked", get_name(technology->type),
3594 technology->softblocked ? "" : " not");
3599 int __connman_technology_remove_rfkill(unsigned int index,
3600 enum connman_service_type type)
3602 struct connman_technology *technology;
3603 struct connman_rfkill *rfkill;
3605 DBG("index %u", index);
3607 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3611 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
3613 technology = technology_find(type);
3617 technology_apply_rfkill_change(technology,
3618 technology->softblocked, !technology->hardblocked, false);
3620 technology_put(technology);
3625 int __connman_technology_init(void)
3629 connection = connman_dbus_get_connection();
3631 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3634 global_offlinemode = connman_technology_load_offlinemode();
3636 /* This will create settings file if it is missing */
3637 connman_technology_save_offlinemode();
3642 void __connman_technology_cleanup(void)
3646 while (technology_list) {
3647 struct connman_technology *technology = technology_list->data;
3648 technology_list = g_slist_remove(technology_list, technology);
3649 technology_put(technology);
3652 g_hash_table_destroy(rfkill_list);
3654 dbus_connection_unref(connection);