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
37 static DBusConnection *connection;
39 static GSList *technology_list = NULL;
42 * List of devices with no technology associated with them either because of
43 * no compiled in support or the driver is not yet loaded.
45 static GSList *techless_device_list = NULL;
46 static GHashTable *rfkill_list;
48 static bool global_offlinemode;
52 CONNMAN_SCAN_TYPE_FULL_CHANNEL = 0x00,
53 CONNMAN_SCAN_TYPE_SPECIFIC_AP,
54 CONNMAN_SCAN_TYPE_MULTI_AP,
55 } connman_scan_type_e;
57 static connman_scan_type_e g_scan_type = -1;
60 struct connman_rfkill {
62 enum connman_service_type type;
67 struct connman_technology {
69 enum connman_service_type type;
77 bool tethering_persistent; /* Tells the save status, needed
78 * as offline mode might set
81 char *tethering_ident;
82 char *tethering_passphrase;
83 bool tethering_hidden;
85 bool enable_persistent; /* Save the tech state */
89 DBusMessage *pending_reply;
90 guint pending_timeout;
98 #if defined TIZEN_EXT_WIFI_MESH
99 DBusMessage *mesh_dbus_msg;
101 #if defined TIZEN_EXT
102 bool is_5_0_ghz_supported;
106 static GSList *driver_list = NULL;
108 static int technology_enabled(struct connman_technology *technology);
109 static int technology_disabled(struct connman_technology *technology);
111 static gint compare_priority(gconstpointer a, gconstpointer b)
113 const struct connman_technology_driver *driver1 = a;
114 const struct connman_technology_driver *driver2 = b;
116 return driver2->priority - driver1->priority;
119 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
121 struct connman_rfkill *rfkill = value;
122 enum connman_service_type type = GPOINTER_TO_INT(user_data);
124 /* Calling _technology_rfkill_add will update the tech. */
125 if (rfkill->type == type)
126 __connman_technology_add_rfkill(rfkill->index, type,
127 rfkill->softblock, rfkill->hardblock);
131 connman_technology_is_tethering_allowed(enum connman_service_type type)
133 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
135 const char *type_str = __connman_service_type2string(type);
142 allowed = connman_setting_get_string_list("TetheringTechnologies");
144 allowed = allowed_default;
146 for (i = 0; allowed[i]; i++) {
147 if (g_strcmp0(allowed[i], type_str) == 0)
154 static const char *get_name(enum connman_service_type type)
157 case CONNMAN_SERVICE_TYPE_UNKNOWN:
158 case CONNMAN_SERVICE_TYPE_SYSTEM:
159 case CONNMAN_SERVICE_TYPE_GPS:
160 case CONNMAN_SERVICE_TYPE_VPN:
162 case CONNMAN_SERVICE_TYPE_GADGET:
164 case CONNMAN_SERVICE_TYPE_ETHERNET:
166 case CONNMAN_SERVICE_TYPE_WIFI:
168 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
170 case CONNMAN_SERVICE_TYPE_CELLULAR:
172 case CONNMAN_SERVICE_TYPE_P2P:
174 #if defined TIZEN_EXT_WIFI_MESH
175 case CONNMAN_SERVICE_TYPE_MESH:
183 static void technology_save(struct connman_technology *technology)
187 const char *name = get_name(technology->type);
189 DBG("technology %p type %d name %s", technology, technology->type,
194 keyfile = __connman_storage_load_global();
196 keyfile = g_key_file_new();
198 identifier = g_strdup_printf("%s", name);
202 g_key_file_set_boolean(keyfile, identifier, "Enable",
203 technology->enable_persistent);
205 g_key_file_set_boolean(keyfile, identifier, "Tethering",
206 technology->tethering_persistent);
208 g_key_file_set_boolean(keyfile, identifier, "Hidden",
209 technology->tethering_hidden);
211 if (technology->tethering_ident)
212 g_key_file_set_string(keyfile, identifier,
213 "Tethering.Identifier",
214 technology->tethering_ident);
216 if (technology->tethering_passphrase)
217 g_key_file_set_string(keyfile, identifier,
218 "Tethering.Passphrase",
219 technology->tethering_passphrase);
224 __connman_storage_save_global(keyfile);
226 g_key_file_free(keyfile);
231 static void tethering_changed(struct connman_technology *technology)
233 dbus_bool_t tethering = technology->tethering;
235 connman_dbus_property_changed_basic(technology->path,
236 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
237 DBUS_TYPE_BOOLEAN, &tethering);
239 technology_save(technology);
242 int connman_technology_tethering_notify(struct connman_technology *technology,
247 DBG("technology %p enabled %u", technology, enabled);
249 if (technology->tethering == enabled)
253 err = __connman_tethering_set_enabled();
257 __connman_tethering_set_disabled();
259 technology->tethering = enabled;
260 tethering_changed(technology);
265 static int set_tethering(struct connman_technology *technology,
268 int result = -EOPNOTSUPP;
270 const char *ident, *passphrase, *bridge;
271 GSList *tech_drivers;
273 ident = technology->tethering_ident;
274 passphrase = technology->tethering_passphrase;
276 __sync_synchronize();
277 if (!technology->enabled)
280 bridge = __connman_tethering_get_bridge();
284 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && (!ident))
287 for (tech_drivers = technology->driver_list; tech_drivers;
288 tech_drivers = g_slist_next(tech_drivers)) {
289 struct connman_technology_driver *driver = tech_drivers->data;
291 if (!driver || !driver->set_tethering)
294 err = driver->set_tethering(technology, ident, passphrase,
297 if (result == -EINPROGRESS)
300 if (err == -EINPROGRESS || err == 0)
307 void connman_technology_regdom_notify(struct connman_technology *technology,
313 connman_error("Failed to set regulatory domain");
315 DBG("Regulatory domain set to %s", alpha2);
317 g_free(technology->regdom);
318 technology->regdom = g_strdup(alpha2);
321 static int set_regdom_by_device(struct connman_technology *technology,
326 for (list = technology->device_list; list; list = list->next) {
327 struct connman_device *device = list->data;
329 if (connman_device_set_regdom(device, alpha2) != 0)
336 int connman_technology_set_regdom(const char *alpha2)
338 GSList *list, *tech_drivers;
340 for (list = technology_list; list; list = list->next) {
341 struct connman_technology *technology = list->data;
343 if (set_regdom_by_device(technology, alpha2) != 0) {
345 for (tech_drivers = technology->driver_list;
347 tech_drivers = g_slist_next(tech_drivers)) {
349 struct connman_technology_driver *driver =
352 if (driver->set_regdom)
353 driver->set_regdom(technology, alpha2);
361 static struct connman_technology *technology_find(enum connman_service_type type)
365 DBG("type %d", type);
367 for (list = technology_list; list; list = list->next) {
368 struct connman_technology *technology = list->data;
370 if (technology->type == type)
377 bool connman_technology_get_wifi_tethering(const char **ssid,
380 struct connman_technology *technology;
387 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
391 if (!technology->tethering)
394 *ssid = technology->tethering_ident;
395 *psk = technology->tethering_passphrase;
400 #if defined TIZEN_EXT
401 void connman_techonology_wifi_set_5ghz_supported(struct connman_technology *wifi_technology,
402 bool is_5_0_ghz_supported)
406 wifi_technology->is_5_0_ghz_supported = is_5_0_ghz_supported;
410 static void free_rfkill(gpointer data)
412 struct connman_rfkill *rfkill = data;
417 static void technology_load(struct connman_technology *technology)
421 GError *error = NULL;
422 bool enable, need_saving = false;
424 DBG("technology %p", technology);
426 keyfile = __connman_storage_load_global();
427 /* Fallback on disabling technology if file not found. */
429 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
430 /* We enable ethernet by default */
431 technology->enable_persistent = true;
433 technology->enable_persistent = false;
437 identifier = g_strdup_printf("%s", get_name(technology->type));
441 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
443 technology->enable_persistent = enable;
445 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
446 technology->enable_persistent = true;
448 technology->enable_persistent = false;
451 g_clear_error(&error);
454 enable = g_key_file_get_boolean(keyfile, identifier,
455 "Tethering", &error);
457 technology->tethering_persistent = enable;
460 g_clear_error(&error);
464 technology_save(technology);
466 technology->tethering_ident = g_key_file_get_string(keyfile,
467 identifier, "Tethering.Identifier", NULL);
469 technology->tethering_passphrase = g_key_file_get_string(keyfile,
470 identifier, "Tethering.Passphrase", NULL);
474 g_key_file_free(keyfile);
479 bool __connman_technology_get_offlinemode(void)
481 return global_offlinemode;
484 static void connman_technology_save_offlinemode(void)
487 GError *error = NULL;
490 keyfile = __connman_storage_load_global();
493 keyfile = g_key_file_new();
494 g_key_file_set_boolean(keyfile, "global",
495 "OfflineMode", global_offlinemode);
497 __connman_storage_save_global(keyfile);
500 offlinemode = g_key_file_get_boolean(keyfile, "global",
501 "OfflineMode", &error);
503 if (error || offlinemode != global_offlinemode) {
504 g_key_file_set_boolean(keyfile, "global",
505 "OfflineMode", global_offlinemode);
507 g_clear_error(&error);
509 __connman_storage_save_global(keyfile);
513 g_key_file_free(keyfile);
518 static bool connman_technology_load_offlinemode(void)
521 GError *error = NULL;
524 /* If there is a error, we enable offlinemode */
525 keyfile = __connman_storage_load_global();
529 offlinemode = g_key_file_get_boolean(keyfile, "global",
530 "OfflineMode", &error);
533 g_clear_error(&error);
536 g_key_file_free(keyfile);
541 static void append_properties(DBusMessageIter *iter,
542 struct connman_technology *technology)
544 DBusMessageIter dict;
548 connman_dbus_dict_open(iter, &dict);
550 str = get_name(technology->type);
552 connman_dbus_dict_append_basic(&dict, "Name",
553 DBUS_TYPE_STRING, &str);
555 str = __connman_service_type2string(technology->type);
557 connman_dbus_dict_append_basic(&dict, "Type",
558 DBUS_TYPE_STRING, &str);
560 __sync_synchronize();
561 val = technology->enabled;
562 connman_dbus_dict_append_basic(&dict, "Powered",
566 val = technology->connected;
567 connman_dbus_dict_append_basic(&dict, "Connected",
571 val = technology->tethering;
572 connman_dbus_dict_append_basic(&dict, "Tethering",
576 if (technology->tethering_ident)
577 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
579 &technology->tethering_ident);
581 if (technology->tethering_passphrase)
582 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
584 &technology->tethering_passphrase);
586 val = technology->tethering_hidden;
587 connman_dbus_dict_append_basic(&dict, "Hidden",
591 connman_dbus_dict_close(iter, &dict);
594 static void technology_added_signal(struct connman_technology *technology)
597 DBusMessageIter iter;
599 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
600 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
604 dbus_message_iter_init_append(signal, &iter);
605 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
607 append_properties(&iter, technology);
609 dbus_connection_send(connection, signal, NULL);
610 dbus_message_unref(signal);
613 static void technology_removed_signal(struct connman_technology *technology)
615 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
616 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
617 DBUS_TYPE_OBJECT_PATH, &technology->path,
621 static DBusMessage *get_properties(DBusConnection *conn,
622 DBusMessage *message, void *user_data)
624 struct connman_technology *technology = user_data;
626 DBusMessageIter iter;
628 reply = dbus_message_new_method_return(message);
632 dbus_message_iter_init_append(reply, &iter);
633 append_properties(&iter, technology);
638 void __connman_technology_list_struct(DBusMessageIter *array)
641 DBusMessageIter entry;
643 for (list = technology_list; list; list = list->next) {
644 struct connman_technology *technology = list->data;
646 if (!technology->path ||
647 (technology->rfkill_driven &&
648 technology->hardblocked))
651 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
653 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
655 append_properties(&entry, technology);
656 dbus_message_iter_close_container(array, &entry);
660 static gboolean technology_pending_reply(gpointer user_data)
662 struct connman_technology *technology = user_data;
665 /* Power request timedout, send ETIMEDOUT. */
666 if (technology->pending_reply) {
667 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
669 g_dbus_send_message(connection, reply);
671 dbus_message_unref(technology->pending_reply);
672 technology->pending_reply = NULL;
673 technology->pending_timeout = 0;
679 static int technology_affect_devices(struct connman_technology *technology,
682 int err = 0, err_dev;
685 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
687 __connman_technology_enabled(technology->type);
689 __connman_technology_disabled(technology->type);
693 #if defined TIZEN_EXT_WIFI_MESH
694 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
698 for (list = technology->device_list; list; list = list->next) {
699 struct connman_device *device = list->data;
702 err_dev = __connman_device_enable(device);
704 err_dev = __connman_device_disable(device);
706 if (err_dev < 0 && err_dev != -EALREADY)
713 static void powered_changed(struct connman_technology *technology)
717 if (!technology->dbus_registered)
720 if (technology->pending_reply) {
721 g_dbus_send_reply(connection,
722 technology->pending_reply, DBUS_TYPE_INVALID);
723 dbus_message_unref(technology->pending_reply);
724 technology->pending_reply = NULL;
726 g_source_remove(technology->pending_timeout);
727 technology->pending_timeout = 0;
730 __sync_synchronize();
731 enabled = technology->enabled;
732 #if defined TIZEN_EXT
733 DBG("ConnMan, Powered : %s, %s",
734 enabled ? "TRUE" : "FALSE",technology->path);
736 connman_dbus_property_changed_basic(technology->path,
737 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
738 DBUS_TYPE_BOOLEAN, &enabled);
741 static void enable_tethering(struct connman_technology *technology)
745 if (!connman_setting_get_bool("PersistentTetheringMode"))
748 ret = set_tethering(technology, true);
749 if (ret < 0 && ret != -EALREADY)
750 DBG("Cannot enable tethering yet for %s (%d/%s)",
751 get_name(technology->type),
752 -ret, strerror(-ret));
755 static int technology_enabled(struct connman_technology *technology)
757 __sync_synchronize();
758 if (technology->enabled)
761 technology->enabled = true;
763 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
764 struct connman_technology *p2p;
766 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
767 if (p2p && !p2p->enabled && p2p->enable_persistent)
768 technology_enabled(p2p);
771 if (technology->tethering_persistent)
772 enable_tethering(technology);
774 powered_changed(technology);
779 static int technology_enable(struct connman_technology *technology)
784 DBG("technology %p enable", technology);
786 __sync_synchronize();
788 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
789 struct connman_technology *wifi;
791 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
792 if (wifi && wifi->enabled)
793 return technology_enabled(technology);
797 if (technology->enabled)
800 if (technology->pending_reply)
803 if (connman_setting_get_bool("PersistentTetheringMode") &&
804 technology->tethering)
805 set_tethering(technology, true);
807 if (technology->rfkill_driven)
808 err = __connman_rfkill_block(technology->type, false);
810 err_dev = technology_affect_devices(technology, true);
812 if (!technology->rfkill_driven)
818 static int technology_disabled(struct connman_technology *technology)
820 __sync_synchronize();
821 if (!technology->enabled)
824 technology->enabled = false;
826 powered_changed(technology);
831 static int technology_disable(struct connman_technology *technology)
835 DBG("technology %p disable", technology);
837 __sync_synchronize();
839 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
840 technology->enable_persistent = false;
841 return technology_disabled(technology);
842 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
843 struct connman_technology *p2p;
845 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
846 if (p2p && p2p->enabled) {
847 p2p->enable_persistent = true;
848 technology_disabled(p2p);
852 if (!technology->enabled)
855 if (technology->pending_reply)
858 if (technology->tethering)
859 set_tethering(technology, false);
861 err = technology_affect_devices(technology, false);
863 if (technology->rfkill_driven)
864 err = __connman_rfkill_block(technology->type, true);
869 static DBusMessage *set_powered(struct connman_technology *technology,
870 DBusMessage *msg, bool powered)
872 DBusMessage *reply = NULL;
875 if (technology->rfkill_driven && technology->hardblocked) {
881 err = technology_enable(technology);
883 err = technology_disable(technology);
886 technology->enable_persistent = powered;
887 technology_save(technology);
891 if (err == -EINPROGRESS) {
892 technology->pending_reply = dbus_message_ref(msg);
893 technology->pending_timeout = g_timeout_add_seconds(10,
894 technology_pending_reply, technology);
895 } else if (err == -EALREADY) {
897 reply = __connman_error_already_enabled(msg);
899 reply = __connman_error_already_disabled(msg);
901 reply = __connman_error_failed(msg, -err);
903 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
908 #if defined TIZEN_EXT
909 int set_connman_bssid(enum bssid_type mode, char *bssid)
911 static unsigned char bssid_for_connect[6];
912 static int bssid_len;
914 DBG("mode : %d", mode);
916 if (mode == CHECK_BSSID) {
920 if (mode == GET_BSSID && bssid) {
921 memcpy(bssid, bssid_for_connect, 6);
925 if (mode == RESET_BSSID) {
930 if (mode != SET_BSSID || !bssid) {
931 DBG("Invalid parameter");
935 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
936 &bssid_for_connect[0], &bssid_for_connect[1], &bssid_for_connect[2],
937 &bssid_for_connect[3], &bssid_for_connect[4], &bssid_for_connect[5]);
938 if (bssid_len != 6) {
939 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
943 DBG("SET BSSID len : %d, BSSID : %02x:%02x:%02x:%02x:%02x:%02x", bssid_len,
944 bssid_for_connect[0], bssid_for_connect[1], bssid_for_connect[2],
945 bssid_for_connect[3], bssid_for_connect[4], bssid_for_connect[5]);
951 static DBusMessage *set_property(DBusConnection *conn,
952 DBusMessage *msg, void *data)
954 struct connman_technology *technology = data;
955 DBusMessageIter iter, value;
959 DBG("conn %p", conn);
961 if (!dbus_message_iter_init(msg, &iter))
962 return __connman_error_invalid_arguments(msg);
964 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
965 return __connman_error_invalid_arguments(msg);
967 dbus_message_iter_get_basic(&iter, &name);
968 dbus_message_iter_next(&iter);
970 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
971 return __connman_error_invalid_arguments(msg);
973 dbus_message_iter_recurse(&iter, &value);
975 type = dbus_message_iter_get_arg_type(&value);
977 DBG("property %s", name);
979 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && technology->connected) {
981 if (connman_dbus_get_connection_unix_user_sync(conn,
982 dbus_message_get_sender(msg),
984 DBG("Can not get unix user id!");
985 return __connman_error_permission_denied(msg);
988 if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
989 DBG("Not allow this user to operate wifi technology now!");
990 return __connman_error_permission_denied(msg);
994 if (g_str_equal(name, "Tethering")) {
995 dbus_bool_t tethering;
998 if (type != DBUS_TYPE_BOOLEAN)
999 return __connman_error_invalid_arguments(msg);
1001 if (!connman_technology_is_tethering_allowed(technology->type)) {
1002 DBG("%s tethering not allowed by config file",
1003 __connman_service_type2string(technology->type));
1004 return __connman_error_not_supported(msg);
1007 dbus_message_iter_get_basic(&value, &tethering);
1009 if (technology->tethering == tethering) {
1011 return __connman_error_already_disabled(msg);
1013 return __connman_error_already_enabled(msg);
1016 err = set_tethering(technology, tethering);
1018 return __connman_error_failed(msg, -err);
1020 technology->tethering_persistent = tethering;
1022 technology_save(technology);
1024 } else if (g_str_equal(name, "TetheringIdentifier")) {
1027 dbus_message_iter_get_basic(&value, &str);
1029 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1030 return __connman_error_not_supported(msg);
1032 if (strlen(str) < 1 || strlen(str) > 32)
1033 return __connman_error_invalid_arguments(msg);
1035 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1036 g_free(technology->tethering_ident);
1037 technology->tethering_ident = g_strdup(str);
1038 technology_save(technology);
1040 connman_dbus_property_changed_basic(technology->path,
1041 CONNMAN_TECHNOLOGY_INTERFACE,
1042 "TetheringIdentifier",
1044 &technology->tethering_ident);
1046 } else if (g_str_equal(name, "TetheringPassphrase")) {
1049 dbus_message_iter_get_basic(&value, &str);
1051 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1052 return __connman_error_not_supported(msg);
1054 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1057 return __connman_error_passphrase_required(msg);
1059 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1060 g_free(technology->tethering_passphrase);
1061 technology->tethering_passphrase = g_strdup(str);
1062 technology_save(technology);
1064 connman_dbus_property_changed_basic(technology->path,
1065 CONNMAN_TECHNOLOGY_INTERFACE,
1066 "TetheringPassphrase",
1068 &technology->tethering_passphrase);
1070 } else if (g_str_equal(name, "Hidden")) {
1073 if (type != DBUS_TYPE_BOOLEAN)
1074 return __connman_error_invalid_arguments(msg);
1076 dbus_message_iter_get_basic(&value, &hidden);
1078 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1079 return __connman_error_not_supported(msg);
1081 technology->tethering_hidden = hidden;
1082 technology_save(technology);
1084 connman_dbus_property_changed_basic(technology->path,
1085 CONNMAN_TECHNOLOGY_INTERFACE,
1089 } else if (g_str_equal(name, "Powered")) {
1092 if (type != DBUS_TYPE_BOOLEAN)
1093 return __connman_error_invalid_arguments(msg);
1095 dbus_message_iter_get_basic(&value, &enable);
1097 return set_powered(technology, msg, enable);
1098 #if defined TIZEN_EXT
1099 } else if (g_str_equal(name, "SetBSSID")) {
1102 if (type != DBUS_TYPE_STRING)
1103 return __connman_error_invalid_arguments(msg);
1105 dbus_message_iter_get_basic(&value, &key);
1106 DBG("BSSID %s", key);
1107 set_connman_bssid(SET_BSSID, key);
1110 return __connman_error_invalid_property(msg);
1112 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1115 static void reply_scan_pending(struct connman_technology *technology, int err)
1119 DBG("technology %p err %d", technology, err);
1121 while (technology->scan_pending) {
1122 DBusMessage *msg = technology->scan_pending->data;
1124 DBG("reply to %s", dbus_message_get_sender(msg));
1127 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1129 reply = __connman_error_failed(msg, -err);
1130 g_dbus_send_message(connection, reply);
1131 dbus_message_unref(msg);
1133 technology->scan_pending =
1134 g_slist_delete_link(technology->scan_pending,
1135 technology->scan_pending);
1139 #if defined TIZEN_EXT
1140 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1143 DBusMessage *signal;
1144 DBusMessageIter iter;
1145 dbus_bool_t result = FALSE;
1147 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1148 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1152 dbus_message_iter_init_append(signal, &iter);
1153 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1155 result = dbus_connection_send(connection, signal, NULL);
1156 dbus_message_unref(signal);
1158 DBG("Successfuly sent signal");
1164 void __connman_technology_scan_started(struct connman_device *device)
1166 DBG("device %p", device);
1167 #if defined TIZEN_EXT
1168 dbus_bool_t status = 1;
1169 __connman_technology_notify_scan_changed("scan_started", &status);
1173 void __connman_technology_scan_stopped(struct connman_device *device,
1174 enum connman_service_type type)
1177 struct connman_technology *technology;
1180 technology = technology_find(type);
1182 DBG("technology %p device %p", technology, device);
1187 for (list = technology->device_list; list; list = list->next) {
1188 struct connman_device *other_device = list->data;
1190 if (device == other_device)
1193 if (__connman_device_get_service_type(other_device) != type)
1196 if (connman_device_get_scanning(other_device))
1200 #if defined TIZEN_EXT
1202 DBusMessage *signal;
1203 DBusMessageIter iter;
1204 dbus_bool_t status = 0;
1205 __connman_technology_notify_scan_changed("scan_done", &status);
1207 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1208 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1212 dbus_message_iter_init_append(signal, &iter);
1213 connman_dbus_property_append_basic(&iter, "Scantype",
1214 DBUS_TYPE_INT32, &g_scan_type);
1216 dbus_connection_send(connection, signal, NULL);
1217 dbus_message_unref(signal);
1218 reply_scan_pending(technology, 0);
1220 DBG("Successfuly sent ScanDone signal");
1224 reply_scan_pending(technology, 0);
1228 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1229 int result, const char *alpha2)
1231 bool regdom_set = false;
1232 struct connman_technology *technology;
1233 enum connman_service_type type;
1234 GSList *tech_drivers;
1236 type = __connman_device_get_service_type(device);
1237 technology = technology_find(type);
1244 for (tech_drivers = technology->driver_list;
1246 tech_drivers = g_slist_next(tech_drivers)) {
1247 struct connman_technology_driver *driver =
1250 if (driver->set_regdom) {
1251 driver->set_regdom(technology, alpha2);
1261 connman_technology_regdom_notify(technology, alpha2);
1264 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1266 struct connman_technology *technology = data;
1269 DBG("technology %p request from %s", technology,
1270 dbus_message_get_sender(msg));
1272 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1273 !technology->enabled)
1274 return __connman_error_permission_denied(msg);
1276 dbus_message_ref(msg);
1277 #if !defined TIZEN_EXT
1278 technology->scan_pending =
1279 g_slist_prepend(technology->scan_pending, msg);
1282 err = __connman_device_request_scan(technology->type);
1283 #if defined TIZEN_EXT
1285 return __connman_error_failed(msg, -err);
1288 reply_scan_pending(technology, err);
1291 #if defined TIZEN_EXT
1293 g_scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1294 DBG("g_scan_type %d", g_scan_type);
1296 technology->scan_pending =
1297 g_slist_prepend(technology->scan_pending, msg);
1302 #if defined TIZEN_EXT
1303 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1305 struct connman_technology *technology = data;
1306 GSList *specific_scan_list = NULL;
1308 const char *name = NULL;
1309 const char *freq = NULL;
1310 DBusMessageIter iter, dict;
1313 DBG("technology %p request from %s", technology,
1314 dbus_message_get_sender(msg));
1316 if (!dbus_message_iter_init(msg, &iter))
1317 return __connman_error_invalid_arguments(msg);
1319 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1320 return __connman_error_invalid_arguments(msg);
1322 dbus_message_iter_recurse(&iter, &dict);
1323 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1324 DBusMessageIter entry, value2;
1328 dbus_message_iter_recurse(&dict, &entry);
1329 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1330 g_slist_free_full(specific_scan_list, g_free);
1331 return __connman_error_invalid_arguments(msg);
1334 dbus_message_iter_get_basic(&entry, &key);
1335 dbus_message_iter_next(&entry);
1337 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1338 g_slist_free_full(specific_scan_list, g_free);
1339 return __connman_error_invalid_arguments(msg);
1342 dbus_message_iter_recurse(&entry, &value2);
1343 type = dbus_message_iter_get_arg_type(&value2);
1344 if (g_str_equal(key, "SSID")) {
1345 if (type != DBUS_TYPE_STRING) {
1346 g_slist_free_full(specific_scan_list, g_free);
1347 return __connman_error_invalid_arguments(msg);
1350 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1351 dbus_message_iter_get_basic(&value2, &name);
1352 DBG("name %s", name);
1353 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1354 } else if (g_str_equal(key, "Frequency")) {
1355 if (type != DBUS_TYPE_STRING) {
1356 g_slist_free_full(specific_scan_list, g_free);
1357 return __connman_error_invalid_arguments(msg);
1360 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1361 dbus_message_iter_get_basic(&value2, &freq);
1362 DBG("freq %s", freq);
1363 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1364 } else if (g_str_equal(key, "SSID_Mixed")) {
1365 if (type != DBUS_TYPE_STRING) {
1366 g_slist_free_full(specific_scan_list, g_free);
1367 return __connman_error_invalid_arguments(msg);
1370 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1371 dbus_message_iter_get_basic(&value2, &name);
1373 connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1375 g_strlcpy(ap->str, name, strlen(name) + 1);
1377 specific_scan_list = g_slist_append(specific_scan_list, ap);
1379 DBG("Failed to allocate memory");
1381 } else if (g_str_equal(key, "Frequency_Mixed")) {
1382 if (type != DBUS_TYPE_STRING) {
1383 g_slist_free_full(specific_scan_list, g_free);
1384 return __connman_error_invalid_arguments(msg);
1387 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1388 dbus_message_iter_get_basic(&value2, &freq);
1390 connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1392 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1394 specific_scan_list = g_slist_append(specific_scan_list, ap);
1396 DBG("Failed to allocate memory");
1398 dbus_message_iter_next(&dict);
1401 dbus_message_ref(msg);
1403 err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list);
1405 return __connman_error_failed(msg, -err);
1408 guint list_size = g_slist_length(specific_scan_list);
1410 g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1412 g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1413 DBG("list_size %u g_scan_type %d", list_size, g_scan_type);
1415 technology->scan_pending =
1416 g_slist_prepend(technology->scan_pending, msg);
1418 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1419 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) {
1420 g_slist_free_full(specific_scan_list, g_free);
1426 #if defined TIZEN_EXT
1427 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
1430 DBusMessageIter iter, dict;
1431 struct connman_technology *technology = data;
1432 dbus_bool_t supported = technology->is_5_0_ghz_supported;
1434 DBG("technology %p", technology);
1436 reply = dbus_message_new_method_return(msg);
1440 dbus_message_iter_init_append(reply, &iter);
1442 connman_dbus_dict_open(&iter, &dict);
1443 connman_dbus_dict_append_basic(&dict, "Is5GhzSupported",
1447 connman_dbus_dict_close(&iter, &dict);
1453 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
1456 DBusMessageIter iter, dict;
1458 struct connman_technology *technology = data;
1459 dbus_bool_t scanning = false;
1461 DBG("technology %p", technology);
1463 for (list = technology->device_list; list; list = list->next) {
1464 struct connman_device *device = list->data;
1465 scanning = connman_device_get_scanning(device);
1470 DBG("scanning : %d", scanning);
1471 reply = dbus_message_new_method_return(msg);
1475 dbus_message_iter_init_append(reply, &iter);
1477 connman_dbus_dict_open(&iter, &dict);
1478 connman_dbus_dict_append_basic(&dict, "Scanstate",
1482 connman_dbus_dict_close(&iter, &dict);
1488 #if defined TIZEN_EXT_WIFI_MESH
1489 bool __connman_technology_get_connected(enum connman_service_type type)
1491 struct connman_technology *technology;
1493 technology = technology_find(type);
1498 return technology->connected;
1501 void __connman_technology_mesh_interface_create_finished(
1502 enum connman_service_type type, bool success,
1506 struct connman_technology *technology;
1508 technology = technology_find(type);
1510 DBG("technology %p success %d", technology, success);
1515 msg = technology->mesh_dbus_msg;
1517 DBG("No pending dbus message");
1522 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1523 __connman_device_request_scan(technology->type);
1525 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
1526 ".MeshInterfaceAddFailed", "%s", error);
1527 g_dbus_send_message(connection, reply);
1528 dbus_message_unref(msg);
1529 technology->mesh_dbus_msg = NULL;
1532 void __connman_technology_mesh_interface_remove_finished(
1533 enum connman_service_type type, bool success)
1536 struct connman_technology *technology;
1538 technology = technology_find(type);
1540 DBG("technology %p success %d", technology, success);
1542 if (!technology || !technology->mesh_dbus_msg)
1545 msg = technology->mesh_dbus_msg;
1547 DBG("No pending dbus message");
1552 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1554 reply = __connman_error_failed(msg, EINVAL);
1555 g_dbus_send_message(connection, reply);
1556 dbus_message_unref(msg);
1557 technology->mesh_dbus_msg = NULL;
1560 void __connman_technology_notify_abort_scan(enum connman_service_type type,
1564 struct connman_technology *technology;
1566 technology = technology_find(type);
1568 DBG("technology %p result %d", technology, result);
1570 if (!technology || !technology->mesh_dbus_msg)
1573 msg = technology->mesh_dbus_msg;
1575 DBG("No pending dbus message");
1580 reply = __connman_error_scan_abort_failed(msg);
1582 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1584 g_dbus_send_message(connection, reply);
1585 dbus_message_unref(msg);
1586 technology->mesh_dbus_msg = NULL;
1589 static DBusMessage *mesh_commands(DBusConnection *conn,
1590 DBusMessage *msg, void *data)
1592 struct connman_technology *technology = data;
1593 DBusMessageIter iter, value, dict;
1594 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
1597 DBG("conn %p", conn);
1599 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
1600 return __connman_error_invalid_arguments(msg);
1602 if (!dbus_message_iter_init(msg, &iter))
1603 return __connman_error_invalid_arguments(msg);
1605 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1606 return __connman_error_invalid_arguments(msg);
1608 dbus_message_iter_get_basic(&iter, &cmd);
1609 dbus_message_iter_next(&iter);
1611 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1612 return __connman_error_invalid_arguments(msg);
1614 dbus_message_iter_recurse(&iter, &value);
1616 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
1617 return __connman_error_invalid_arguments(msg);
1619 DBG("Mesh Command %s", cmd);
1620 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
1621 dbus_message_iter_recurse(&value, &dict);
1622 const char *bridge_ifname = NULL;
1623 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1624 DBusMessageIter entry, value2;
1628 dbus_message_iter_recurse(&dict, &entry);
1630 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1631 return __connman_error_invalid_arguments(msg);
1633 dbus_message_iter_get_basic(&entry, &key);
1634 dbus_message_iter_next(&entry);
1636 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1637 return __connman_error_invalid_arguments(msg);
1639 dbus_message_iter_recurse(&entry, &value2);
1641 type = dbus_message_iter_get_arg_type(&value2);
1643 if (g_str_equal(key, "Ifname")) {
1644 if (type != DBUS_TYPE_STRING)
1645 return __connman_error_invalid_arguments(msg);
1647 dbus_message_iter_get_basic(&value2, &ifname);
1648 } else if (g_str_equal(key, "ParentIfname")) {
1649 if (type != DBUS_TYPE_STRING)
1650 return __connman_error_invalid_arguments(msg);
1652 dbus_message_iter_get_basic(&value2, &parent_ifname);
1653 } else if (g_str_equal(key, "BridgeIfname")) {
1654 if (type != DBUS_TYPE_STRING)
1655 return __connman_error_invalid_arguments(msg);
1657 dbus_message_iter_get_basic(&value2, &bridge_ifname);
1659 dbus_message_iter_next(&dict);
1661 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
1662 bridge_ifname ? bridge_ifname : "NULL");
1663 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
1667 DBG("Failed to add virtual mesh interface");
1668 return __connman_error_failed(msg, -err);
1671 DBG("Successfully added virtual mesh interface");
1673 dbus_message_ref(msg);
1674 technology->mesh_dbus_msg = msg;
1676 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
1677 dbus_message_iter_recurse(&value, &dict);
1678 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1679 DBusMessageIter entry, value2;
1683 dbus_message_iter_recurse(&dict, &entry);
1685 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1686 return __connman_error_invalid_arguments(msg);
1688 dbus_message_iter_get_basic(&entry, &key);
1689 dbus_message_iter_next(&entry);
1691 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1692 return __connman_error_invalid_arguments(msg);
1694 dbus_message_iter_recurse(&entry, &value2);
1696 type = dbus_message_iter_get_arg_type(&value2);
1698 if (g_str_equal(key, "Ifname")) {
1699 if (type != DBUS_TYPE_STRING)
1700 return __connman_error_invalid_arguments(msg);
1702 dbus_message_iter_get_basic(&value2, &ifname);
1704 dbus_message_iter_next(&dict);
1706 DBG("Mesh Ifname %s", ifname);
1707 err = __connman_mesh_remove_virtual_interface(ifname);
1710 DBG("Failed to remove virtual mesh interface");
1711 return __connman_error_failed(msg, -err);
1714 DBG("Successfully removed virtual mesh interface");
1716 dbus_message_ref(msg);
1717 technology->mesh_dbus_msg = msg;
1719 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
1720 struct connman_mesh *connman_mesh;
1721 const char *name = NULL;
1722 const char *sec_type = NULL;
1723 const char *mesh_ifname = NULL;
1724 char *identifier, *group, *address;
1725 unsigned int freq = 0;
1726 unsigned int ieee80211w = 0;
1729 dbus_message_iter_recurse(&value, &dict);
1730 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1731 DBusMessageIter entry, value2;
1735 dbus_message_iter_recurse(&dict, &entry);
1737 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1738 return __connman_error_invalid_arguments(msg);
1740 dbus_message_iter_get_basic(&entry, &key);
1741 dbus_message_iter_next(&entry);
1743 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1744 return __connman_error_invalid_arguments(msg);
1746 dbus_message_iter_recurse(&entry, &value2);
1748 type = dbus_message_iter_get_arg_type(&value2);
1750 if (g_str_equal(key, "Name")) {
1751 if (type != DBUS_TYPE_STRING)
1752 return __connman_error_invalid_arguments(msg);
1754 dbus_message_iter_get_basic(&value2, &name);
1755 } else if (g_str_equal(key, "Frequency")) {
1756 if (type != DBUS_TYPE_UINT16)
1757 return __connman_error_invalid_arguments(msg);
1759 dbus_message_iter_get_basic(&value2, &freq);
1760 } else if (g_str_equal(key, "Security")) {
1761 if (type != DBUS_TYPE_STRING)
1762 return __connman_error_invalid_arguments(msg);
1764 dbus_message_iter_get_basic(&value2, &sec_type);
1765 } else if (g_str_equal(key, "Pmf")) {
1766 if (type != DBUS_TYPE_UINT16)
1767 return __connman_error_invalid_arguments(msg);
1769 dbus_message_iter_get_basic(&value2, &ieee80211w);
1771 dbus_message_iter_next(&dict);
1774 if (name == NULL || sec_type == NULL || freq == 0)
1775 return __connman_error_invalid_arguments(msg);
1777 DBG("Name %s Frequency %d Security type %s Pmf %u",
1778 name, freq, sec_type, ieee80211w);
1780 if (g_strcmp0(sec_type, "none") != 0 &&
1781 g_strcmp0(sec_type, "sae") != 0) {
1782 DBG("Unsupported security");
1783 return __connman_error_invalid_arguments(msg);
1786 mesh_ifname = connman_mesh_get_interface_name();
1788 if (!connman_mesh_is_interface_created()) {
1789 DBG("Mesh interface doesn't exists");
1790 return __connman_error_invalid_command(msg);
1793 str = g_string_sized_new((strlen(name) * 2) + 24);
1795 for (i = 0; name[i]; i++)
1796 g_string_append_printf(str, "%02x", name[i]);
1798 g_string_append_printf(str, "_mesh");
1800 if (g_strcmp0(sec_type, "none") == 0)
1801 g_string_append_printf(str, "_none");
1802 else if (g_strcmp0(sec_type, "sae") == 0)
1803 g_string_append_printf(str, "_sae");
1805 group = g_string_free(str, FALSE);
1807 identifier = connman_inet_ifaddr(mesh_ifname);
1808 address = connman_inet_ifname2addr(mesh_ifname);
1810 connman_mesh = connman_mesh_create(identifier, group);
1811 connman_mesh_set_name(connman_mesh, name);
1812 connman_mesh_set_address(connman_mesh, address);
1813 connman_mesh_set_security(connman_mesh, sec_type);
1814 connman_mesh_set_frequency(connman_mesh, freq);
1815 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
1816 connman_mesh_set_peer_type(connman_mesh,
1817 CONNMAN_MESH_PEER_TYPE_CREATED);
1818 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
1820 connman_mesh_register(connman_mesh);
1824 DBG("Successfully Created Mesh Network");
1825 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1827 } else if (g_str_equal(cmd, "AbortScan")) {
1828 DBG("Abort Scan method");
1829 err = __connman_device_abort_scan(technology->type);
1831 DBG("Failed to abort scan");
1832 return __connman_error_failed(msg, -err);
1835 DBG("Successfully requested to abort scan");
1836 dbus_message_ref(msg);
1837 technology->mesh_dbus_msg = msg;
1839 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
1840 const char *name = NULL;
1841 unsigned int freq = 0;
1842 dbus_message_iter_recurse(&value, &dict);
1843 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1844 DBusMessageIter entry, value2;
1848 dbus_message_iter_recurse(&dict, &entry);
1850 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1851 return __connman_error_invalid_arguments(msg);
1853 dbus_message_iter_get_basic(&entry, &key);
1854 dbus_message_iter_next(&entry);
1856 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1857 return __connman_error_invalid_arguments(msg);
1859 dbus_message_iter_recurse(&entry, &value2);
1861 type = dbus_message_iter_get_arg_type(&value2);
1863 if (g_str_equal(key, "Name")) {
1864 if (type != DBUS_TYPE_STRING)
1865 return __connman_error_invalid_arguments(msg);
1867 dbus_message_iter_get_basic(&value2, &name);
1868 } else if (g_str_equal(key, "Frequency")) {
1869 if (type != DBUS_TYPE_UINT16)
1870 return __connman_error_invalid_arguments(msg);
1872 dbus_message_iter_get_basic(&value2, &freq);
1874 dbus_message_iter_next(&dict);
1877 DBG("MeshID %s Frequency %d sender %s", name, freq,
1878 dbus_message_get_sender(msg));
1880 dbus_message_ref(msg);
1881 technology->scan_pending =
1882 g_slist_prepend(technology->scan_pending, msg);
1884 err = __connman_device_request_mesh_specific_scan(technology->type,
1887 reply_scan_pending(technology, err);
1889 DBG("Successfully requested to scan specific Mesh Network");
1891 } else if (g_str_equal(cmd, "SetMeshGate")) {
1892 unsigned int hwmp_rootmode = 0;
1893 bool gate_announce = false;
1894 unsigned int stp = 0;
1896 dbus_message_iter_recurse(&value, &dict);
1897 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1898 DBusMessageIter entry, value2;
1902 dbus_message_iter_recurse(&dict, &entry);
1904 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1905 return __connman_error_invalid_arguments(msg);
1907 dbus_message_iter_get_basic(&entry, &key);
1908 dbus_message_iter_next(&entry);
1910 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1911 return __connman_error_invalid_arguments(msg);
1913 dbus_message_iter_recurse(&entry, &value2);
1915 type = dbus_message_iter_get_arg_type(&value2);
1917 if (g_str_equal(key, "GateAnnounce")) {
1918 if (type != DBUS_TYPE_BOOLEAN)
1919 return __connman_error_invalid_arguments(msg);
1921 dbus_message_iter_get_basic(&value2, &gate_announce);
1922 } else if (g_str_equal(key, "HWMPRootMode")) {
1923 if (type != DBUS_TYPE_UINT16)
1924 return __connman_error_invalid_arguments(msg);
1926 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
1927 } else if (g_str_equal(key, "STP")) {
1928 if (type != DBUS_TYPE_UINT16)
1929 return __connman_error_invalid_arguments(msg);
1931 dbus_message_iter_get_basic(&value2, &stp);
1933 dbus_message_iter_next(&dict);
1936 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
1937 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
1939 err = __connman_mesh_set_stp_gate_announce(gate_announce,
1944 return __connman_error_failed(msg, -err);
1946 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1948 return __connman_error_invalid_command(msg);
1953 static const GDBusMethodTable technology_methods[] = {
1954 { GDBUS_DEPRECATED_METHOD("GetProperties",
1955 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1957 { GDBUS_ASYNC_METHOD("SetProperty",
1958 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1959 NULL, set_property) },
1960 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1961 #if defined TIZEN_EXT
1962 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
1963 NULL, specific_scan) },
1964 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
1966 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
1967 get_5ghz_supported) },
1969 #if defined TIZEN_EXT_WIFI_MESH
1970 { GDBUS_ASYNC_METHOD("MeshCommands",
1971 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1972 NULL, mesh_commands) },
1977 static const GDBusSignalTable technology_signals[] = {
1978 { GDBUS_SIGNAL("PropertyChanged",
1979 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1980 { GDBUS_SIGNAL("DhcpConnected",
1981 GDBUS_ARGS({ "aptype", "s" },
1984 { "hostname", "s" })) },
1985 { GDBUS_SIGNAL("DhcpLeaseDeleted",
1986 GDBUS_ARGS({ "aptype", "s" },
1989 { "hostname", "s" })) },
1993 static bool technology_dbus_register(struct connman_technology *technology)
1995 if (technology->dbus_registered ||
1996 (technology->rfkill_driven &&
1997 technology->hardblocked))
2000 if (!g_dbus_register_interface(connection, technology->path,
2001 CONNMAN_TECHNOLOGY_INTERFACE,
2002 technology_methods, technology_signals,
2003 NULL, technology, NULL)) {
2004 connman_error("Failed to register %s", technology->path);
2008 technology_added_signal(technology);
2009 technology->dbus_registered = true;
2014 static void technology_dbus_unregister(struct connman_technology *technology)
2016 if (!technology->dbus_registered)
2019 technology_removed_signal(technology);
2020 g_dbus_unregister_interface(connection, technology->path,
2021 CONNMAN_TECHNOLOGY_INTERFACE);
2023 technology->dbus_registered = false;
2026 static void technology_put(struct connman_technology *technology)
2028 DBG("technology %p", technology);
2030 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2033 reply_scan_pending(technology, -EINTR);
2035 while (technology->driver_list) {
2036 struct connman_technology_driver *driver;
2038 driver = technology->driver_list->data;
2041 driver->remove(technology);
2043 technology->driver_list =
2044 g_slist_delete_link(technology->driver_list,
2045 technology->driver_list);
2048 technology_list = g_slist_remove(technology_list, technology);
2050 technology_dbus_unregister(technology);
2052 g_slist_free(technology->device_list);
2054 if (technology->pending_reply) {
2055 dbus_message_unref(technology->pending_reply);
2056 technology->pending_reply = NULL;
2057 g_source_remove(technology->pending_timeout);
2058 technology->pending_timeout = 0;
2061 g_free(technology->path);
2062 g_free(technology->regdom);
2063 g_free(technology->tethering_ident);
2064 g_free(technology->tethering_passphrase);
2068 static struct connman_technology *technology_get(enum connman_service_type type)
2070 GSList *tech_drivers = NULL;
2071 struct connman_technology_driver *driver;
2072 struct connman_technology *technology;
2076 DBG("type %d", type);
2078 str = __connman_service_type2string(type);
2082 technology = technology_find(type);
2084 #if defined TIZEN_EXT_WIFI_MESH
2085 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2086 type != CONNMAN_SERVICE_TYPE_MESH)
2088 if (type != CONNMAN_SERVICE_TYPE_P2P)
2090 __sync_fetch_and_add(&technology->refcount, 1);
2094 /* First check if we have a driver for this technology type */
2095 for (list = driver_list; list; list = list->next) {
2096 driver = list->data;
2098 if (driver->type == type) {
2099 DBG("technology %p driver %p", technology, driver);
2100 tech_drivers = g_slist_append(tech_drivers, driver);
2104 if (!tech_drivers) {
2105 DBG("No matching drivers found for %s.",
2106 __connman_service_type2string(type));
2110 technology = g_try_new0(struct connman_technology, 1);
2114 technology->refcount = 1;
2115 technology->type = type;
2116 technology->tethering_hidden = FALSE;
2117 technology->path = g_strdup_printf("%s/technology/%s",
2120 #if defined TIZEN_EXT_WIFI_MESH
2121 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2122 struct connman_technology *wifi;
2124 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2126 technology->enabled = wifi->enabled;
2130 technology_load(technology);
2131 technology_list = g_slist_prepend(technology_list, technology);
2132 technology->driver_list = tech_drivers;
2134 for (list = tech_drivers; list; list = list->next) {
2135 driver = list->data;
2137 if (driver->probe && driver->probe(technology) < 0)
2138 DBG("Driver probe failed for technology %p",
2142 if (!technology_dbus_register(technology)) {
2143 technology_put(technology);
2147 if (type == CONNMAN_SERVICE_TYPE_P2P) {
2148 struct connman_technology *wifi;
2151 enable = technology->enable_persistent;
2153 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2155 enable = wifi->enabled;
2157 technology_affect_devices(technology, enable);
2160 DBG("technology %p %s", technology, get_name(technology->type));
2165 int connman_technology_driver_register(struct connman_technology_driver *driver)
2168 struct connman_device *device;
2169 enum connman_service_type type;
2171 for (list = driver_list; list; list = list->next) {
2172 if (list->data == driver)
2176 DBG("Registering %s driver", driver->name);
2178 driver_list = g_slist_insert_sorted(driver_list, driver,
2182 * Check for technology less devices if this driver
2183 * can service any of them.
2185 for (list = techless_device_list; list; list = list->next) {
2186 device = list->data;
2188 type = __connman_device_get_service_type(device);
2189 if (type != driver->type)
2192 techless_device_list = g_slist_remove(techless_device_list,
2195 __connman_technology_add_device(device);
2198 /* Check for orphaned rfkill switches. */
2199 g_hash_table_foreach(rfkill_list, rfkill_check,
2200 GINT_TO_POINTER(driver->type));
2203 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2204 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
2208 #if defined TIZEN_EXT_WIFI_MESH
2209 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2210 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
2218 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
2220 GSList *list, *tech_drivers;
2221 struct connman_technology *technology;
2222 struct connman_technology_driver *current;
2224 DBG("Unregistering driver %p name %s", driver, driver->name);
2226 for (list = technology_list; list; list = list->next) {
2227 technology = list->data;
2229 for (tech_drivers = technology->driver_list; tech_drivers;
2230 tech_drivers = g_slist_next(tech_drivers)) {
2231 current = tech_drivers->data;
2232 if (driver != current)
2236 driver->remove(technology);
2238 technology->driver_list =
2239 g_slist_remove(technology->driver_list,
2245 driver_list = g_slist_remove(driver_list, driver);
2247 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2248 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
2250 technology_put(technology);
2252 #if defined TIZEN_EXT_WIFI_MESH
2253 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2254 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
2256 technology_put(technology);
2261 void __connman_technology_add_interface(enum connman_service_type type,
2262 int index, const char *ident)
2264 struct connman_technology *technology;
2265 GSList *tech_drivers;
2266 struct connman_technology_driver *driver;
2270 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2271 case CONNMAN_SERVICE_TYPE_SYSTEM:
2273 case CONNMAN_SERVICE_TYPE_ETHERNET:
2274 case CONNMAN_SERVICE_TYPE_WIFI:
2275 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2276 case CONNMAN_SERVICE_TYPE_CELLULAR:
2277 case CONNMAN_SERVICE_TYPE_GPS:
2278 case CONNMAN_SERVICE_TYPE_VPN:
2279 case CONNMAN_SERVICE_TYPE_GADGET:
2280 case CONNMAN_SERVICE_TYPE_P2P:
2281 #if defined TIZEN_EXT_WIFI_MESH
2282 case CONNMAN_SERVICE_TYPE_MESH:
2287 name = connman_inet_ifname(index);
2288 connman_info("Adding interface %s [ %s ]", name,
2289 __connman_service_type2string(type));
2291 technology = technology_find(type);
2296 for (tech_drivers = technology->driver_list; tech_drivers;
2297 tech_drivers = g_slist_next(tech_drivers)) {
2298 driver = tech_drivers->data;
2300 if (driver->add_interface)
2301 driver->add_interface(technology, index, name, ident);
2305 * At this point we can try to enable tethering automatically as
2306 * now the interfaces are set properly.
2308 if (technology->tethering_persistent)
2309 enable_tethering(technology);
2315 void __connman_technology_remove_interface(enum connman_service_type type,
2316 int index, const char *ident)
2318 struct connman_technology *technology;
2319 GSList *tech_drivers;
2320 struct connman_technology_driver *driver;
2324 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2325 case CONNMAN_SERVICE_TYPE_SYSTEM:
2327 case CONNMAN_SERVICE_TYPE_ETHERNET:
2328 case CONNMAN_SERVICE_TYPE_WIFI:
2329 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2330 case CONNMAN_SERVICE_TYPE_CELLULAR:
2331 case CONNMAN_SERVICE_TYPE_GPS:
2332 case CONNMAN_SERVICE_TYPE_VPN:
2333 case CONNMAN_SERVICE_TYPE_GADGET:
2334 case CONNMAN_SERVICE_TYPE_P2P:
2335 #if defined TIZEN_EXT_WIFI_MESH
2336 case CONNMAN_SERVICE_TYPE_MESH:
2341 name = connman_inet_ifname(index);
2342 connman_info("Remove interface %s [ %s ]", name,
2343 __connman_service_type2string(type));
2346 technology = technology_find(type);
2351 for (tech_drivers = technology->driver_list; tech_drivers;
2352 tech_drivers = g_slist_next(tech_drivers)) {
2353 driver = tech_drivers->data;
2355 if (driver->remove_interface)
2356 driver->remove_interface(technology, index);
2360 int __connman_technology_add_device(struct connman_device *device)
2362 struct connman_technology *technology;
2363 enum connman_service_type type;
2365 type = __connman_device_get_service_type(device);
2367 DBG("device %p type %s", device, get_name(type));
2369 technology = technology_get(type);
2372 * Since no driver can be found for this device at the moment we
2373 * add it to the techless device list.
2375 techless_device_list = g_slist_prepend(techless_device_list,
2381 __sync_synchronize();
2382 if (technology->rfkill_driven) {
2383 if (technology->enabled)
2384 __connman_device_enable(device);
2386 __connman_device_disable(device);
2391 if (technology->enable_persistent &&
2392 !global_offlinemode) {
2393 int err = __connman_device_enable(device);
2395 * connman_technology_add_device() calls __connman_device_enable()
2396 * but since the device is already enabled, the calls does not
2397 * propagate through to connman_technology_enabled via
2398 * connman_device_set_powered.
2400 if (err == -EALREADY)
2401 __connman_technology_enabled(type);
2403 /* if technology persistent state is offline */
2404 if (!technology->enable_persistent)
2405 __connman_device_disable(device);
2408 technology->device_list = g_slist_prepend(technology->device_list,
2414 int __connman_technology_remove_device(struct connman_device *device)
2416 struct connman_technology *technology;
2417 enum connman_service_type type;
2419 DBG("device %p", device);
2421 type = __connman_device_get_service_type(device);
2423 technology = technology_find(type);
2425 techless_device_list = g_slist_remove(techless_device_list,
2430 technology->device_list = g_slist_remove(technology->device_list,
2433 if (technology->tethering)
2434 set_tethering(technology, false);
2436 technology_put(technology);
2441 int __connman_technology_enabled(enum connman_service_type type)
2443 struct connman_technology *technology;
2445 technology = technology_find(type);
2449 DBG("technology %p type %s rfkill %d enabled %d", technology,
2450 get_name(type), technology->rfkill_driven,
2451 technology->enabled);
2452 #if !defined TIZEN_EXT
2453 if (technology->rfkill_driven) {
2454 if (technology->tethering_persistent)
2455 enable_tethering(technology);
2460 return technology_enabled(technology);
2463 int __connman_technology_disabled(enum connman_service_type type)
2465 struct connman_technology *technology;
2468 technology = technology_find(type);
2471 #if !defined TIZEN_EXT
2472 if (technology->rfkill_driven)
2475 for (list = technology->device_list; list; list = list->next) {
2476 struct connman_device *device = list->data;
2478 if (connman_device_get_powered(device))
2482 return technology_disabled(technology);
2485 int __connman_technology_set_offlinemode(bool offlinemode)
2488 int err = -EINVAL, enabled_tech_count = 0;
2490 if (global_offlinemode == offlinemode)
2493 DBG("offlinemode %s", offlinemode ? "On" : "Off");
2496 * This is a bit tricky. When you set offlinemode, there is no
2497 * way to differentiate between attempting offline mode and
2498 * resuming offlinemode from last saved profile. We need that
2499 * information in rfkill_update, otherwise it falls back on the
2500 * technology's persistent state. Hence we set the offline mode here
2501 * but save it & call the notifier only if its successful.
2504 global_offlinemode = offlinemode;
2506 /* Traverse technology list, enable/disable each technology. */
2507 for (list = technology_list; list; list = list->next) {
2508 struct connman_technology *technology = list->data;
2511 err = technology_disable(technology);
2513 if (technology->hardblocked)
2516 if (technology->enable_persistent) {
2517 err = technology_enable(technology);
2518 enabled_tech_count++;
2523 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
2524 (err == -EINVAL && enabled_tech_count == 0)) {
2525 connman_technology_save_offlinemode();
2526 __connman_notifier_offlinemode(offlinemode);
2528 global_offlinemode = connman_technology_load_offlinemode();
2533 #if defined TIZEN_EXT_WIFI_MESH
2534 static gboolean __add_ethernet_to_bridge(gpointer data)
2537 __connman_mesh_add_ethernet_to_bridge();
2542 void __connman_technology_set_connected(enum connman_service_type type,
2545 struct connman_technology *technology;
2548 technology = technology_find(type);
2552 DBG("technology %p connected %d", technology, connected);
2554 technology->connected = connected;
2556 #if defined TIZEN_EXT_WIFI_MESH
2557 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
2558 g_idle_add(__add_ethernet_to_bridge, NULL);
2562 connman_dbus_property_changed_basic(technology->path,
2563 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
2564 DBUS_TYPE_BOOLEAN, &val);
2567 static bool technology_apply_rfkill_change(struct connman_technology *technology,
2572 bool hardblock_changed = false;
2574 GList *start, *list;
2576 DBG("technology %p --> %d/%d vs %d/%d",
2577 technology, softblock, hardblock,
2578 technology->softblocked, technology->hardblocked);
2580 if (technology->hardblocked == hardblock)
2581 goto softblock_change;
2583 if (!(new_rfkill && !hardblock)) {
2584 start = g_hash_table_get_values(rfkill_list);
2586 for (list = start; list; list = list->next) {
2587 struct connman_rfkill *rfkill = list->data;
2589 if (rfkill->type != technology->type)
2592 if (rfkill->hardblock != hardblock)
2600 goto softblock_change;
2602 technology->hardblocked = hardblock;
2603 hardblock_changed = true;
2606 if (!apply && technology->softblocked != softblock)
2610 return technology->hardblocked;
2612 technology->softblocked = softblock;
2614 if (technology->hardblocked ||
2615 technology->softblocked) {
2616 if (technology_disabled(technology) != -EALREADY)
2617 technology_affect_devices(technology, false);
2618 } else if (!technology->hardblocked &&
2619 !technology->softblocked) {
2620 if (technology_enabled(technology) != -EALREADY)
2621 technology_affect_devices(technology, true);
2624 if (hardblock_changed) {
2625 if (technology->hardblocked) {
2626 DBG("%s is switched off.", get_name(technology->type));
2627 technology_dbus_unregister(technology);
2629 DBG("%s is switched on.", get_name(technology->type));
2630 technology_dbus_register(technology);
2632 if (global_offlinemode)
2633 __connman_rfkill_block(technology->type, true);
2637 return technology->hardblocked;
2640 int __connman_technology_add_rfkill(unsigned int index,
2641 enum connman_service_type type,
2645 struct connman_technology *technology;
2646 struct connman_rfkill *rfkill;
2648 DBG("index %u type %d soft %u hard %u", index, type,
2649 softblock, hardblock);
2651 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2655 rfkill = g_try_new0(struct connman_rfkill, 1);
2659 rfkill->index = index;
2660 rfkill->type = type;
2661 rfkill->softblock = softblock;
2662 rfkill->hardblock = hardblock;
2664 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
2667 #if defined TIZEN_EXT
2668 /* Fix Svace Issue [WGID: 1348]. */
2671 technology = technology_get(type);
2672 /* If there is no driver for this type, ignore it. */
2676 technology->rfkill_driven = true;
2678 #if !defined TIZEN_EXT
2679 /* If hardblocked, there is no need to handle softblocked state */
2680 if (technology_apply_rfkill_change(technology,
2681 softblock, hardblock, true))
2684 if (global_offlinemode)
2688 * Depending on softblocked state we unblock/block according to
2689 * offlinemode and persistente state.
2691 if (technology->softblocked &&
2692 technology->enable_persistent)
2693 return __connman_rfkill_block(type, false);
2694 else if (!technology->softblocked &&
2695 !technology->enable_persistent)
2696 return __connman_rfkill_block(type, true);
2701 int __connman_technology_update_rfkill(unsigned int index,
2702 enum connman_service_type type,
2706 struct connman_technology *technology;
2707 struct connman_rfkill *rfkill;
2709 DBG("index %u soft %u hard %u", index, softblock, hardblock);
2711 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2715 if (rfkill->softblock == softblock &&
2716 rfkill->hardblock == hardblock)
2719 rfkill->softblock = softblock;
2720 rfkill->hardblock = hardblock;
2722 technology = technology_find(type);
2723 /* If there is no driver for this type, ignore it. */
2727 technology_apply_rfkill_change(technology, softblock, hardblock,
2730 if (technology->hardblocked)
2731 DBG("%s hardblocked", get_name(technology->type));
2733 DBG("%s is%s softblocked", get_name(technology->type),
2734 technology->softblocked ? "" : " not");
2739 int __connman_technology_remove_rfkill(unsigned int index,
2740 enum connman_service_type type)
2742 struct connman_technology *technology;
2743 struct connman_rfkill *rfkill;
2745 DBG("index %u", index);
2747 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2751 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
2753 technology = technology_find(type);
2757 technology_apply_rfkill_change(technology,
2758 technology->softblocked, !technology->hardblocked, false);
2760 technology_put(technology);
2765 int __connman_technology_init(void)
2769 connection = connman_dbus_get_connection();
2771 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2774 global_offlinemode = connman_technology_load_offlinemode();
2776 /* This will create settings file if it is missing */
2777 connman_technology_save_offlinemode();
2782 void __connman_technology_cleanup(void)
2786 while (technology_list) {
2787 struct connman_technology *technology = technology_list->data;
2788 technology_list = g_slist_remove(technology_list, technology);
2789 technology_put(technology);
2792 g_hash_table_destroy(rfkill_list);
2794 dbus_connection_unref(connection);