5 * Copyright (C) 2007-2014 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
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <net/ethernet.h>
34 #include <linux/wireless.h>
37 #define IFF_LOWER_UP 0x10000
40 #include <dbus/dbus.h>
43 #define CONNMAN_API_SUBJECT_TO_CHANGE
44 #include <connman/plugin.h>
45 #include <connman/inet.h>
46 #include <connman/device.h>
47 #include <connman/rtnl.h>
48 #include <connman/technology.h>
49 #include <connman/service.h>
50 #include <connman/peer.h>
51 #include <connman/log.h>
52 #include <connman/option.h>
53 #include <connman/storage.h>
54 #include <include/setting.h>
55 #include <connman/provision.h>
56 #include <connman/utsname.h>
57 #include <connman/machine.h>
58 #include <connman/tethering.h>
60 #include <gsupplicant/gsupplicant.h>
62 #define CLEANUP_TIMEOUT 8 /* in seconds */
63 #define INACTIVE_TIMEOUT 12 /* in seconds */
64 #define FAVORITE_MAXIMUM_RETRIES 2
66 #define BGSCAN_DEFAULT "simple:30:-45:300"
67 #define AUTOSCAN_EXPONENTIAL "exponential:3:300"
68 #define AUTOSCAN_SINGLE "single:3"
70 #define P2P_FIND_TIMEOUT 30
71 #define P2P_CONNECTION_TIMEOUT 100
72 #define P2P_LISTEN_PERIOD 500
73 #define P2P_LISTEN_INTERVAL 2000
75 #define ASSOC_STATUS_NO_CLIENT 17
77 #define LOAD_SHAPING_MAX_RETRIES 7
79 #define LOAD_SHAPING_MAX_RETRIES 3
83 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
86 static struct connman_technology *wifi_technology = NULL;
87 static struct connman_technology *p2p_technology = NULL;
89 enum wifi_ap_capability{
91 WIFI_AP_SUPPORTED = 1,
92 WIFI_AP_NOT_SUPPORTED = 2,
95 enum wifi_scanning_type {
96 WIFI_SCANNING_UNKNOWN = 0,
97 WIFI_SCANNING_PASSIVE = 1,
98 WIFI_SCANNING_ACTIVE = 2,
101 struct hidden_params {
103 unsigned int ssid_len;
105 char *anonymous_identity;
107 char *altsubject_match;
108 char *domain_suffix_match;
112 GSupplicantScanParams *scan_params;
117 * Used for autoscan "emulation".
118 * Should be removed when wpa_s autoscan support will be by default.
120 struct autoscan_params {
124 unsigned int timeout;
127 struct wifi_tethering_info {
128 struct wifi_data *wifi;
129 struct connman_technology *technology;
131 GSupplicantSSID *ssid;
136 struct connman_device *device;
137 struct connman_network *network;
138 struct connman_network *pending_network;
140 GSupplicantInterface *interface;
141 GSupplicantState state;
145 enum wifi_ap_capability ap_supported;
147 bool interface_ready;
153 int load_shaping_retries;
154 struct hidden_params *hidden;
155 bool postpone_hidden;
156 struct wifi_tethering_info *tethering_param;
158 * autoscan "emulation".
160 struct autoscan_params *autoscan;
161 enum wifi_scanning_type scanning_type;
162 GSupplicantScanParams *scan_params;
163 unsigned int p2p_find_timeout;
164 unsigned int p2p_connection_timeout;
165 struct connman_peer *pending_peer;
170 #if defined TIZEN_EXT
171 int assoc_retry_count;
172 struct connman_network *scan_pending_network;
173 bool allow_full_scan;
174 unsigned int automaxspeed_timeout;
175 GSupplicantScanParams *hidden_scan_params;
179 #if defined TIZEN_EXT_WIFI_MESH
181 struct wifi_mesh_info *mesh_info;
185 #if defined TIZEN_EXT
189 #define TIZEN_ASSOC_RETRY_COUNT 4
191 static gboolean wifi_first_scan = false;
192 static gboolean found_with_first_scan = false;
193 static gboolean is_wifi_notifier_registered = false;
194 static GHashTable *failed_bssids = NULL;
195 static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
199 static GList *iface_list = NULL;
201 static GList *pending_wifi_device = NULL;
202 static GList *p2p_iface_list = NULL;
203 static bool wfd_service_registered = false;
205 static void start_autoscan(struct connman_device *device);
206 static int tech_set_tethering(struct connman_technology *technology,
207 const char *identifier, const char *passphrase,
208 const char *bridge, bool enabled);
210 #if defined TIZEN_EXT
211 #define NETCONFIG_SERVICE "net.netconfig"
212 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
213 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
215 struct enc_method_call_data {
216 DBusConnection *connection;
217 struct connman_network *network;
220 static struct enc_method_call_data encrypt_request_data;
222 static void encryption_request_reply(DBusPendingCall *call,
227 DBusMessageIter args;
229 struct connman_service *service;
230 gchar* encrypted_value = NULL;
231 struct connman_network *network = encrypt_request_data.network;
235 reply = dbus_pending_call_steal_reply(call);
237 dbus_error_init(&error);
238 if (dbus_set_error_from_message(&error, reply)) {
239 DBG("send_encryption_request() %s %s", error.name, error.message);
240 dbus_error_free(&error);
244 if (dbus_message_iter_init(reply, &args) == FALSE)
247 dbus_message_iter_get_basic(&args, &out_data);
249 encrypted_value = g_strdup((const gchar *)out_data);
250 service = connman_service_lookup_from_network(network);
253 DBG("encryption result: no service");
257 if (connman_service_get_favorite(service)) {
258 __connman_service_set_passphrase(service, encrypted_value);
259 __connman_service_save(service);
261 connman_network_set_string(network, "WiFi.Passphrase",
264 DBG("encryption result: succeeded");
267 dbus_message_unref(reply);
268 dbus_pending_call_unref(call);
269 dbus_connection_unref(encrypt_request_data.connection);
270 g_free(encrypted_value);
272 encrypt_request_data.connection = NULL;
273 encrypt_request_data.network = NULL;
276 static int send_encryption_request(const char *passphrase,
277 struct connman_network *network)
279 DBusConnection *connection = NULL;
280 DBusMessage *msg = NULL;
281 DBusPendingCall *call;
284 DBG("Invalid parameter");
288 connection = connman_dbus_get_connection();
290 DBG("dbus connection does not exist");
294 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
295 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
297 dbus_connection_unref(connection);
301 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
304 if (!dbus_connection_send_with_reply(connection, msg,
305 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
306 dbus_message_unref(msg);
307 dbus_connection_unref(connection);
312 dbus_message_unref(msg);
313 dbus_connection_unref(connection);
317 encrypt_request_data.connection = connection;
318 encrypt_request_data.network = network;
320 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
321 dbus_message_unref(msg);
327 static int p2p_tech_probe(struct connman_technology *technology)
329 p2p_technology = technology;
334 static void p2p_tech_remove(struct connman_technology *technology)
336 p2p_technology = NULL;
339 static struct connman_technology_driver p2p_tech_driver = {
341 .type = CONNMAN_SERVICE_TYPE_P2P,
342 .probe = p2p_tech_probe,
343 .remove = p2p_tech_remove,
346 static bool is_p2p_connecting(void)
350 for (list = iface_list; list; list = list->next) {
351 struct wifi_data *wifi = list->data;
353 if (wifi->p2p_connecting)
360 static void add_pending_wifi_device(struct wifi_data *wifi)
362 if (g_list_find(pending_wifi_device, wifi))
365 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
368 #if defined TIZEN_EXT_WIFI_MESH
369 struct wifi_mesh_info {
370 struct wifi_data *wifi;
371 GSupplicantInterface *interface;
372 struct connman_mesh *mesh;
379 struct mesh_change_peer_status_info {
381 enum connman_mesh_peer_status peer_status;
382 mesh_change_peer_status_cb_t callback;
386 static struct connman_technology_driver mesh_tech_driver = {
388 .type = CONNMAN_SERVICE_TYPE_MESH,
391 static void mesh_interface_create_callback(int result,
392 GSupplicantInterface *interface,
395 struct wifi_mesh_info *mesh_info = user_data;
396 struct wifi_data *wifi;
397 bool success = false;
399 DBG("result %d ifname %s, mesh_info %p", result,
400 g_supplicant_interface_get_ifname(interface),
403 if (result < 0 || !mesh_info)
406 wifi = mesh_info->wifi;
408 mesh_info->interface = interface;
409 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
410 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
411 DBG("Mesh Interface identifier %s", mesh_info->identifier);
412 wifi->mesh_interface = true;
413 wifi->mesh_info = mesh_info;
414 g_supplicant_interface_set_data(interface, wifi);
418 connman_mesh_notify_interface_create(success);
421 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
424 struct wifi_data *wifi;
425 struct wifi_mesh_info *mesh_info;
426 const char *wifi_ifname;
427 bool parent_found = false;
428 const char *driver = "nl80211";
430 for (list = iface_list; list; list = list->next) {
433 if (!g_supplicant_interface_has_mesh(wifi->interface))
436 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
440 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
447 DBG("Parent interface %s doesn't exist", parent_ifname);
451 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
455 mesh_info->wifi = wifi;
456 mesh_info->ifname = g_strdup(ifname);
457 mesh_info->parent_ifname = g_strdup(parent_ifname);
459 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
460 mesh_interface_create_callback, mesh_info);
464 static void mesh_interface_remove_callback(int result,
465 GSupplicantInterface *interface,
468 struct wifi_data *wifi = user_data;
469 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
470 bool success = false;
472 DBG("result %d mesh_info %p", result, mesh_info);
474 if (result < 0 || !mesh_info)
477 mesh_info->interface = NULL;
478 g_free(mesh_info->parent_ifname);
479 g_free(mesh_info->ifname);
480 g_free(mesh_info->identifier);
482 wifi->mesh_interface = false;
483 wifi->mesh_info = NULL;
487 connman_mesh_notify_interface_remove(success);
490 static int remove_mesh_interface(const char *ifname)
493 struct wifi_data *wifi;
494 struct wifi_mesh_info *mesh_info;
495 bool mesh_if_found = false;
498 for (list = iface_list; list; list = list->next) {
501 if (wifi->mesh_interface) {
502 mesh_if_found = true;
507 if (!mesh_if_found) {
508 DBG("Mesh interface %s doesn't exist", ifname);
512 mesh_info = wifi->mesh_info;
513 ret = g_supplicant_interface_remove(mesh_info->interface,
514 mesh_interface_remove_callback, wifi);
521 static void mesh_disconnect_callback(int result,
522 GSupplicantInterface *interface, void *user_data)
524 struct connman_mesh *mesh = user_data;
526 DBG("result %d interface %p mesh %p", result, interface, mesh);
529 static int mesh_peer_disconnect(struct connman_mesh *mesh)
532 struct wifi_data *wifi;
533 struct wifi_mesh_info *mesh_info;
534 bool mesh_if_found = false;
535 GSupplicantInterface *interface;
537 for (list = iface_list; list; list = list->next) {
540 if (wifi->mesh_interface) {
541 mesh_if_found = true;
546 if (!mesh_if_found) {
547 DBG("Mesh interface is not created");
551 mesh_info = wifi->mesh_info;
553 interface = mesh_info->interface;
554 return g_supplicant_interface_disconnect(interface,
555 mesh_disconnect_callback, mesh);
558 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
561 struct connman_mesh *mesh = user_data;
562 DBG("mesh %p result %d", mesh, result);
565 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
567 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
570 static GSupplicantSecurity mesh_network_security(const char *security)
572 if (g_str_equal(security, "none"))
573 return G_SUPPLICANT_SECURITY_NONE;
574 else if (g_str_equal(security, "sae"))
575 return G_SUPPLICANT_SECURITY_SAE;
577 return G_SUPPLICANT_SECURITY_UNKNOWN;
580 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
583 const char *security;
588 memset(ssid, 0, sizeof(*ssid));
589 ssid->mode = G_SUPPLICANT_MODE_MESH;
591 security = connman_mesh_get_security(mesh);
592 ssid->security = mesh_network_security(security);
594 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
595 ssid->passphrase = connman_mesh_get_passphrase(mesh);
597 ssid->freq = connman_mesh_get_frequency(mesh);
598 name = connman_mesh_get_name(mesh);
600 ssid->ssid_len = strlen(name);
601 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
602 memcpy(ssid->ssid, name, ssid->ssid_len);
607 static int mesh_peer_connect(struct connman_mesh *mesh)
610 struct wifi_data *wifi;
611 struct wifi_mesh_info *mesh_info;
612 bool mesh_if_found = false;
613 GSupplicantInterface *interface;
614 GSupplicantSSID *ssid;
616 for (list = iface_list; list; list = list->next) {
619 if (wifi->mesh_interface) {
620 mesh_if_found = true;
625 if (!mesh_if_found) {
626 DBG("Mesh interface is not created");
630 mesh_info = wifi->mesh_info;
632 interface = mesh_info->interface;
634 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
638 mesh_info->mesh = mesh;
640 mesh_ssid_init(ssid, mesh);
641 return g_supplicant_interface_connect(interface, ssid,
642 mesh_connect_callback, mesh);
645 static void mesh_peer_change_status_callback(int result,
646 GSupplicantInterface *interface,
649 struct mesh_change_peer_status_info *data = user_data;
651 DBG("result %d Peer Status %d", result, data->peer_status);
653 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
654 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
655 connman_mesh_remove_connected_peer(data->peer_address, 52);
659 data->callback(result, data->user_data);
661 g_free(data->peer_address);
666 static int mesh_change_peer_status(const char *peer_address,
667 enum connman_mesh_peer_status status,
668 mesh_change_peer_status_cb_t callback, void *user_data)
671 struct wifi_data *wifi;
672 struct wifi_mesh_info *mesh_info;
673 bool mesh_if_found = false;
674 GSupplicantInterface *interface;
675 struct mesh_change_peer_status_info *data;
678 for (list = iface_list; list; list = list->next) {
681 if (wifi->mesh_interface) {
682 mesh_if_found = true;
687 if (!mesh_if_found) {
688 DBG("Mesh interface is not created");
692 mesh_info = wifi->mesh_info;
694 interface = mesh_info->interface;
697 case CONNMAN_MESH_PEER_ADD:
698 method = "MeshPeerAdd";
700 case CONNMAN_MESH_PEER_REMOVE:
701 method = "MeshPeerRemove";
704 DBG("Invalid method");
708 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
710 DBG("Memory allocation failed");
714 data->peer_address = g_strdup(peer_address);
715 data->peer_status = status;
716 data->callback = callback;
717 data->user_data = user_data;
719 return g_supplicant_interface_mesh_peer_change_status(interface,
720 mesh_peer_change_status_callback, peer_address, method,
724 static struct connman_mesh_driver mesh_driver = {
725 .add_interface = add_mesh_interface,
726 .remove_interface = remove_mesh_interface,
727 .connect = mesh_peer_connect,
728 .disconnect = mesh_peer_disconnect,
729 .change_peer_status = mesh_change_peer_status,
732 static void mesh_support(GSupplicantInterface *interface)
736 if (!g_supplicant_interface_has_mesh(interface))
739 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
740 DBG("Could not register Mesh technology driver");
744 connman_mesh_driver_register(&mesh_driver);
747 static void check_mesh_technology(void)
749 bool mesh_exists = false;
752 for (list = iface_list; list; list = list->next) {
753 struct wifi_data *w = list->data;
756 g_supplicant_interface_has_mesh(w->interface))
761 connman_technology_driver_unregister(&mesh_tech_driver);
762 connman_mesh_driver_unregister(&mesh_driver);
766 static void mesh_group_started(GSupplicantInterface *interface)
768 struct wifi_data *wifi;
769 struct wifi_mesh_info *mesh_info;
770 struct connman_mesh *mesh;
771 const unsigned char *ssid;
772 unsigned int ssid_len;
775 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
776 memcpy(name, ssid, ssid_len);
777 name[ssid_len] = '\0';
778 DBG("name %s", name);
779 wifi = g_supplicant_interface_get_data(interface);
780 DBG("wifi %p", wifi);
785 mesh_info = wifi->mesh_info;
789 mesh = mesh_info->mesh;
793 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
796 static void mesh_group_removed(GSupplicantInterface *interface)
798 struct wifi_data *wifi;
799 struct wifi_mesh_info *mesh_info;
800 struct connman_mesh *mesh;
801 const unsigned char *ssid;
802 unsigned int ssid_len;
803 int disconnect_reason;
806 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
807 memcpy(name, ssid, ssid_len);
808 name[ssid_len] = '\0';
809 DBG("name %s", name);
811 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
812 DBG("Disconnect Reason %d", disconnect_reason);
814 wifi = g_supplicant_interface_get_data(interface);
815 DBG("wifi %p", wifi);
820 mesh_info = wifi->mesh_info;
824 mesh = connman_get_connected_mesh_from_name(name);
826 DBG("%s is not connected", name);
827 mesh = connman_get_connecting_mesh_from_name(name);
829 DBG("%s is not connecting", name);
834 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
835 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
838 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
840 const char *peer_address;
842 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
847 DBG("Peer %s connected", peer_address);
848 connman_mesh_add_connected_peer(peer_address);
851 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
853 const char *peer_address;
856 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
861 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
863 DBG("Peer %s disconnected with reason %d", peer_address, reason);
864 connman_mesh_remove_connected_peer(peer_address, reason);
868 static struct wifi_data *get_pending_wifi_data(const char *ifname)
872 for (list = pending_wifi_device; list; list = list->next) {
873 struct wifi_data *wifi;
874 const char *dev_name;
877 if (!wifi || !wifi->device)
880 dev_name = connman_device_get_string(wifi->device, "Interface");
881 if (!g_strcmp0(ifname, dev_name)) {
882 pending_wifi_device = g_list_delete_link(
883 pending_wifi_device, list);
891 static void remove_pending_wifi_device(struct wifi_data *wifi)
895 link = g_list_find(pending_wifi_device, wifi);
900 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
903 static void peer_cancel_timeout(struct wifi_data *wifi)
905 if (wifi->p2p_connection_timeout > 0)
906 g_source_remove(wifi->p2p_connection_timeout);
908 wifi->p2p_connection_timeout = 0;
909 wifi->p2p_connecting = false;
911 if (wifi->pending_peer) {
912 connman_peer_unref(wifi->pending_peer);
913 wifi->pending_peer = NULL;
917 static gboolean peer_connect_timeout(gpointer data)
919 struct wifi_data *wifi = data;
923 if (wifi->p2p_connecting) {
924 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
925 GSupplicantPeer *gs_peer =
926 g_supplicant_interface_peer_lookup(wifi->interface,
927 connman_peer_get_identifier(wifi->pending_peer));
929 if (g_supplicant_peer_has_requested_connection(gs_peer))
930 state = CONNMAN_PEER_STATE_IDLE;
932 connman_peer_set_state(wifi->pending_peer, state);
935 peer_cancel_timeout(wifi);
940 static void peer_connect_callback(int result, GSupplicantInterface *interface,
943 struct wifi_data *wifi = user_data;
944 struct connman_peer *peer = wifi->pending_peer;
946 DBG("peer %p - %d", peer, result);
952 peer_connect_timeout(wifi);
956 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
958 wifi->p2p_connection_timeout = g_timeout_add_seconds(
959 P2P_CONNECTION_TIMEOUT,
960 peer_connect_timeout, wifi);
963 static int peer_connect(struct connman_peer *peer,
964 enum connman_peer_wps_method wps_method,
967 struct connman_device *device = connman_peer_get_device(peer);
968 GSupplicantPeerParams *peer_params;
969 GSupplicantPeer *gs_peer;
970 struct wifi_data *wifi;
974 DBG("peer %p", peer);
979 wifi = connman_device_get_data(device);
980 if (!wifi || !wifi->interface)
983 if (wifi->p2p_connecting)
986 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
987 connman_peer_get_identifier(peer));
991 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
992 pin = g_supplicant_peer_is_wps_pin(gs_peer);
994 switch (wps_method) {
995 case CONNMAN_PEER_WPS_UNKNOWN:
996 if ((pbc && pin) || pin)
999 case CONNMAN_PEER_WPS_PBC:
1004 case CONNMAN_PEER_WPS_PIN:
1005 if (!pin || !wps_pin)
1010 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1014 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1016 peer_params->wps_pin = g_strdup(wps_pin);
1018 peer_params->master = connman_peer_service_is_master();
1020 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1021 peer_connect_callback, wifi);
1022 if (ret == -EINPROGRESS) {
1023 wifi->pending_peer = connman_peer_ref(peer);
1024 wifi->p2p_connecting = true;
1025 } else if (ret < 0) {
1026 g_free(peer_params->path);
1027 g_free(peer_params->wps_pin);
1028 g_free(peer_params);
1034 static int peer_disconnect(struct connman_peer *peer)
1036 struct connman_device *device = connman_peer_get_device(peer);
1037 GSupplicantPeerParams peer_params = {};
1038 GSupplicantPeer *gs_peer;
1039 struct wifi_data *wifi;
1042 DBG("peer %p", peer);
1047 wifi = connman_device_get_data(device);
1051 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1052 connman_peer_get_identifier(peer));
1056 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1058 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1060 g_free(peer_params.path);
1062 if (ret == -EINPROGRESS) {
1063 peer_cancel_timeout(wifi);
1064 wifi->p2p_device = false;
1070 struct peer_service_registration {
1071 peer_service_registration_cb_t callback;
1075 static bool is_service_wfd(const unsigned char *specs, int length)
1077 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1083 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1085 struct wifi_data *wifi = data;
1087 if (!wifi->interface ||
1088 !g_supplicant_interface_has_p2p(wifi->interface))
1091 if (!wifi->servicing) {
1092 g_supplicant_interface_p2p_listen(wifi->interface,
1093 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1099 static void register_wfd_service_cb(int result,
1100 GSupplicantInterface *iface, void *user_data)
1102 struct peer_service_registration *reg_data = user_data;
1107 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1109 if (reg_data && reg_data->callback) {
1110 reg_data->callback(result, reg_data->user_data);
1115 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1116 const unsigned char *spec,
1117 int spec_length, const unsigned char *query,
1118 int query_length, int version)
1120 GSupplicantP2PServiceParams *params;
1122 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1127 params->version = version;
1128 params->service = g_memdup(spec, spec_length);
1129 } else if (query_length > 0 && spec_length > 0) {
1130 params->query = g_memdup(query, query_length);
1131 params->query_length = query_length;
1133 params->response = g_memdup(spec, spec_length);
1134 params->response_length = spec_length;
1136 params->wfd_ies = g_memdup(spec, spec_length);
1137 params->wfd_ies_length = spec_length;
1143 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1148 g_free(params->service);
1149 g_free(params->query);
1150 g_free(params->response);
1151 g_free(params->wfd_ies);
1156 static int peer_register_wfd_service(const unsigned char *specification,
1157 int specification_length,
1158 peer_service_registration_cb_t callback,
1161 struct peer_service_registration *reg_data = NULL;
1162 static GSupplicantP2PServiceParams *params;
1167 if (wfd_service_registered)
1170 params = fill_in_peer_service_params(specification,
1171 specification_length, NULL, 0, 0);
1175 reg_data = g_try_malloc0(sizeof(*reg_data));
1181 reg_data->callback = callback;
1182 reg_data->user_data = user_data;
1184 ret = g_supplicant_set_widi_ies(params,
1185 register_wfd_service_cb, reg_data);
1186 if (ret < 0 && ret != -EINPROGRESS)
1189 wfd_service_registered = true;
1193 free_peer_service_params(params);
1199 static void register_peer_service_cb(int result,
1200 GSupplicantInterface *iface, void *user_data)
1202 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1203 struct peer_service_registration *reg_data = user_data;
1205 #if defined TIZEN_EXT
1213 apply_p2p_listen_on_iface(wifi, NULL);
1215 if (reg_data->callback)
1216 reg_data->callback(result, reg_data->user_data);
1221 static int peer_register_service(const unsigned char *specification,
1222 int specification_length,
1223 const unsigned char *query,
1224 int query_length, int version,
1225 peer_service_registration_cb_t callback,
1228 struct peer_service_registration *reg_data;
1229 GSupplicantP2PServiceParams *params;
1236 if (specification && !version && !query &&
1237 is_service_wfd(specification, specification_length)) {
1238 return peer_register_wfd_service(specification,
1239 specification_length, callback, user_data);
1242 reg_data = g_try_malloc0(sizeof(*reg_data));
1246 reg_data->callback = callback;
1247 reg_data->user_data = user_data;
1249 ret_f = -EOPNOTSUPP;
1251 for (list = iface_list; list; list = list->next) {
1252 struct wifi_data *wifi = list->data;
1253 GSupplicantInterface *iface = wifi->interface;
1255 if (!g_supplicant_interface_has_p2p(iface))
1258 params = fill_in_peer_service_params(specification,
1259 specification_length, query,
1260 query_length, version);
1265 ret_f = g_supplicant_interface_p2p_add_service(iface,
1266 register_peer_service_cb, params, reg_data);
1267 if (ret_f == 0 || ret_f == -EINPROGRESS)
1271 ret = g_supplicant_interface_p2p_add_service(iface,
1272 register_peer_service_cb, params, NULL);
1273 if (ret != 0 && ret != -EINPROGRESS)
1274 free_peer_service_params(params);
1277 if (ret_f != 0 && ret_f != -EINPROGRESS)
1283 static int peer_unregister_wfd_service(void)
1285 GSupplicantP2PServiceParams *params;
1288 if (!wfd_service_registered)
1291 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1295 wfd_service_registered = false;
1297 g_supplicant_set_widi_ies(params, NULL, NULL);
1299 for (list = iface_list; list; list = list->next) {
1300 struct wifi_data *wifi = list->data;
1302 if (!g_supplicant_interface_has_p2p(wifi->interface))
1306 if (!wifi->servicing || wifi->servicing < 0) {
1307 g_supplicant_interface_p2p_listen(wifi->interface,
1309 wifi->servicing = 0;
1316 static int peer_unregister_service(const unsigned char *specification,
1317 int specification_length,
1318 const unsigned char *query,
1319 int query_length, int version)
1321 GSupplicantP2PServiceParams *params;
1326 if (specification && !version && !query &&
1327 is_service_wfd(specification, specification_length)) {
1328 ret = peer_unregister_wfd_service();
1329 if (ret != 0 && ret != -EINPROGRESS)
1334 for (list = iface_list; list; list = list->next) {
1335 struct wifi_data *wifi = list->data;
1336 GSupplicantInterface *iface = wifi->interface;
1339 goto stop_listening;
1341 if (!g_supplicant_interface_has_p2p(iface))
1344 params = fill_in_peer_service_params(specification,
1345 specification_length, query,
1346 query_length, version);
1350 ret = g_supplicant_interface_p2p_del_service(iface, params);
1351 if (ret != 0 && ret != -EINPROGRESS)
1352 free_peer_service_params(params);
1355 if (!wifi->servicing || wifi->servicing < 0) {
1356 g_supplicant_interface_p2p_listen(iface, 0, 0);
1357 wifi->servicing = 0;
1364 static struct connman_peer_driver peer_driver = {
1365 .connect = peer_connect,
1366 .disconnect = peer_disconnect,
1367 .register_service = peer_register_service,
1368 .unregister_service = peer_unregister_service,
1371 static void handle_tethering(struct wifi_data *wifi)
1373 if (!wifi->tethering)
1382 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1384 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1387 wifi->bridged = true;
1390 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1392 struct connman_device *device = user_data;
1393 struct wifi_data *wifi = connman_device_get_data(device);
1398 DBG("index %d flags %d change %d", wifi->index, flags, change);
1400 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1402 DBG("interface up");
1404 DBG("interface down");
1407 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1408 if (flags & IFF_LOWER_UP) {
1411 handle_tethering(wifi);
1416 wifi->flags = flags;
1419 static int wifi_probe(struct connman_device *device)
1421 struct wifi_data *wifi;
1423 DBG("device %p", device);
1425 wifi = g_try_new0(struct wifi_data, 1);
1429 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1430 wifi->ap_supported = WIFI_AP_UNKNOWN;
1431 wifi->tethering_param = NULL;
1433 connman_device_set_data(device, wifi);
1434 wifi->device = connman_device_ref(device);
1436 wifi->index = connman_device_get_index(device);
1439 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1440 wifi_newlink, device);
1441 if (is_p2p_connecting())
1442 add_pending_wifi_device(wifi);
1444 iface_list = g_list_append(iface_list, wifi);
1449 static void remove_networks(struct connman_device *device,
1450 struct wifi_data *wifi)
1454 for (list = wifi->networks; list; list = list->next) {
1455 struct connman_network *network = list->data;
1457 connman_device_remove_network(device, network);
1458 connman_network_unref(network);
1461 g_slist_free(wifi->networks);
1462 wifi->networks = NULL;
1465 static void remove_peers(struct wifi_data *wifi)
1469 for (list = wifi->peers; list; list = list->next) {
1470 struct connman_peer *peer = list->data;
1472 connman_peer_unregister(peer);
1473 connman_peer_unref(peer);
1476 g_slist_free(wifi->peers);
1480 static void reset_autoscan(struct connman_device *device)
1482 struct wifi_data *wifi = connman_device_get_data(device);
1483 struct autoscan_params *autoscan;
1487 if (!wifi || !wifi->autoscan)
1490 autoscan = wifi->autoscan;
1492 autoscan->interval = 0;
1494 if (autoscan->timeout == 0)
1497 g_source_remove(autoscan->timeout);
1498 autoscan->timeout = 0;
1500 connman_device_unref(device);
1503 static void stop_autoscan(struct connman_device *device)
1505 const struct wifi_data *wifi = connman_device_get_data(device);
1507 if (!wifi || !wifi->autoscan)
1510 reset_autoscan(device);
1512 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1515 static void check_p2p_technology(void)
1517 bool p2p_exists = false;
1520 for (list = iface_list; list; list = list->next) {
1521 struct wifi_data *w = list->data;
1524 g_supplicant_interface_has_p2p(w->interface))
1529 connman_technology_driver_unregister(&p2p_tech_driver);
1530 connman_peer_driver_unregister(&peer_driver);
1534 struct last_connected {
1540 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1542 GTimeVal *aval = (GTimeVal *)a;
1543 GTimeVal *bval = (GTimeVal *)b;
1545 /* Note that the sort order is descending */
1546 if (aval->tv_sec < bval->tv_sec)
1549 if (aval->tv_sec > bval->tv_sec)
1555 static void free_entry(gpointer data)
1557 struct last_connected *entry = data;
1559 g_free(entry->ssid);
1563 static void wifi_remove(struct connman_device *device)
1565 struct wifi_data *wifi = connman_device_get_data(device);
1567 DBG("device %p wifi %p", device, wifi);
1572 stop_autoscan(device);
1574 if (wifi->p2p_device)
1575 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1577 iface_list = g_list_remove(iface_list, wifi);
1579 check_p2p_technology();
1580 #if defined TIZEN_EXT_WIFI_MESH
1581 check_mesh_technology();
1584 remove_pending_wifi_device(wifi);
1586 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
1587 g_source_remove(wifi->p2p_find_timeout);
1588 connman_device_unref(wifi->device);
1591 if (wifi->p2p_connection_timeout)
1592 g_source_remove(wifi->p2p_connection_timeout);
1594 #if defined TIZEN_EXT
1595 if (wifi->automaxspeed_timeout != 0) {
1596 g_source_remove(wifi->automaxspeed_timeout);
1597 wifi->automaxspeed_timeout = 0;
1601 remove_networks(device, wifi);
1604 connman_device_set_powered(device, false);
1605 connman_device_set_data(device, NULL);
1606 connman_device_unref(wifi->device);
1607 connman_rtnl_remove_watch(wifi->watch);
1609 g_supplicant_interface_set_data(wifi->interface, NULL);
1611 g_supplicant_interface_cancel(wifi->interface);
1613 if (wifi->scan_params)
1614 g_supplicant_free_scan_params(wifi->scan_params);
1615 #if defined TIZEN_EXT
1616 if (wifi->hidden_scan_params) {
1617 while (wifi->hidden_scan_params->ssids) {
1618 struct scan_ssid *ssid;
1619 ssid = wifi->hidden_scan_params->ssids->data;
1620 wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
1622 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1626 g_free(wifi->autoscan);
1627 g_free(wifi->identifier);
1631 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1635 for (iter = list; iter; iter = g_slist_next(iter)) {
1636 struct scan_ssid *scan_ssid = iter->data;
1638 if (ssid_len == scan_ssid->ssid_len &&
1639 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1646 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1647 int freq, GSupplicantScanParams *scan_data,
1648 int driver_max_scan_ssids, char *ssid_name)
1651 struct scan_ssid *scan_ssid;
1653 if ((driver_max_scan_ssids == 0 ||
1654 driver_max_scan_ssids > scan_data->num_ssids) &&
1655 (hex_ssid || raw_ssid)) {
1657 unsigned int j = 0, hex;
1660 size_t hex_ssid_len = strlen(hex_ssid);
1662 ssid = g_try_malloc0(hex_ssid_len / 2);
1666 for (i = 0; i < hex_ssid_len; i += 2) {
1667 sscanf(hex_ssid + i, "%02x", &hex);
1676 * If we have already added hidden AP to the list,
1677 * then do not do it again. This might happen if you have
1678 * used or are using multiple wifi cards, so in that case
1679 * you might have multiple service files for same AP.
1681 if (is_duplicate(scan_data->ssids, ssid, j)) {
1687 scan_ssid = g_try_new(struct scan_ssid, 1);
1694 memcpy(scan_ssid->ssid, ssid, j);
1695 scan_ssid->ssid_len = j;
1696 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1699 scan_data->num_ssids++;
1701 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1702 scan_data->num_ssids);
1709 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1711 if (!scan_data->freqs) {
1712 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1713 if (!scan_data->freqs) {
1714 g_slist_free_full(scan_data->ssids, g_free);
1718 scan_data->num_freqs = 1;
1719 scan_data->freqs[0] = freq;
1721 bool duplicate = false;
1723 /* Don't add duplicate entries */
1724 for (i = 0; i < scan_data->num_freqs; i++) {
1725 if (scan_data->freqs[i] == freq) {
1732 scan_data->num_freqs++;
1733 scan_data->freqs = g_try_realloc(scan_data->freqs,
1734 sizeof(uint16_t) * scan_data->num_freqs);
1735 if (!scan_data->freqs) {
1736 g_slist_free_full(scan_data->ssids, g_free);
1739 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1746 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1748 struct connman_config_entry **entries;
1750 #if defined TIZEN_EXT
1751 gchar **services = NULL;
1754 #endif /* defined TIZEN_EXT */
1758 int num_ssids = 0, add_param_failed = 0;
1759 #if defined TIZEN_EXT
1760 GSequenceIter *iter;
1761 GSequence *latest_list;
1762 struct last_connected *entry;
1765 latest_list = g_sequence_new(free_entry);
1769 services = connman_storage_get_services();
1770 for (i = 0; services && services[i]; i++) {
1771 if (strncmp(services[i], "wifi_", 5) != 0)
1774 keyfile = connman_storage_load_service(services[i]);
1778 value = g_key_file_get_boolean(keyfile,
1779 services[i], "Hidden", NULL);
1781 g_key_file_free(keyfile);
1785 value = g_key_file_get_boolean(keyfile,
1786 services[i], "Favorite", NULL);
1788 g_key_file_free(keyfile);
1792 #if defined TIZEN_EXT
1793 value = g_key_file_get_boolean(keyfile,
1794 services[i], "AutoConnect", NULL);
1796 g_key_file_free(keyfile);
1800 gchar *str = g_key_file_get_string(keyfile,
1801 services[i], "Modified", NULL);
1803 g_key_file_free(keyfile);
1806 g_time_val_from_iso8601(str, &modified);
1810 ssid = g_key_file_get_string(keyfile,
1811 services[i], "SSID", NULL);
1813 name = g_key_file_get_string(keyfile, services[i], "Name",
1816 #if defined TIZEN_EXT
1817 entry = g_try_new(struct last_connected, 1);
1819 g_sequence_free(latest_list);
1822 g_key_file_free(keyfile);
1826 entry->modified = modified;
1829 g_sequence_insert_sorted(latest_list, entry,
1832 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1841 g_key_file_free(keyfile);
1844 #if defined TIZEN_EXT
1845 gint length = g_sequence_get_length(latest_list);
1846 iter = g_sequence_get_begin_iter(latest_list);
1848 for (i = 0; i < length; i++) {
1849 entry = g_sequence_get(iter);
1851 ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid);
1857 iter = g_sequence_iter_next(iter);
1860 g_sequence_free(latest_list);
1864 * Check if there are any hidden AP that needs to be provisioned.
1866 entries = connman_config_get_entries("wifi");
1867 for (i = 0; entries && entries[i]; i++) {
1870 if (!entries[i]->hidden)
1873 if (!entries[i]->ssid) {
1874 ssid = entries[i]->name;
1877 ssid = entries[i]->ssid;
1878 len = entries[i]->ssid_len;
1884 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1891 connman_config_free_entries(entries);
1893 if (add_param_failed > 0)
1894 DBG("Unable to scan %d out of %d SSIDs",
1895 add_param_failed, num_ssids);
1897 g_strfreev(services);
1902 static int get_hidden_connections_params(struct wifi_data *wifi,
1903 GSupplicantScanParams *scan_params)
1905 int driver_max_ssids, i;
1906 GSupplicantScanParams *orig_params;
1909 * Scan hidden networks so that we can autoconnect to them.
1910 * We will assume 1 as a default number of ssid to scan.
1912 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1914 if (driver_max_ssids == 0)
1915 driver_max_ssids = 1;
1917 DBG("max ssids %d", driver_max_ssids);
1919 #if defined TIZEN_EXT
1920 if (!wifi->hidden_scan_params) {
1921 wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1922 if (!wifi->hidden_scan_params)
1925 if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
1926 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1927 wifi->hidden_scan_params = NULL;
1933 orig_params = wifi->hidden_scan_params;
1935 if (!wifi->scan_params) {
1936 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1937 if (!wifi->scan_params)
1940 if (get_hidden_connections(wifi->scan_params) == 0) {
1941 g_supplicant_free_scan_params(wifi->scan_params);
1942 wifi->scan_params = NULL;
1948 orig_params = wifi->scan_params;
1951 /* Let's transfer driver_max_ssids params */
1952 for (i = 0; i < driver_max_ssids; i++) {
1953 struct scan_ssid *ssid;
1955 #if defined TIZEN_EXT
1956 if (!wifi->hidden_scan_params->ssids)
1958 if (!wifi->scan_params->ssids)
1962 ssid = orig_params->ssids->data;
1963 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1964 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1968 scan_params->num_ssids = i;
1969 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1971 scan_params->freqs = g_memdup(orig_params->freqs,
1972 sizeof(uint16_t) * orig_params->num_freqs);
1973 if (!scan_params->freqs)
1976 scan_params->num_freqs = orig_params->num_freqs;
1981 orig_params->num_ssids -= scan_params->num_ssids;
1983 return scan_params->num_ssids;
1986 g_slist_free_full(scan_params->ssids, g_free);
1987 #if defined TIZEN_EXT
1988 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1989 wifi->hidden_scan_params = NULL;
1991 g_supplicant_free_scan_params(wifi->scan_params);
1992 wifi->scan_params = NULL;
1998 static int throw_wifi_scan(struct connman_device *device,
1999 GSupplicantInterfaceCallback callback)
2001 struct wifi_data *wifi = connman_device_get_data(device);
2007 DBG("device %p %p", device, wifi->interface);
2009 if (wifi->tethering)
2012 #if defined TIZEN_EXT
2013 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)
2014 && !wifi->allow_full_scan)
2016 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
2020 connman_device_ref(device);
2022 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2025 connman_device_set_scanning(device,
2026 CONNMAN_SERVICE_TYPE_WIFI, true);
2028 connman_device_unref(device);
2033 static void hidden_free(struct hidden_params *hidden)
2038 if (hidden->scan_params)
2039 g_supplicant_free_scan_params(hidden->scan_params);
2040 g_free(hidden->identity);
2041 g_free(hidden->passphrase);
2042 g_free(hidden->security);
2046 #if defined TIZEN_EXT
2047 static void service_state_changed(struct connman_service *service,
2048 enum connman_service_state state);
2050 static int network_connect(struct connman_network *network);
2052 static struct connman_notifier notifier = {
2054 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
2055 .service_state_changed = service_state_changed,
2058 static void service_state_changed(struct connman_service *service,
2059 enum connman_service_state state)
2061 enum connman_service_type type;
2063 type = connman_service_get_type(service);
2064 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2067 DBG("service %p state %d", service, state);
2070 case CONNMAN_SERVICE_STATE_READY:
2071 case CONNMAN_SERVICE_STATE_ONLINE:
2072 case CONNMAN_SERVICE_STATE_FAILURE:
2073 connman_notifier_unregister(¬ifier);
2074 is_wifi_notifier_registered = FALSE;
2076 __connman_device_request_scan(type);
2084 static void scan_callback_hidden(int result,
2085 GSupplicantInterface *interface, void *user_data);
2088 static void scan_callback(int result, GSupplicantInterface *interface,
2091 struct connman_device *device = user_data;
2092 struct wifi_data *wifi = connman_device_get_data(device);
2095 DBG("result %d wifi %p", result, wifi);
2098 if (wifi->hidden && !wifi->postpone_hidden) {
2099 connman_network_clear_hidden(wifi->hidden->user_data);
2100 hidden_free(wifi->hidden);
2101 wifi->hidden = NULL;
2104 if (wifi->scan_params) {
2105 g_supplicant_free_scan_params(wifi->scan_params);
2106 wifi->scan_params = NULL;
2109 #if defined TIZEN_EXT
2110 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2111 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2112 wifi->hidden_scan_params = NULL;
2118 connman_device_reset_scanning(device);
2120 /* User is connecting to a hidden AP, let's wait for finished event */
2121 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2122 GSupplicantScanParams *scan_params;
2125 wifi->postpone_hidden = false;
2126 scan_params = wifi->hidden->scan_params;
2127 wifi->hidden->scan_params = NULL;
2129 reset_autoscan(device);
2131 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2132 scan_callback, device);
2136 /* On error, let's recall scan_callback, which will cleanup */
2137 return scan_callback(ret, interface, user_data);
2140 #if defined TIZEN_EXT
2141 if (wifi && wifi->allow_full_scan) {
2143 DBG("Trigger Full Channel Scan");
2144 wifi->allow_full_scan = FALSE;
2146 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2147 scan_callback_hidden, device);
2151 /* On error, let's recall scan_callback, which will cleanup */
2152 return scan_callback(ret, interface, user_data);
2156 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
2159 connman_device_set_scanning(device,
2160 CONNMAN_SERVICE_TYPE_WIFI, false);
2163 if (result != -ENOLINK)
2164 #if defined TIZEN_EXT
2167 start_autoscan(device);
2170 * If we are here then we were scanning; however, if we are
2171 * also mid-flight disabling the interface, then wifi_disable
2172 * has already cleared the device scanning state and
2173 * unreferenced the device, obviating the need to do it here.
2177 connman_device_unref(device);
2179 #if defined TIZEN_EXT
2180 if (wifi && wifi->scan_pending_network && result != -EIO) {
2181 network_connect(wifi->scan_pending_network);
2182 wifi->scan_pending_network = NULL;
2183 connman_network_set_connecting(wifi->network);
2186 if (is_wifi_notifier_registered != true &&
2187 wifi_first_scan == true && found_with_first_scan == true) {
2188 wifi_first_scan = false;
2189 found_with_first_scan = false;
2191 connman_notifier_register(¬ifier);
2192 is_wifi_notifier_registered = true;
2197 static void scan_callback_hidden(int result,
2198 GSupplicantInterface *interface, void *user_data)
2200 struct connman_device *device = user_data;
2201 struct wifi_data *wifi = connman_device_get_data(device);
2202 GSupplicantScanParams *scan_params;
2205 DBG("result %d wifi %p", result, wifi);
2210 /* User is trying to connect to a hidden AP */
2211 if (wifi->hidden && wifi->postpone_hidden)
2214 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2218 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2219 ret = g_supplicant_interface_scan(wifi->interface,
2221 #if defined TIZEN_EXT
2224 scan_callback_hidden,
2231 g_supplicant_free_scan_params(scan_params);
2234 scan_callback(result, interface, user_data);
2237 static gboolean autoscan_timeout(gpointer data)
2239 struct connman_device *device = data;
2240 struct wifi_data *wifi = connman_device_get_data(device);
2241 struct autoscan_params *autoscan;
2247 autoscan = wifi->autoscan;
2249 if (autoscan->interval <= 0) {
2250 interval = autoscan->base;
2253 interval = autoscan->interval * autoscan->base;
2255 #if defined TIZEN_EXT
2256 if (autoscan->interval >= autoscan->limit)
2258 if (interval > autoscan->limit)
2260 interval = autoscan->limit;
2262 throw_wifi_scan(wifi->device, scan_callback_hidden);
2265 * In case BackgroundScanning is disabled, interval will reach the
2266 * limit exactly after the very first passive scanning. It allows
2267 * to ensure at most one passive scan is performed in such cases.
2269 if (!connman_setting_get_bool("BackgroundScanning") &&
2270 interval == autoscan->limit) {
2271 g_source_remove(autoscan->timeout);
2272 autoscan->timeout = 0;
2274 connman_device_unref(device);
2280 DBG("interval %d", interval);
2282 autoscan->interval = interval;
2284 autoscan->timeout = g_timeout_add_seconds(interval,
2285 autoscan_timeout, device);
2290 static void start_autoscan(struct connman_device *device)
2292 struct wifi_data *wifi = connman_device_get_data(device);
2293 struct autoscan_params *autoscan;
2300 if (wifi->p2p_device)
2303 if (wifi->connected)
2306 autoscan = wifi->autoscan;
2310 if (autoscan->timeout > 0 || autoscan->interval > 0)
2313 connman_device_ref(device);
2315 autoscan_timeout(device);
2318 static struct autoscan_params *parse_autoscan_params(const char *params)
2320 struct autoscan_params *autoscan;
2327 list_params = g_strsplit(params, ":", 0);
2328 if (list_params == 0)
2331 if (!g_strcmp0(list_params[0], "exponential") &&
2332 g_strv_length(list_params) == 3) {
2333 base = atoi(list_params[1]);
2334 limit = atoi(list_params[2]);
2335 } else if (!g_strcmp0(list_params[0], "single") &&
2336 g_strv_length(list_params) == 2)
2337 base = limit = atoi(list_params[1]);
2339 g_strfreev(list_params);
2343 DBG("Setup %s autoscanning", list_params[0]);
2345 g_strfreev(list_params);
2347 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2349 DBG("Could not allocate memory for autoscan");
2353 DBG("base %d - limit %d", base, limit);
2354 autoscan->base = base;
2355 autoscan->limit = limit;
2360 static void setup_autoscan(struct wifi_data *wifi)
2363 * If BackgroundScanning is enabled, setup exponential
2364 * autoscanning if it has not been previously done.
2366 if (connman_setting_get_bool("BackgroundScanning")) {
2367 wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
2372 * On the contrary, if BackgroundScanning is disabled, update autoscan
2373 * parameters based on the type of scanning that is being performed.
2375 if (wifi->autoscan) {
2376 g_free(wifi->autoscan);
2377 wifi->autoscan = NULL;
2380 switch (wifi->scanning_type) {
2381 case WIFI_SCANNING_PASSIVE:
2382 /* Do not setup autoscan. */
2384 case WIFI_SCANNING_ACTIVE:
2385 /* Setup one single passive scan after active. */
2386 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2388 case WIFI_SCANNING_UNKNOWN:
2389 /* Setup autoscan in this case but we should never fall here. */
2390 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2395 static void finalize_interface_creation(struct wifi_data *wifi)
2397 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2399 if (!wifi->device) {
2400 connman_error("WiFi device not set");
2404 connman_device_set_powered(wifi->device, true);
2406 if (wifi->p2p_device)
2409 if (!wifi->autoscan)
2410 setup_autoscan(wifi);
2412 start_autoscan(wifi->device);
2415 static void interface_create_callback(int result,
2416 GSupplicantInterface *interface,
2419 struct wifi_data *wifi = user_data;
2421 DBG("result %d ifname %s, wifi %p", result,
2422 g_supplicant_interface_get_ifname(interface),
2425 if (result < 0 || !wifi)
2428 wifi->interface = interface;
2429 g_supplicant_interface_set_data(interface, wifi);
2431 if (g_supplicant_interface_get_ready(interface)) {
2432 wifi->interface_ready = true;
2433 finalize_interface_creation(wifi);
2437 static int wifi_enable(struct connman_device *device)
2439 struct wifi_data *wifi = connman_device_get_data(device);
2442 const char *driver = connman_option_get_string("wifi");
2445 DBG("device %p %p", device, wifi);
2447 index = connman_device_get_index(device);
2448 if (!wifi || index < 0)
2451 if (is_p2p_connecting())
2452 return -EINPROGRESS;
2454 interface = connman_inet_ifname(index);
2455 ret = g_supplicant_interface_create(interface, driver, NULL,
2456 interface_create_callback,
2463 return -EINPROGRESS;
2466 static int wifi_disable(struct connman_device *device)
2468 struct wifi_data *wifi = connman_device_get_data(device);
2471 DBG("device %p wifi %p", device, wifi);
2476 wifi->connected = false;
2477 wifi->disconnecting = false;
2479 if (wifi->pending_network)
2480 wifi->pending_network = NULL;
2482 stop_autoscan(device);
2484 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
2485 g_source_remove(wifi->p2p_find_timeout);
2486 wifi->p2p_find_timeout = 0;
2487 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2488 connman_device_unref(wifi->device);
2491 #if defined TIZEN_EXT
2492 if (wifi->automaxspeed_timeout != 0) {
2493 g_source_remove(wifi->automaxspeed_timeout);
2494 wifi->automaxspeed_timeout = 0;
2498 /* In case of a user scan, device is still referenced */
2499 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) {
2500 connman_device_set_scanning(device,
2501 CONNMAN_SERVICE_TYPE_WIFI, false);
2502 connman_device_unref(wifi->device);
2505 remove_networks(device, wifi);
2508 #if defined TIZEN_EXT
2509 wifi->scan_pending_network = NULL;
2511 if (is_wifi_notifier_registered == true) {
2512 connman_notifier_unregister(¬ifier);
2513 is_wifi_notifier_registered = false;
2517 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2521 return -EINPROGRESS;
2524 static int get_latest_connections(int max_ssids,
2525 GSupplicantScanParams *scan_data)
2527 GSequenceIter *iter;
2528 GSequence *latest_list;
2529 struct last_connected *entry;
2538 latest_list = g_sequence_new(free_entry);
2542 services = connman_storage_get_services();
2543 for (i = 0; services && services[i]; i++) {
2544 if (strncmp(services[i], "wifi_", 5) != 0)
2547 keyfile = connman_storage_load_service(services[i]);
2551 str = g_key_file_get_string(keyfile,
2552 services[i], "Favorite", NULL);
2553 if (!str || g_strcmp0(str, "true")) {
2555 g_key_file_free(keyfile);
2560 str = g_key_file_get_string(keyfile,
2561 services[i], "AutoConnect", NULL);
2562 if (!str || g_strcmp0(str, "true")) {
2564 g_key_file_free(keyfile);
2569 str = g_key_file_get_string(keyfile,
2570 services[i], "Modified", NULL);
2572 g_key_file_free(keyfile);
2575 g_time_val_from_iso8601(str, &modified);
2578 ssid = g_key_file_get_string(keyfile,
2579 services[i], "SSID", NULL);
2581 freq = g_key_file_get_integer(keyfile, services[i],
2584 entry = g_try_new(struct last_connected, 1);
2586 g_sequence_free(latest_list);
2587 g_key_file_free(keyfile);
2593 entry->modified = modified;
2596 g_sequence_insert_sorted(latest_list, entry,
2602 g_key_file_free(keyfile);
2605 g_strfreev(services);
2607 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2609 iter = g_sequence_get_begin_iter(latest_list);
2611 for (i = 0; i < num_ssids; i++) {
2612 entry = g_sequence_get(iter);
2614 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2615 entry->modified.tv_sec);
2617 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2618 max_ssids, entry->ssid);
2620 iter = g_sequence_iter_next(iter);
2623 g_sequence_free(latest_list);
2627 static void wifi_update_scanner_type(struct wifi_data *wifi,
2628 enum wifi_scanning_type new_type)
2632 if (!wifi || wifi->scanning_type == new_type)
2635 wifi->scanning_type = new_type;
2637 setup_autoscan(wifi);
2640 static int wifi_scan_simple(struct connman_device *device)
2642 struct wifi_data *wifi = connman_device_get_data(device);
2644 reset_autoscan(device);
2646 /* Distinguish between devices performing passive and active scanning */
2648 wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE);
2650 return throw_wifi_scan(device, scan_callback_hidden);
2653 static gboolean p2p_find_stop(gpointer data)
2655 struct connman_device *device = data;
2656 struct wifi_data *wifi = connman_device_get_data(device);
2661 wifi->p2p_find_timeout = 0;
2663 g_supplicant_interface_p2p_stop_find(wifi->interface);
2666 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2668 connman_device_unref(device);
2669 start_autoscan(device);
2674 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2677 struct connman_device *device = user_data;
2678 struct wifi_data *wifi = connman_device_get_data(device);
2680 DBG("result %d wifi %p", result, wifi);
2685 if (wifi->p2p_find_timeout) {
2686 g_source_remove(wifi->p2p_find_timeout);
2687 wifi->p2p_find_timeout = 0;
2693 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2694 p2p_find_stop, device);
2695 if (!wifi->p2p_find_timeout)
2700 p2p_find_stop(device);
2703 static int p2p_find(struct connman_device *device)
2705 struct wifi_data *wifi;
2710 if (!p2p_technology)
2713 wifi = connman_device_get_data(device);
2715 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2718 reset_autoscan(device);
2719 connman_device_ref(device);
2721 ret = g_supplicant_interface_p2p_find(wifi->interface,
2722 p2p_find_callback, device);
2724 connman_device_unref(device);
2725 start_autoscan(device);
2727 connman_device_set_scanning(device,
2728 CONNMAN_SERVICE_TYPE_P2P, true);
2734 #if defined TIZEN_EXT
2735 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2738 struct connman_device *device = user_data;
2739 struct wifi_data *wifi = connman_device_get_data(device);
2742 DBG("result %d wifi %p", result, wifi);
2744 if (wifi && wifi->scan_params) {
2745 g_supplicant_free_scan_params(wifi->scan_params);
2746 wifi->scan_params = NULL;
2749 scanning = connman_device_get_scanning(device,
2750 CONNMAN_SERVICE_TYPE_WIFI);
2752 connman_device_set_scanning(device,
2753 CONNMAN_SERVICE_TYPE_WIFI, false);
2754 connman_device_unref(device);
2758 static int wifi_specific_scan(enum connman_service_type type,
2759 struct connman_device *device, int scan_type,
2760 GSList *specific_scan_list, void *user_data)
2762 GSList *list = NULL;
2764 struct wifi_data *wifi = connman_device_get_data(device);
2765 GSupplicantScanParams *scan_params = NULL;
2766 struct scan_ssid *scan_ssid = NULL;
2775 if (wifi->p2p_device)
2778 if (type == CONNMAN_SERVICE_TYPE_P2P)
2779 return p2p_find(device);
2781 if (wifi->tethering)
2785 connman_device_get_scanning(device,
2786 CONNMAN_SERVICE_TYPE_WIFI);
2790 DBG("scan_type: %d", scan_type);
2791 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2792 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2794 DBG("Failed to allocate memory.");
2798 for (list = specific_scan_list; list; list = list->next) {
2799 ssid = (char *)list->data;
2800 int ssid_len = strlen(ssid);
2802 scan_ssid = g_try_new0(struct scan_ssid, 1);
2804 DBG("Failed to allocate memory.");
2805 g_supplicant_free_scan_params(scan_params);
2809 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2810 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2811 scan_ssid->ssid_len = ssid_len;
2812 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2815 scan_params->num_ssids = count;
2817 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2819 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2821 DBG("Failed to allocate memory.");
2825 guint num_freqs = g_slist_length(specific_scan_list);
2826 DBG("num_freqs: %d", num_freqs);
2828 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2829 if (!scan_params->freqs) {
2830 DBG("Failed to allocate memory.");
2831 g_free(scan_params);
2836 for (list = specific_scan_list; list; list = list->next) {
2837 freq = (int)list->data;
2839 scan_params->freqs[count] = freq;
2840 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2843 scan_params->num_freqs = count;
2845 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2846 int freq_count, ap_count;
2847 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2849 DBG("Failed to allocate memory.");
2853 guint size = g_slist_length(specific_scan_list);
2855 scan_params->freqs = g_try_new0(uint16_t, size/2);
2856 if (!scan_params->freqs) {
2857 DBG("Failed to allocate memory.");
2858 g_free(scan_params);
2862 ap_count = freq_count = 0;
2863 for (list = specific_scan_list; list; list = list->next) {
2864 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2865 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2866 int ssid_len = strlen(ssid);
2868 scan_ssid = g_try_new0(struct scan_ssid, 1);
2870 DBG("Failed to allocate memory.");
2871 g_supplicant_free_scan_params(scan_params);
2875 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2876 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2877 scan_ssid->ssid_len = ssid_len;
2878 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2882 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2883 scan_params->freqs[freq_count] = freq;
2884 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2888 scan_params->num_ssids = ap_count;
2889 scan_params->num_freqs = freq_count;
2891 DBG("Invalid scan");
2895 reset_autoscan(device);
2896 connman_device_ref(device);
2898 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2899 specific_scan_callback, device);
2902 connman_device_set_scanning(device,
2903 CONNMAN_SERVICE_TYPE_WIFI, true);
2905 g_supplicant_free_scan_params(scan_params);
2906 connman_device_unref(device);
2913 #if defined TIZEN_EXT_WIFI_MESH
2914 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2917 struct connman_device *device = user_data;
2918 struct wifi_data *wifi = connman_device_get_data(device);
2921 DBG("result %d wifi %p", result, wifi);
2923 scanning = connman_device_get_scanning(device,
2924 CONNMAN_SERVICE_TYPE_MESH);
2926 connman_device_set_scanning(device,
2927 CONNMAN_SERVICE_TYPE_MESH, false);
2930 connman_device_unref(device);
2933 static int mesh_scan(struct connman_device *device)
2935 struct wifi_data *wifi;
2936 struct wifi_mesh_info *mesh_info;
2941 wifi = connman_device_get_data(device);
2943 if (!wifi->mesh_interface)
2946 mesh_info = wifi->mesh_info;
2947 reset_autoscan(device);
2948 connman_device_ref(device);
2950 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2951 mesh_scan_callback, device);
2953 connman_device_unref(device);
2955 connman_device_set_scanning(device,
2956 CONNMAN_SERVICE_TYPE_MESH, true);
2961 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2964 struct connman_device *device = user_data;
2965 struct wifi_data *wifi = connman_device_get_data(device);
2967 DBG("result %d wifi %p", result, wifi);
2969 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2972 static int mesh_abort_scan(enum connman_service_type type,
2973 struct connman_device *device)
2975 struct wifi_data *wifi = connman_device_get_data(device);
2976 struct wifi_mesh_info *mesh_info;
2980 if (!wifi || !wifi->mesh_interface)
2983 if (type != CONNMAN_SERVICE_TYPE_MESH)
2986 mesh_info = wifi->mesh_info;
2988 scanning = connman_device_get_scanning(device,
2989 CONNMAN_SERVICE_TYPE_MESH);
2993 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2994 abort_scan_callback, device);
2999 static int mesh_specific_scan(enum connman_service_type type,
3000 struct connman_device *device, const char *ssid,
3001 unsigned int freq, void *user_data)
3003 struct wifi_data *wifi = connman_device_get_data(device);
3004 GSupplicantScanParams *scan_params = NULL;
3005 struct wifi_mesh_info *mesh_info;
3006 struct scan_ssid *scan_ssid;
3010 if (!wifi || !wifi->mesh_interface)
3013 if (type != CONNMAN_SERVICE_TYPE_MESH)
3016 if (wifi->p2p_device)
3019 mesh_info = wifi->mesh_info;
3021 scanning = connman_device_get_scanning(device,
3022 CONNMAN_SERVICE_TYPE_MESH);
3026 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3030 scan_ssid = g_try_new(struct scan_ssid, 1);
3032 g_free(scan_params);
3036 scan_ssid->ssid_len = strlen(ssid);
3037 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
3038 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3039 scan_params->num_ssids = 1;
3041 scan_params->freqs = g_try_new(uint16_t, 1);
3042 if (!scan_params->freqs) {
3043 g_slist_free_full(scan_params->ssids, g_free);
3044 g_free(scan_params);
3048 scan_params->freqs[0] = freq;
3049 scan_params->num_freqs = 1;
3051 reset_autoscan(device);
3052 connman_device_ref(device);
3054 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
3055 mesh_scan_callback, device);
3058 connman_device_set_scanning(device,
3059 CONNMAN_SERVICE_TYPE_MESH, true);
3061 g_supplicant_free_scan_params(scan_params);
3062 connman_device_unref(device);
3070 * Note that the hidden scan is only used when connecting to this specific
3071 * hidden AP first time. It is not used when system autoconnects to hidden AP.
3073 static int wifi_scan(struct connman_device *device,
3074 struct connman_device_scan_params *params)
3076 struct wifi_data *wifi = connman_device_get_data(device);
3077 GSupplicantScanParams *scan_params = NULL;
3078 struct scan_ssid *scan_ssid;
3079 struct hidden_params *hidden;
3081 int driver_max_ssids = 0;
3088 if (wifi->p2p_device)
3091 if (wifi->tethering)
3094 if (params->type == CONNMAN_SERVICE_TYPE_P2P)
3095 return p2p_find(device);
3097 #if defined TIZEN_EXT_WIFI_MESH
3098 if (params->type == CONNMAN_SERVICE_TYPE_MESH)
3099 return mesh_scan(device);
3102 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface,
3105 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
3107 if (!params->ssid || params->ssid_len == 0 || params->ssid_len > 32) {
3111 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
3113 DBG("max ssids %d", driver_max_ssids);
3114 if (driver_max_ssids == 0)
3115 return wifi_scan_simple(device);
3119 if (scanning && wifi->hidden && wifi->postpone_hidden)
3125 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3130 scan_ssid = g_try_new(struct scan_ssid, 1);
3132 g_free(scan_params);
3136 memcpy(scan_ssid->ssid, params->ssid, params->ssid_len);
3137 scan_ssid->ssid_len = params->ssid_len;
3138 scan_params->ssids = g_slist_prepend(scan_params->ssids,
3140 scan_params->num_ssids = 1;
3142 hidden = g_try_new0(struct hidden_params, 1);
3144 g_supplicant_free_scan_params(scan_params);
3149 hidden_free(wifi->hidden);
3150 wifi->hidden = NULL;
3153 memcpy(hidden->ssid, params->ssid, params->ssid_len);
3154 hidden->ssid_len = params->ssid_len;
3155 hidden->identity = g_strdup(params->identity);
3156 hidden->passphrase = g_strdup(params->passphrase);
3157 hidden->security = g_strdup(params->security);
3158 hidden->user_data = params->user_data;
3159 wifi->hidden = hidden;
3162 /* Let's keep this active scan for later,
3163 * when current scan will be over. */
3164 wifi->postpone_hidden = TRUE;
3165 hidden->scan_params = scan_params;
3169 } else if (wifi->connected) {
3170 g_supplicant_free_scan_params(scan_params);
3171 return wifi_scan_simple(device);
3172 } else if (!params->force_full_scan) {
3173 ret = get_latest_connections(driver_max_ssids, scan_params);
3175 g_supplicant_free_scan_params(scan_params);
3176 return wifi_scan_simple(device);
3180 /* Distinguish between devices performing passive and active scanning */
3181 wifi_update_scanner_type(wifi, WIFI_SCANNING_ACTIVE);
3183 connman_device_ref(device);
3185 reset_autoscan(device);
3187 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3188 scan_callback, device);
3190 connman_device_set_scanning(device,
3191 CONNMAN_SERVICE_TYPE_WIFI, true);
3192 #if defined TIZEN_EXT
3193 /*To allow the Full Scan after ssid based scan, set the flag here
3194 It is required because Tizen does not use the ConnMan specific
3195 backgroung Scan feature.Tizen has added the BG Scan feature in
3196 net-config. To sync with up ConnMan, we need to issue the Full Scan
3197 after SSID specific scan.*/
3198 wifi->allow_full_scan = TRUE;
3201 g_supplicant_free_scan_params(scan_params);
3202 connman_device_unref(device);
3205 hidden_free(wifi->hidden);
3206 wifi->hidden = NULL;
3213 static void wifi_stop_scan(enum connman_service_type type,
3214 struct connman_device *device)
3216 struct wifi_data *wifi = connman_device_get_data(device);
3218 DBG("device %p wifi %p", device, wifi);
3223 if (type == CONNMAN_SERVICE_TYPE_P2P) {
3224 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
3225 g_source_remove(wifi->p2p_find_timeout);
3226 p2p_find_stop(device);
3231 static void wifi_regdom_callback(int result,
3235 struct connman_device *device = user_data;
3237 connman_device_regdom_notify(device, result, alpha2);
3239 connman_device_unref(device);
3242 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3244 struct wifi_data *wifi = connman_device_get_data(device);
3250 connman_device_ref(device);
3252 ret = g_supplicant_interface_set_country(wifi->interface,
3253 wifi_regdom_callback,
3256 connman_device_unref(device);
3261 static struct connman_device_driver wifi_ng_driver = {
3263 .type = CONNMAN_DEVICE_TYPE_WIFI,
3264 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3265 .probe = wifi_probe,
3266 .remove = wifi_remove,
3267 .enable = wifi_enable,
3268 .disable = wifi_disable,
3270 .stop_scan = wifi_stop_scan,
3271 .set_regdom = wifi_set_regdom,
3272 #if defined TIZEN_EXT
3273 .specific_scan = wifi_specific_scan,
3275 #if defined TIZEN_EXT_WIFI_MESH
3276 .abort_scan = mesh_abort_scan,
3277 .mesh_specific_scan = mesh_specific_scan,
3281 static void system_ready(void)
3285 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3286 connman_error("Failed to register WiFi driver");
3289 static void system_killed(void)
3293 connman_device_driver_unregister(&wifi_ng_driver);
3296 static int network_probe(struct connman_network *network)
3298 DBG("network %p", network);
3303 static void network_remove(struct connman_network *network)
3305 struct connman_device *device = connman_network_get_device(network);
3306 struct wifi_data *wifi;
3308 DBG("network %p", network);
3310 wifi = connman_device_get_data(device);
3314 if (wifi->network != network)
3317 wifi->network = NULL;
3319 #if defined TIZEN_EXT
3320 wifi->disconnecting = false;
3322 if (wifi->pending_network == network)
3323 wifi->pending_network = NULL;
3325 if (wifi->scan_pending_network == network)
3326 wifi->scan_pending_network = NULL;
3330 static void connect_callback(int result, GSupplicantInterface *interface,
3333 #if defined TIZEN_EXT
3335 struct wifi_data *wifi;
3337 struct connman_network *network = user_data;
3339 DBG("network %p result %d", network, result);
3341 #if defined TIZEN_EXT
3342 set_connman_bssid(RESET_BSSID, NULL);
3344 for (list = iface_list; list; list = list->next) {
3347 if (wifi && wifi->network == network)
3351 /* wifi_data may be invalid because wifi is already disabled */
3356 if (result == -ENOKEY) {
3357 connman_network_set_error(network,
3358 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3359 } else if (result < 0) {
3360 connman_network_set_error(network,
3361 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3364 connman_network_unref(network);
3367 static GSupplicantSecurity network_security(const char *security)
3369 if (g_str_equal(security, "none"))
3370 return G_SUPPLICANT_SECURITY_NONE;
3371 else if (g_str_equal(security, "wep"))
3372 return G_SUPPLICANT_SECURITY_WEP;
3373 else if (g_str_equal(security, "psk"))
3374 return G_SUPPLICANT_SECURITY_PSK;
3375 else if (g_str_equal(security, "wpa"))
3376 return G_SUPPLICANT_SECURITY_PSK;
3377 else if (g_str_equal(security, "rsn"))
3378 return G_SUPPLICANT_SECURITY_PSK;
3379 else if (g_str_equal(security, "ieee8021x"))
3380 return G_SUPPLICANT_SECURITY_IEEE8021X;
3381 #if defined TIZEN_EXT
3382 else if (g_str_equal(security, "ft_psk") == TRUE)
3383 return G_SUPPLICANT_SECURITY_FT_PSK;
3384 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3385 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3386 else if (g_str_equal(security, "sae"))
3387 return G_SUPPLICANT_SECURITY_SAE;
3388 else if (g_str_equal(security, "owe"))
3389 return G_SUPPLICANT_SECURITY_OWE;
3392 return G_SUPPLICANT_SECURITY_UNKNOWN;
3395 #if defined TIZEN_EXT
3396 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3398 if (security == NULL)
3399 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3401 if (g_str_equal(security, "FT") == TRUE)
3402 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3403 else if (g_str_equal(security, "CCKM") == TRUE)
3404 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3406 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3410 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3412 const char *security;
3413 #if defined TIZEN_EXT
3414 const void *ssid_data;
3417 memset(ssid, 0, sizeof(*ssid));
3418 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3419 #if defined TIZEN_EXT
3420 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3422 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3427 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3429 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3432 ssid->scan_ssid = 1;
3433 security = connman_network_get_string(network, "WiFi.Security");
3434 ssid->security = network_security(security);
3435 #if defined TIZEN_EXT
3436 ssid->ieee80211w = 1;
3438 ssid->passphrase = connman_network_get_string(network,
3441 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3444 * If our private key password is unset,
3445 * we use the supplied passphrase. That is needed
3446 * for PEAP where 2 passphrases (identity and client
3447 * cert may have to be provided.
3449 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3450 connman_network_set_string(network,
3451 "WiFi.PrivateKeyPassphrase",
3453 /* We must have an identity for both PEAP and TLS */
3454 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3456 /* Use agent provided identity as a fallback */
3457 if (!ssid->identity || strlen(ssid->identity) == 0)
3458 ssid->identity = connman_network_get_string(network,
3459 "WiFi.AgentIdentity");
3461 ssid->anonymous_identity = connman_network_get_string(network,
3462 "WiFi.AnonymousIdentity");
3463 ssid->ca_cert_path = connman_network_get_string(network,
3465 ssid->subject_match = connman_network_get_string(network,
3466 "WiFi.SubjectMatch");
3467 ssid->altsubject_match = connman_network_get_string(network,
3468 "WiFi.AltSubjectMatch");
3469 ssid->domain_suffix_match = connman_network_get_string(network,
3470 "WiFi.DomainSuffixMatch");
3471 ssid->domain_match = connman_network_get_string(network,
3472 "WiFi.DomainMatch");
3473 ssid->client_cert_path = connman_network_get_string(network,
3474 "WiFi.ClientCertFile");
3475 ssid->private_key_path = connman_network_get_string(network,
3476 "WiFi.PrivateKeyFile");
3477 ssid->private_key_passphrase = connman_network_get_string(network,
3478 "WiFi.PrivateKeyPassphrase");
3479 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3481 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3482 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3484 #if defined TIZEN_EXT
3485 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3486 ssid->bssid_for_connect_len = 6;
3487 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3488 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3489 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3490 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3491 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3493 ssid->freq = connman_network_get_frequency(network);
3496 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3497 if (bssid_list && g_slist_length(bssid_list) > 1) {
3499 /* If there are more than one bssid,
3500 * the user-specified bssid is tried only once at the beginning.
3501 * After that, the bssids in the list are tried in order.
3503 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3504 set_connman_bssid(RESET_BSSID, NULL);
3509 char buff[MAC_ADDRESS_LENGTH];
3510 for (list = bssid_list; list; list = list->next) {
3511 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3513 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3514 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3515 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3516 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3518 gchar *curr_bssid = g_strdup((const gchar *)buff);
3520 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3521 DBG("bssid match, try next bssid");
3525 g_hash_table_add(failed_bssids, curr_bssid);
3527 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3528 ssid->bssid = buff_bssid;
3529 ssid->freq = (unsigned int)bssids->frequency;
3535 ssid->bssid = connman_network_get_bssid(network);
3536 g_hash_table_remove_all(failed_bssids);
3539 ssid->bssid = connman_network_get_bssid(network);
3542 ssid->eap_keymgmt = network_eap_keymgmt(
3543 connman_network_get_string(network, "WiFi.KeymgmtType"));
3544 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3546 if(g_strcmp0(ssid->eap, "fast") == 0)
3547 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3550 if (connman_setting_get_bool("BackgroundScanning"))
3551 ssid->bgscan = BGSCAN_DEFAULT;
3554 static int network_connect(struct connman_network *network)
3556 struct connman_device *device = connman_network_get_device(network);
3557 struct wifi_data *wifi;
3558 GSupplicantInterface *interface;
3559 GSupplicantSSID *ssid;
3561 DBG("network %p", network);
3566 wifi = connman_device_get_data(device);
3570 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3574 interface = wifi->interface;
3576 ssid_init(ssid, network);
3578 if (wifi->disconnecting) {
3579 wifi->pending_network = network;
3580 #if defined TIZEN_EXT
3585 wifi->network = connman_network_ref(network);
3587 #if defined TIZEN_EXT
3588 wifi->scan_pending_network = NULL;
3591 return g_supplicant_interface_connect(interface, ssid,
3592 connect_callback, network);
3595 return -EINPROGRESS;
3598 static void disconnect_callback(int result, GSupplicantInterface *interface,
3601 #if defined TIZEN_EXT
3603 struct wifi_data *wifi;
3604 struct connman_network *network = user_data;
3606 DBG("network %p result %d", network, result);
3608 for (list = iface_list; list; list = list->next) {
3611 if (wifi->network == NULL && wifi->disconnecting == true)
3612 wifi->disconnecting = false;
3614 if (wifi->network == network)
3618 /* wifi_data may be invalid because wifi is already disabled */
3623 struct wifi_data *wifi = user_data;
3626 DBG("result %d supplicant interface %p wifi %p",
3627 result, interface, wifi);
3629 if (result == -ECONNABORTED) {
3630 DBG("wifi interface no longer available");
3634 if (wifi->network != wifi->pending_network)
3635 connman_network_set_connected(wifi->network, false);
3636 wifi->network = NULL;
3638 wifi->disconnecting = false;
3639 wifi->connected = false;
3641 if (wifi->pending_network) {
3642 network_connect(wifi->pending_network);
3643 wifi->pending_network = NULL;
3646 start_autoscan(wifi->device);
3649 static int network_disconnect(struct connman_network *network)
3651 struct connman_device *device = connman_network_get_device(network);
3652 struct wifi_data *wifi;
3654 #if defined TIZEN_EXT
3655 struct connman_service *service;
3658 DBG("network %p", network);
3660 wifi = connman_device_get_data(device);
3661 if (!wifi || !wifi->interface)
3664 #if defined TIZEN_EXT
3665 if (connman_network_get_associating(network) == true) {
3666 connman_network_clear_associating(network);
3667 connman_network_set_bool(network, "WiFi.UseWPS", false);
3669 service = connman_service_lookup_from_network(network);
3671 if (service != NULL &&
3672 (__connman_service_is_connected_state(service,
3673 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3674 __connman_service_is_connected_state(service,
3675 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3676 (connman_service_get_favorite(service) == false))
3677 __connman_service_set_passphrase(service, NULL);
3680 if (wifi->pending_network == network)
3681 wifi->pending_network = NULL;
3683 if (wifi->scan_pending_network == network)
3684 wifi->scan_pending_network = NULL;
3687 connman_network_set_associating(network, false);
3689 if (wifi->disconnecting)
3692 wifi->disconnecting = true;
3694 #if defined TIZEN_EXT
3695 err = g_supplicant_interface_disconnect(wifi->interface,
3696 disconnect_callback, network);
3698 err = g_supplicant_interface_disconnect(wifi->interface,
3699 disconnect_callback, wifi);
3703 wifi->disconnecting = false;
3708 #if defined TIZEN_EXT
3709 static void set_connection_mode(struct connman_network *network,
3712 ieee80211_modes_e phy_mode;
3713 connection_mode_e conn_mode;
3715 phy_mode = connman_network_get_phy_mode(network);
3717 case IEEE80211_MODE_B:
3718 if (linkspeed > 0 && linkspeed <= 11)
3719 conn_mode = CONNECTION_MODE_IEEE80211B;
3721 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3724 case IEEE80211_MODE_BG:
3725 if (linkspeed > 0 && linkspeed <= 11)
3726 conn_mode = CONNECTION_MODE_IEEE80211B;
3727 else if (linkspeed > 11 && linkspeed <= 54)
3728 conn_mode = CONNECTION_MODE_IEEE80211G;
3730 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3733 case IEEE80211_MODE_BGN:
3734 if (linkspeed > 0 && linkspeed <= 11)
3735 conn_mode = CONNECTION_MODE_IEEE80211B;
3736 else if (linkspeed > 11 && linkspeed <= 54)
3737 conn_mode = CONNECTION_MODE_IEEE80211G;
3738 else if (linkspeed > 54 && linkspeed <= 450)
3739 conn_mode = CONNECTION_MODE_IEEE80211N;
3741 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3744 case IEEE80211_MODE_A:
3745 if (linkspeed > 0 && linkspeed <= 54)
3746 conn_mode = CONNECTION_MODE_IEEE80211A;
3748 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3751 case IEEE80211_MODE_AN:
3752 if (linkspeed > 0 && linkspeed <= 54)
3753 conn_mode = CONNECTION_MODE_IEEE80211A;
3754 else if (linkspeed > 54 && linkspeed <= 450)
3755 conn_mode = CONNECTION_MODE_IEEE80211N;
3757 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3760 case IEEE80211_MODE_ANAC:
3761 if (linkspeed > 0 && linkspeed <= 54)
3762 conn_mode = CONNECTION_MODE_IEEE80211A;
3763 else if (linkspeed > 54 && linkspeed <= 450)
3764 conn_mode = CONNECTION_MODE_IEEE80211N;
3765 else if (linkspeed > 450 && linkspeed <= 1300)
3766 conn_mode = CONNECTION_MODE_IEEE80211AC;
3768 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3772 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3776 DBG("connection mode(%d)", conn_mode);
3777 connman_network_set_connection_mode(network, conn_mode);
3780 static void signalpoll_callback(int result, int maxspeed, uint8_t strength,
3783 struct connman_network *network = user_data;
3786 DBG("Failed to get maxspeed from signalpoll !");
3794 DBG("maxspeed = %d, strength = %d", maxspeed, strength);
3796 connman_network_set_strength(network, strength);
3797 connman_network_set_maxspeed(network, maxspeed);
3798 set_connection_mode(network, maxspeed);
3802 static int network_signalpoll(struct wifi_data *wifi)
3804 GSupplicantInterface *interface;
3805 struct connman_network *network;
3807 if (!wifi || !wifi->network)
3810 interface = wifi->interface;
3811 network = wifi->network;
3813 DBG("network %p", network);
3815 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3818 static gboolean autosignalpoll_timeout(gpointer data)
3820 struct wifi_data *wifi = data;
3822 if (!wifi || !wifi->automaxspeed_timeout) {
3823 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3827 int ret = network_signalpoll(wifi);
3829 DBG("Fail to get max speed !!");
3830 wifi->automaxspeed_timeout = 0;
3838 static struct connman_network_driver network_driver = {
3840 .type = CONNMAN_NETWORK_TYPE_WIFI,
3841 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3842 .probe = network_probe,
3843 .remove = network_remove,
3844 .connect = network_connect,
3845 .disconnect = network_disconnect,
3848 static void interface_added(GSupplicantInterface *interface)
3850 const char *ifname = g_supplicant_interface_get_ifname(interface);
3851 const char *driver = g_supplicant_interface_get_driver(interface);
3852 #if defined TIZEN_EXT
3853 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3856 struct wifi_data *wifi;
3858 wifi = g_supplicant_interface_get_data(interface);
3860 wifi = get_pending_wifi_data(ifname);
3864 wifi->interface = interface;
3865 g_supplicant_interface_set_data(interface, wifi);
3866 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3867 wifi->p2p_device = true;
3870 DBG("ifname %s driver %s wifi %p tethering %d",
3871 ifname, driver, wifi, wifi->tethering);
3873 if (!wifi->device) {
3874 connman_error("WiFi device not set");
3878 connman_device_set_powered(wifi->device, true);
3879 #if defined TIZEN_EXT
3880 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3881 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3882 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3883 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3887 static bool is_idle(struct wifi_data *wifi)
3889 DBG("state %d", wifi->state);
3891 switch (wifi->state) {
3892 case G_SUPPLICANT_STATE_UNKNOWN:
3893 case G_SUPPLICANT_STATE_DISABLED:
3894 case G_SUPPLICANT_STATE_DISCONNECTED:
3895 case G_SUPPLICANT_STATE_INACTIVE:
3896 case G_SUPPLICANT_STATE_SCANNING:
3899 case G_SUPPLICANT_STATE_AUTHENTICATING:
3900 case G_SUPPLICANT_STATE_ASSOCIATING:
3901 case G_SUPPLICANT_STATE_ASSOCIATED:
3902 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3903 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3904 case G_SUPPLICANT_STATE_COMPLETED:
3911 static bool is_idle_wps(GSupplicantInterface *interface,
3912 struct wifi_data *wifi)
3914 /* First, let's check if WPS processing did not went wrong */
3915 if (g_supplicant_interface_get_wps_state(interface) ==
3916 G_SUPPLICANT_WPS_STATE_FAIL)
3919 /* Unlike normal connection, being associated while processing wps
3920 * actually means that we are idling. */
3921 switch (wifi->state) {
3922 case G_SUPPLICANT_STATE_UNKNOWN:
3923 case G_SUPPLICANT_STATE_DISABLED:
3924 case G_SUPPLICANT_STATE_DISCONNECTED:
3925 case G_SUPPLICANT_STATE_INACTIVE:
3926 case G_SUPPLICANT_STATE_SCANNING:
3927 case G_SUPPLICANT_STATE_ASSOCIATED:
3929 case G_SUPPLICANT_STATE_AUTHENTICATING:
3930 case G_SUPPLICANT_STATE_ASSOCIATING:
3931 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3932 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3933 case G_SUPPLICANT_STATE_COMPLETED:
3940 static bool handle_wps_completion(GSupplicantInterface *interface,
3941 struct connman_network *network,
3942 struct connman_device *device,
3943 struct wifi_data *wifi)
3947 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3949 const unsigned char *ssid, *wps_ssid;
3950 unsigned int ssid_len, wps_ssid_len;
3951 const char *wps_key;
3953 /* Checking if we got associated with requested
3955 ssid = connman_network_get_blob(network, "WiFi.SSID",
3958 wps_ssid = g_supplicant_interface_get_wps_ssid(
3959 interface, &wps_ssid_len);
3961 if (!wps_ssid || wps_ssid_len != ssid_len ||
3962 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3963 connman_network_set_associating(network, false);
3964 #if defined TIZEN_EXT
3965 g_supplicant_interface_disconnect(wifi->interface,
3966 disconnect_callback, wifi->network);
3968 connman_network_set_bool(network, "WiFi.UseWPS", false);
3969 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3971 g_supplicant_interface_disconnect(wifi->interface,
3972 disconnect_callback, wifi);
3977 wps_key = g_supplicant_interface_get_wps_key(interface);
3978 #if defined TIZEN_EXT
3979 /* Check the passphrase and encrypt it
3982 gchar *passphrase = g_strdup(wps_key);
3984 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3986 if (check_passphrase_ext(network, passphrase) < 0) {
3987 DBG("[WPS] Invalid passphrase");
3992 ret = send_encryption_request(passphrase, network);
3997 DBG("[WPS] Encryption request succeeded");
3999 DBG("[WPS] Encryption request failed %d", ret);
4002 connman_network_set_string(network, "WiFi.Passphrase",
4005 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4012 static bool handle_assoc_status_code(GSupplicantInterface *interface,
4013 struct wifi_data *wifi)
4015 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
4016 #if defined TIZEN_EXT
4017 wifi->assoc_code > 0 &&
4019 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
4021 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
4022 wifi->load_shaping_retries ++;
4025 wifi->load_shaping_retries = 0;
4029 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
4030 struct connman_network *network,
4031 struct wifi_data *wifi)
4033 #if defined TIZEN_EXT
4034 const char *security;
4035 struct connman_service *service;
4037 if (wifi->connected)
4040 security = connman_network_get_string(network, "WiFi.Security");
4042 if (security && g_str_equal(security, "ieee8021x") == true &&
4043 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4045 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4050 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4053 struct connman_service *service;
4055 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4058 if (wifi->connected)
4062 service = connman_service_lookup_from_network(network);
4068 if (connman_service_get_favorite(service)) {
4069 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
4074 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4079 #if defined TIZEN_EXT
4080 static bool handle_wifi_assoc_retry(struct connman_network *network,
4081 struct wifi_data *wifi)
4083 const char *security;
4085 if (!wifi->network || wifi->connected || wifi->disconnecting ||
4086 connman_network_get_connecting(network) != true) {
4087 wifi->assoc_retry_count = 0;
4091 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
4092 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
4093 wifi->assoc_retry_count = 0;
4097 security = connman_network_get_string(network, "WiFi.Security");
4098 if (security && g_str_equal(security, "ieee8021x") == true &&
4099 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4100 wifi->assoc_retry_count = 0;
4104 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
4105 wifi->assoc_retry_count = 0;
4107 /* Honestly it's not an invalid-key error,
4108 * however QA team recommends that the invalid-key error
4109 * might be better to display for user experience.
4111 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
4120 static void interface_state(GSupplicantInterface *interface)
4122 struct connman_network *network;
4123 struct connman_device *device;
4124 struct wifi_data *wifi;
4125 GSupplicantState state = g_supplicant_interface_get_state(interface);
4129 wifi = g_supplicant_interface_get_data(interface);
4131 DBG("wifi %p interface state %d", wifi, state);
4136 device = wifi->device;
4140 if (state == G_SUPPLICANT_STATE_COMPLETED) {
4141 if (wifi->tethering_param) {
4142 g_free(wifi->tethering_param->ssid);
4143 g_free(wifi->tethering_param);
4144 wifi->tethering_param = NULL;
4147 if (wifi->tethering)
4148 stop_autoscan(device);
4151 if (g_supplicant_interface_get_ready(interface) &&
4152 !wifi->interface_ready) {
4153 wifi->interface_ready = true;
4154 finalize_interface_creation(wifi);
4157 network = wifi->network;
4162 case G_SUPPLICANT_STATE_SCANNING:
4163 if (wifi->connected)
4164 connman_network_set_connected(network, false);
4168 case G_SUPPLICANT_STATE_AUTHENTICATING:
4169 case G_SUPPLICANT_STATE_ASSOCIATING:
4170 #if defined TIZEN_EXT
4171 reset_autoscan(device);
4173 stop_autoscan(device);
4176 if (!wifi->connected)
4177 connman_network_set_associating(network, true);
4181 case G_SUPPLICANT_STATE_COMPLETED:
4182 #if defined TIZEN_EXT
4183 /* though it should be already reset: */
4184 reset_autoscan(device);
4186 wifi->assoc_retry_count = 0;
4188 wifi->scan_pending_network = NULL;
4190 /* should be cleared scanning flag */
4191 bool scanning = connman_device_get_scanning(device,
4192 CONNMAN_SERVICE_TYPE_WIFI);
4194 connman_device_set_scanning(device,
4195 CONNMAN_SERVICE_TYPE_WIFI, false);
4196 connman_device_unref(device);
4199 if (!wifi->automaxspeed_timeout) {
4200 DBG("Going to start signalpoll timer!!");
4201 int ret = network_signalpoll(wifi);
4203 DBG("Fail to get max speed !!");
4205 wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
4208 g_hash_table_remove_all(failed_bssids);
4210 /* though it should be already stopped: */
4211 stop_autoscan(device);
4214 if (!handle_wps_completion(interface, network, device, wifi))
4217 connman_network_set_connected(network, true);
4219 wifi->disconnect_code = 0;
4220 wifi->assoc_code = 0;
4221 wifi->load_shaping_retries = 0;
4224 case G_SUPPLICANT_STATE_DISCONNECTED:
4225 #if defined TIZEN_EXT
4226 connman_network_set_strength(network, 0);
4227 connman_network_set_maxspeed(network, 0);
4229 if (wifi->automaxspeed_timeout != 0) {
4230 g_source_remove(wifi->automaxspeed_timeout);
4231 wifi->automaxspeed_timeout = 0;
4232 DBG("Remove signalpoll timer!!");
4236 * If we're in one of the idle modes, we have
4237 * not started association yet and thus setting
4238 * those ones to FALSE could cancel an association
4241 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4243 if (is_idle_wps(interface, wifi))
4249 #if defined TIZEN_EXT
4250 if (handle_assoc_status_code(interface, wifi)) {
4251 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4252 guint bssid_length = 0;
4255 bssid_length = g_slist_length(bssid_list);
4257 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4258 network_connect(network);
4262 wifi->load_shaping_retries = 0;
4265 g_hash_table_remove_all(failed_bssids);
4267 if (handle_assoc_status_code(interface, wifi))
4271 /* If previous state was 4way-handshake, then
4272 * it's either: psk was incorrect and thus we retry
4273 * or if we reach the maximum retries we declare the
4275 if (handle_4way_handshake_failure(interface,
4279 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4280 switch (wifi->disconnect_code) {
4281 case 1: /* Unspecified reason */
4282 /* Let's assume it's because we got blocked */
4284 case 6: /* Class 2 frame received from nonauthenticated STA */
4285 connman_network_set_error(network,
4286 CONNMAN_NETWORK_ERROR_BLOCKED);
4293 #if defined TIZEN_EXT
4294 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4295 * Retry association until its retry count is expired */
4296 if (handle_wifi_assoc_retry(network, wifi) == true) {
4297 throw_wifi_scan(wifi->device, scan_callback);
4298 wifi->scan_pending_network = wifi->network;
4302 if(wifi->disconnect_code > 0){
4303 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4304 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4308 if (network != wifi->pending_network) {
4309 connman_network_set_connected(network, false);
4310 connman_network_set_associating(network, false);
4312 wifi->disconnecting = false;
4314 start_autoscan(device);
4318 case G_SUPPLICANT_STATE_INACTIVE:
4319 #if defined TIZEN_EXT
4320 if (handle_wps_completion(interface, network, device, wifi) == false)
4323 connman_network_set_associating(network, false);
4324 start_autoscan(device);
4328 case G_SUPPLICANT_STATE_UNKNOWN:
4329 case G_SUPPLICANT_STATE_DISABLED:
4330 case G_SUPPLICANT_STATE_ASSOCIATED:
4331 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4332 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4336 old_connected = wifi->connected;
4337 wifi->state = state;
4339 /* Saving wpa_s state policy:
4340 * If connected and if the state changes are roaming related:
4341 * --> We stay connected
4343 * --> We are connected
4345 * --> We are not connected
4348 case G_SUPPLICANT_STATE_AUTHENTICATING:
4349 case G_SUPPLICANT_STATE_ASSOCIATING:
4350 case G_SUPPLICANT_STATE_ASSOCIATED:
4351 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4352 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4353 if (wifi->connected)
4354 connman_warn("Probably roaming right now!"
4355 " Staying connected...");
4357 case G_SUPPLICANT_STATE_SCANNING:
4358 wifi->connected = false;
4361 start_autoscan(device);
4363 case G_SUPPLICANT_STATE_COMPLETED:
4364 wifi->connected = true;
4367 wifi->connected = false;
4374 static void interface_removed(GSupplicantInterface *interface)
4376 const char *ifname = g_supplicant_interface_get_ifname(interface);
4377 struct wifi_data *wifi;
4379 DBG("ifname %s", ifname);
4381 wifi = g_supplicant_interface_get_data(interface);
4383 #if defined TIZEN_EXT_WIFI_MESH
4384 if (wifi && wifi->mesh_interface) {
4385 DBG("Notify mesh interface remove");
4386 connman_mesh_notify_interface_remove(true);
4387 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4388 g_free(mesh_info->parent_ifname);
4389 g_free(mesh_info->ifname);
4390 g_free(mesh_info->identifier);
4392 wifi->mesh_interface = false;
4393 wifi->mesh_info = NULL;
4399 wifi->interface = NULL;
4401 if (wifi && wifi->tethering)
4404 if (!wifi || !wifi->device) {
4405 DBG("wifi interface already removed");
4409 connman_device_set_powered(wifi->device, false);
4411 check_p2p_technology();
4412 #if defined TIZEN_EXT_WIFI_MESH
4413 check_mesh_technology();
4417 static void set_device_type(const char *type, char dev_type[17])
4419 const char *oui = "0050F204";
4420 const char *category = "0001";
4421 const char *sub_category = "0000";
4423 if (!g_strcmp0(type, "handset")) {
4425 sub_category = "0005";
4426 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4427 sub_category = "0001";
4428 else if (!g_strcmp0(type, "server"))
4429 sub_category = "0002";
4430 else if (!g_strcmp0(type, "laptop"))
4431 sub_category = "0005";
4432 else if (!g_strcmp0(type, "desktop"))
4433 sub_category = "0006";
4434 else if (!g_strcmp0(type, "tablet"))
4435 sub_category = "0009";
4436 else if (!g_strcmp0(type, "watch"))
4439 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4442 static void p2p_support(GSupplicantInterface *interface)
4444 char dev_type[17] = {};
4445 const char *hostname;
4452 if (!g_supplicant_interface_has_p2p(interface))
4455 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4456 DBG("Could not register P2P technology driver");
4460 hostname = connman_utsname_get_hostname();
4462 hostname = "ConnMan";
4464 set_device_type(connman_machine_get_type(), dev_type);
4465 g_supplicant_interface_set_p2p_device_config(interface,
4466 hostname, dev_type);
4467 connman_peer_driver_register(&peer_driver);
4470 static void scan_started(GSupplicantInterface *interface)
4475 static void scan_finished(GSupplicantInterface *interface)
4477 #if defined TIZEN_EXT
4478 struct wifi_data *wifi;
4479 bool is_associating = false;
4480 static bool is_scanning = true;
4485 #if defined TIZEN_EXT
4486 wifi = g_supplicant_interface_get_data(interface);
4487 if (wifi && wifi->scan_pending_network) {
4488 network_connect(wifi->scan_pending_network);
4489 wifi->scan_pending_network = NULL;
4492 //service state - associating
4493 if(!wifi || !wifi->network)
4496 is_associating = connman_network_get_associating(wifi->network);
4497 if(is_associating && is_scanning){
4498 is_scanning = false;
4499 DBG("send scan for connecting");
4500 throw_wifi_scan(wifi->device, scan_callback);
4511 static void ap_create_fail(GSupplicantInterface *interface)
4513 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4516 if ((wifi->tethering) && (wifi->tethering_param)) {
4517 DBG("%s create AP fail \n",
4518 g_supplicant_interface_get_ifname(wifi->interface));
4520 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4521 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4522 wifi->tethering = false;
4524 ret = tech_set_tethering(wifi->tethering_param->technology,
4525 wifi->tethering_param->ssid->ssid,
4526 wifi->tethering_param->ssid->passphrase,
4527 wifi->bridge, true);
4529 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4530 connman_technology_tethering_notify(wifi_technology,false);
4533 g_free(wifi->tethering_param->ssid);
4534 g_free(wifi->tethering_param);
4535 wifi->tethering_param = NULL;
4539 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4541 unsigned char strength;
4543 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4544 #if !defined TIZEN_EXT
4552 #if defined TIZEN_EXT_WIFI_MESH
4553 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4555 GSupplicantInterface *interface;
4556 struct wifi_data *wifi;
4557 const char *name, *security;
4558 struct connman_mesh *connman_mesh;
4559 struct wifi_mesh_info *mesh_info;
4560 const unsigned char *bssid;
4561 const char *identifier;
4566 interface = g_supplicant_network_get_interface(supplicant_network);
4567 wifi = g_supplicant_interface_get_data(interface);
4568 if (!wifi || !wifi->mesh_interface) {
4569 DBG("Virtual Mesh interface not created");
4573 bssid = g_supplicant_network_get_bssid(supplicant_network);
4574 address = g_malloc0(19);
4575 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4576 bssid[2], bssid[3], bssid[4], bssid[5]);
4578 identifier = g_supplicant_network_get_identifier(supplicant_network);
4579 name = g_supplicant_network_get_name(supplicant_network);
4580 security = g_supplicant_network_get_security(supplicant_network);
4581 frequency = g_supplicant_network_get_frequency(supplicant_network);
4583 mesh_info = wifi->mesh_info;
4584 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4588 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4590 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4591 connman_mesh_set_name(connman_mesh, name);
4592 connman_mesh_set_security(connman_mesh, security);
4593 connman_mesh_set_frequency(connman_mesh, frequency);
4594 connman_mesh_set_address(connman_mesh, address);
4595 connman_mesh_set_index(connman_mesh, mesh_info->index);
4596 connman_mesh_set_strength(connman_mesh,
4597 calculate_strength(supplicant_network));
4598 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4600 ret = connman_mesh_register(connman_mesh);
4601 if (ret == -EALREADY)
4602 DBG("Mesh Peer is already registered");
4608 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4610 GSupplicantInterface *interface;
4611 struct wifi_data *wifi;
4612 struct connman_mesh *connman_mesh;
4613 struct wifi_mesh_info *mesh_info;
4614 const char *identifier;
4616 interface = g_supplicant_network_get_interface(supplicant_network);
4617 wifi = g_supplicant_interface_get_data(interface);
4618 if (!wifi || !wifi->mesh_interface) {
4619 DBG("Virtual Mesh interface not created");
4623 identifier = g_supplicant_network_get_identifier(supplicant_network);
4625 DBG("Failed to get Mesh Peer identifier");
4629 mesh_info = wifi->mesh_info;
4630 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4632 /* Do not unregister connected mesh peer */
4633 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4634 DBG("Mesh Peer %s is connected", identifier);
4637 DBG("Mesh Peer identifier %s removed", identifier);
4638 connman_mesh_unregister(connman_mesh);
4643 static void network_added(GSupplicantNetwork *supplicant_network)
4645 struct connman_network *network;
4646 GSupplicantInterface *interface;
4647 struct wifi_data *wifi;
4648 const char *name, *identifier, *security, *group, *mode;
4649 const unsigned char *ssid;
4650 unsigned int ssid_len;
4654 bool wps_advertizing;
4656 #if defined TIZEN_EXT
4657 GSList *vsie_list = NULL;
4658 const unsigned char *country_code;
4659 ieee80211_modes_e phy_mode;
4662 mode = g_supplicant_network_get_mode(supplicant_network);
4663 identifier = g_supplicant_network_get_identifier(supplicant_network);
4665 DBG("%s", identifier);
4667 if (!g_strcmp0(mode, "adhoc"))
4670 #if defined TIZEN_EXT_WIFI_MESH
4671 if (!g_strcmp0(mode, "mesh")) {
4672 mesh_peer_added(supplicant_network);
4677 interface = g_supplicant_network_get_interface(supplicant_network);
4678 wifi = g_supplicant_interface_get_data(interface);
4679 name = g_supplicant_network_get_name(supplicant_network);
4680 security = g_supplicant_network_get_security(supplicant_network);
4681 group = g_supplicant_network_get_identifier(supplicant_network);
4682 wps = g_supplicant_network_get_wps(supplicant_network);
4683 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4684 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4685 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4686 supplicant_network);
4691 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4693 network = connman_device_get_network(wifi->device, identifier);
4696 network = connman_network_create(identifier,
4697 CONNMAN_NETWORK_TYPE_WIFI);
4701 connman_network_set_index(network, wifi->index);
4703 if (connman_device_add_network(wifi->device, network) < 0) {
4704 connman_network_unref(network);
4708 wifi->networks = g_slist_prepend(wifi->networks, network);
4711 if (name && name[0] != '\0')
4712 connman_network_set_name(network, name);
4714 connman_network_set_blob(network, "WiFi.SSID",
4716 #if defined TIZEN_EXT
4717 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4719 connman_network_set_vsie_list(network, vsie_list);
4721 DBG("vsie_list is NULL");
4722 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4723 connman_network_set_countrycode(network, country_code);
4724 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4725 connman_network_set_phy_mode(network, phy_mode);
4727 connman_network_set_string(network, "WiFi.Security", security);
4728 connman_network_set_strength(network,
4729 calculate_strength(supplicant_network));
4730 connman_network_set_bool(network, "WiFi.WPS", wps);
4731 connman_network_set_bool(network, "WiFi.WPSAdvertising",
4735 /* Is AP advertizing for WPS association?
4736 * If so, we decide to use WPS by default */
4737 if (wps_ready && wps_pbc &&
4739 #if !defined TIZEN_EXT
4740 connman_network_set_bool(network, "WiFi.UseWPS", true);
4742 DBG("wps is activating by ap but ignore it.");
4746 connman_network_set_frequency(network,
4747 g_supplicant_network_get_frequency(supplicant_network));
4749 #if defined TIZEN_EXT
4750 connman_network_set_bssid(network,
4751 g_supplicant_network_get_bssid(supplicant_network));
4752 connman_network_set_maxrate(network,
4753 g_supplicant_network_get_maxrate(supplicant_network));
4754 connman_network_set_enc_mode(network,
4755 g_supplicant_network_get_enc_mode(supplicant_network));
4756 connman_network_set_rsn_mode(network,
4757 g_supplicant_network_get_rsn_mode(supplicant_network));
4758 connman_network_set_keymgmt(network,
4759 g_supplicant_network_get_keymgmt(supplicant_network));
4760 connman_network_set_bool(network, "WiFi.HS20AP",
4761 g_supplicant_network_is_hs20AP(supplicant_network));
4762 connman_network_set_bssid_list(network,
4763 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4765 connman_network_set_available(network, true);
4766 connman_network_set_string(network, "WiFi.Mode", mode);
4768 #if defined TIZEN_EXT
4773 connman_network_set_group(network, group);
4775 #if defined TIZEN_EXT
4776 if (wifi_first_scan == true)
4777 found_with_first_scan = true;
4780 if (wifi->hidden && ssid) {
4781 #if defined TIZEN_EXT
4782 if (network_security(wifi->hidden->security) ==
4783 network_security(security) &&
4785 if (!g_strcmp0(wifi->hidden->security, security) &&
4787 wifi->hidden->ssid_len == ssid_len &&
4788 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4789 connman_network_connect_hidden(network,
4790 wifi->hidden->identity,
4791 wifi->hidden->passphrase,
4792 wifi->hidden->user_data);
4793 wifi->hidden->user_data = NULL;
4794 hidden_free(wifi->hidden);
4795 wifi->hidden = NULL;
4800 static void network_removed(GSupplicantNetwork *network)
4802 GSupplicantInterface *interface;
4803 struct wifi_data *wifi;
4804 const char *name, *identifier;
4805 struct connman_network *connman_network;
4807 #if defined TIZEN_EXT_WIFI_MESH
4809 mode = g_supplicant_network_get_mode(network);
4810 if (!g_strcmp0(mode, "mesh")) {
4811 mesh_peer_removed(network);
4816 interface = g_supplicant_network_get_interface(network);
4817 wifi = g_supplicant_interface_get_data(interface);
4818 identifier = g_supplicant_network_get_identifier(network);
4819 name = g_supplicant_network_get_name(network);
4821 DBG("name %s", name);
4826 connman_network = connman_device_get_network(wifi->device, identifier);
4827 if (!connman_network)
4830 #if defined TIZEN_EXT
4831 if (connman_network == wifi->scan_pending_network)
4832 wifi->scan_pending_network = NULL;
4834 if (connman_network == wifi->pending_network)
4835 wifi->pending_network = NULL;
4837 if(connman_network_get_connecting(connman_network) == true){
4838 connman_network_set_connected(connman_network, false);
4842 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4844 connman_device_remove_network(wifi->device, connman_network);
4845 connman_network_unref(connman_network);
4848 static void network_changed(GSupplicantNetwork *network, const char *property)
4850 GSupplicantInterface *interface;
4851 struct wifi_data *wifi;
4852 const char *name, *identifier;
4853 struct connman_network *connman_network;
4856 #if defined TIZEN_EXT
4857 const unsigned char *bssid;
4858 unsigned int maxrate;
4861 const unsigned char *country_code;
4862 ieee80211_modes_e phy_mode;
4866 interface = g_supplicant_network_get_interface(network);
4867 wifi = g_supplicant_interface_get_data(interface);
4868 identifier = g_supplicant_network_get_identifier(network);
4869 name = g_supplicant_network_get_name(network);
4871 DBG("name %s", name);
4876 connman_network = connman_device_get_network(wifi->device, identifier);
4877 if (!connman_network)
4880 if (g_str_equal(property, "WPSCapabilities")) {
4884 bool wps_advertizing;
4886 wps = g_supplicant_network_get_wps(network);
4887 wps_pbc = g_supplicant_network_is_wps_pbc(network);
4888 wps_ready = g_supplicant_network_is_wps_active(network);
4890 g_supplicant_network_is_wps_advertizing(network);
4892 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4893 connman_network_set_bool(connman_network,
4894 "WiFi.WPSAdvertising", wps_advertizing);
4898 * Is AP advertizing for WPS association?
4899 * If so, we decide to use WPS by default
4901 if (wps_ready && wps_pbc && wps_advertizing)
4902 connman_network_set_bool(connman_network,
4903 "WiFi.UseWPS", true);
4906 update_needed = true;
4907 } else if (g_str_equal(property, "Signal")) {
4908 connman_network_set_strength(connman_network,
4909 calculate_strength(network));
4910 update_needed = true;
4912 update_needed = false;
4915 connman_network_update(connman_network);
4917 #if defined TIZEN_EXT
4918 bssid = g_supplicant_network_get_bssid(network);
4919 maxrate = g_supplicant_network_get_maxrate(network);
4920 frequency = g_supplicant_network_get_frequency(network);
4921 wps = g_supplicant_network_get_wps(network);
4922 phy_mode = g_supplicant_network_get_phy_mode(network);
4924 connman_network_set_bssid(connman_network, bssid);
4925 connman_network_set_maxrate(connman_network, maxrate);
4926 connman_network_set_frequency(connman_network, frequency);
4927 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4928 country_code = g_supplicant_network_get_countrycode(network);
4929 connman_network_set_countrycode(connman_network, country_code);
4930 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4931 connman_network_set_bssid_list(connman_network, bssid_list);
4932 connman_network_set_phy_mode(connman_network, phy_mode);
4934 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4935 connman_network_get_associating(connman_network))
4936 network_connect(connman_network);
4940 static void network_associated(GSupplicantNetwork *network)
4942 GSupplicantInterface *interface;
4943 struct wifi_data *wifi;
4944 struct connman_network *connman_network;
4945 const char *identifier;
4949 interface = g_supplicant_network_get_interface(network);
4953 wifi = g_supplicant_interface_get_data(interface);
4957 /* P2P networks must not be treated as WiFi networks */
4958 if (wifi->p2p_connecting || wifi->p2p_device)
4961 identifier = g_supplicant_network_get_identifier(network);
4963 connman_network = connman_device_get_network(wifi->device, identifier);
4964 if (!connman_network)
4967 if (wifi->network) {
4968 if (wifi->network == connman_network)
4972 * This should never happen, we got associated with
4973 * a network different than the one we were expecting.
4975 DBG("Associated to %p while expecting %p",
4976 connman_network, wifi->network);
4978 connman_network_set_associating(wifi->network, false);
4981 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4983 wifi->network = connman_network_ref(connman_network);
4987 * Interface state changes callback (interface_state) is always
4988 * called before network_associated callback thus we need to call
4989 * interface_state again in order to process the new state now that
4990 * we have the network properly set.
4992 interface_state(interface);
4995 static void sta_authorized(GSupplicantInterface *interface,
4998 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5000 DBG("wifi %p station %s authorized", wifi, addr);
5002 if (!wifi || !wifi->tethering)
5005 __connman_tethering_client_register(addr);
5008 static void sta_deauthorized(GSupplicantInterface *interface,
5011 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5013 DBG("wifi %p station %s deauthorized", wifi, addr);
5015 if (!wifi || !wifi->tethering)
5018 __connman_tethering_client_unregister(addr);
5021 static void apply_peer_services(GSupplicantPeer *peer,
5022 struct connman_peer *connman_peer)
5024 const unsigned char *data;
5029 connman_peer_reset_services(connman_peer);
5031 data = g_supplicant_peer_get_widi_ies(peer, &length);
5033 connman_peer_add_service(connman_peer,
5034 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
5038 static void peer_found(GSupplicantPeer *peer)
5040 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5041 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5042 struct connman_peer *connman_peer;
5043 const char *identifier, *name;
5046 #if defined TIZEN_EXT
5050 identifier = g_supplicant_peer_get_identifier(peer);
5051 name = g_supplicant_peer_get_name(peer);
5053 DBG("ident: %s", identifier);
5055 connman_peer = connman_peer_get(wifi->device, identifier);
5059 connman_peer = connman_peer_create(identifier);
5060 connman_peer_set_name(connman_peer, name);
5061 connman_peer_set_device(connman_peer, wifi->device);
5062 apply_peer_services(peer, connman_peer);
5064 ret = connman_peer_register(connman_peer);
5065 if (ret < 0 && ret != -EALREADY)
5066 connman_peer_unref(connman_peer);
5068 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
5071 static void peer_lost(GSupplicantPeer *peer)
5073 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5074 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5075 struct connman_peer *connman_peer;
5076 const char *identifier;
5081 identifier = g_supplicant_peer_get_identifier(peer);
5083 DBG("ident: %s", identifier);
5085 connman_peer = connman_peer_get(wifi->device, identifier);
5087 if (wifi->p2p_connecting &&
5088 wifi->pending_peer == connman_peer) {
5089 peer_connect_timeout(wifi);
5091 connman_peer_unregister(connman_peer);
5092 connman_peer_unref(connman_peer);
5095 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
5098 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
5100 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5101 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5102 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
5103 struct connman_peer *connman_peer;
5104 const char *identifier;
5106 identifier = g_supplicant_peer_get_identifier(peer);
5108 DBG("ident: %s", identifier);
5113 connman_peer = connman_peer_get(wifi->device, identifier);
5118 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
5119 apply_peer_services(peer, connman_peer);
5120 connman_peer_services_changed(connman_peer);
5122 case G_SUPPLICANT_PEER_GROUP_CHANGED:
5123 if (!g_supplicant_peer_is_in_a_group(peer))
5124 p_state = CONNMAN_PEER_STATE_IDLE;
5126 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
5128 case G_SUPPLICANT_PEER_GROUP_STARTED:
5130 case G_SUPPLICANT_PEER_GROUP_FINISHED:
5131 p_state = CONNMAN_PEER_STATE_IDLE;
5133 case G_SUPPLICANT_PEER_GROUP_JOINED:
5134 connman_peer_set_iface_address(connman_peer,
5135 g_supplicant_peer_get_iface_address(peer));
5137 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
5138 p_state = CONNMAN_PEER_STATE_IDLE;
5140 case G_SUPPLICANT_PEER_GROUP_FAILED:
5141 if (g_supplicant_peer_has_requested_connection(peer))
5142 p_state = CONNMAN_PEER_STATE_IDLE;
5144 p_state = CONNMAN_PEER_STATE_FAILURE;
5148 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
5149 p_state == CONNMAN_PEER_STATE_FAILURE) {
5150 if (wifi->p2p_connecting
5151 && connman_peer == wifi->pending_peer)
5152 peer_cancel_timeout(wifi);
5154 p_state = CONNMAN_PEER_STATE_UNKNOWN;
5157 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
5160 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
5161 GSupplicantInterface *g_iface;
5162 struct wifi_data *g_wifi;
5164 g_iface = g_supplicant_peer_get_group_interface(peer);
5168 g_wifi = g_supplicant_interface_get_data(g_iface);
5172 connman_peer_set_as_master(connman_peer,
5173 !g_supplicant_peer_is_client(peer));
5174 connman_peer_set_sub_device(connman_peer, g_wifi->device);
5177 * If wpa_supplicant didn't create a dedicated p2p-group
5178 * interface then mark this interface as p2p_device to avoid
5179 * scan and auto-scan are launched on it while P2P is connected.
5181 if (!g_list_find(p2p_iface_list, g_wifi))
5182 wifi->p2p_device = true;
5185 connman_peer_set_state(connman_peer, p_state);
5188 static void peer_request(GSupplicantPeer *peer)
5190 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5191 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5192 struct connman_peer *connman_peer;
5193 const char *identifier;
5195 #if defined TIZEN_EXT
5200 identifier = g_supplicant_peer_get_identifier(peer);
5202 DBG("ident: %s", identifier);
5204 connman_peer = connman_peer_get(wifi->device, identifier);
5208 connman_peer_request_connection(connman_peer);
5211 #if defined TIZEN_EXT
5212 static void system_power_off(void)
5215 struct wifi_data *wifi;
5216 struct connman_service *service;
5217 struct connman_ipconfig *ipconfig_ipv4;
5219 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
5220 for (list = iface_list; list; list = list->next) {
5223 if (wifi->network != NULL) {
5224 service = connman_service_lookup_from_network(wifi->network);
5225 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5226 __connman_dhcp_stop(ipconfig_ipv4);
5232 static void network_merged(GSupplicantNetwork *network)
5234 GSupplicantInterface *interface;
5235 GSupplicantState state;
5236 struct wifi_data *wifi;
5237 const char *identifier;
5238 struct connman_network *connman_network;
5242 interface = g_supplicant_network_get_interface(network);
5246 state = g_supplicant_interface_get_state(interface);
5247 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5250 wifi = g_supplicant_interface_get_data(interface);
5254 identifier = g_supplicant_network_get_identifier(network);
5256 connman_network = connman_device_get_network(wifi->device, identifier);
5257 if (!connman_network)
5260 DBG("merged identifier %s", identifier);
5262 if (wifi->connected == FALSE) {
5264 case G_SUPPLICANT_STATE_AUTHENTICATING:
5265 case G_SUPPLICANT_STATE_ASSOCIATING:
5266 case G_SUPPLICANT_STATE_ASSOCIATED:
5267 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5268 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5269 connman_network_set_associating(connman_network, TRUE);
5271 case G_SUPPLICANT_STATE_COMPLETED:
5272 connman_network_set_connected(connman_network, TRUE);
5275 DBG("Not handled the state : %d", state);
5280 ishs20AP = g_supplicant_network_is_hs20AP(network);
5283 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5284 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5285 connman_network_set_string(connman_network, "WiFi.EAP",
5287 connman_network_set_string(connman_network, "WiFi.Identity",
5288 g_supplicant_network_get_identity(network));
5289 connman_network_set_string(connman_network, "WiFi.Phase2",
5290 g_supplicant_network_get_phase2(network));
5295 wifi->network = connman_network;
5298 static void assoc_failed(void *user_data)
5300 struct connman_network *network = user_data;
5301 connman_network_set_associating(network, false);
5305 static void debug(const char *str)
5307 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5308 connman_debug("%s", str);
5311 static void disconnect_reasoncode(GSupplicantInterface *interface,
5314 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5317 wifi->disconnect_code = reasoncode;
5321 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5323 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5326 wifi->assoc_code = status_code;
5330 static const GSupplicantCallbacks callbacks = {
5331 .system_ready = system_ready,
5332 .system_killed = system_killed,
5333 .interface_added = interface_added,
5334 .interface_state = interface_state,
5335 .interface_removed = interface_removed,
5336 .p2p_support = p2p_support,
5337 .scan_started = scan_started,
5338 .scan_finished = scan_finished,
5339 .ap_create_fail = ap_create_fail,
5340 .network_added = network_added,
5341 .network_removed = network_removed,
5342 .network_changed = network_changed,
5343 .network_associated = network_associated,
5344 .sta_authorized = sta_authorized,
5345 .sta_deauthorized = sta_deauthorized,
5346 .peer_found = peer_found,
5347 .peer_lost = peer_lost,
5348 .peer_changed = peer_changed,
5349 .peer_request = peer_request,
5350 #if defined TIZEN_EXT
5351 .system_power_off = system_power_off,
5352 .network_merged = network_merged,
5353 .assoc_failed = assoc_failed,
5356 .disconnect_reasoncode = disconnect_reasoncode,
5357 .assoc_status_code = assoc_status_code,
5358 #if defined TIZEN_EXT_WIFI_MESH
5359 .mesh_support = mesh_support,
5360 .mesh_group_started = mesh_group_started,
5361 .mesh_group_removed = mesh_group_removed,
5362 .mesh_peer_connected = mesh_peer_connected,
5363 .mesh_peer_disconnected = mesh_peer_disconnected,
5368 static int tech_probe(struct connman_technology *technology)
5370 wifi_technology = technology;
5375 static void tech_remove(struct connman_technology *technology)
5377 wifi_technology = NULL;
5380 static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
5382 GSupplicantSSID *ap;
5384 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5388 ap->mode = G_SUPPLICANT_MODE_MASTER;
5389 #if defined TIZEN_EXT
5390 ap->ssid = (void *) ssid;
5394 ap->ssid_len = strlen(ssid);
5398 if (!passphrase || strlen(passphrase) == 0) {
5399 ap->security = G_SUPPLICANT_SECURITY_NONE;
5400 ap->passphrase = NULL;
5402 ap->security = G_SUPPLICANT_SECURITY_PSK;
5403 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5404 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5405 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5406 ap->passphrase = passphrase;
5412 static void ap_start_callback(int result, GSupplicantInterface *interface,
5415 struct wifi_tethering_info *info = user_data;
5417 DBG("result %d index %d bridge %s",
5418 result, info->wifi->index, info->wifi->bridge);
5420 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5421 connman_inet_remove_from_bridge(info->wifi->index,
5422 info->wifi->bridge);
5424 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5425 connman_technology_tethering_notify(info->technology, false);
5426 g_free(info->wifi->tethering_param->ssid);
5427 g_free(info->wifi->tethering_param);
5428 info->wifi->tethering_param = NULL;
5432 g_free(info->ifname);
5436 static void ap_create_callback(int result,
5437 GSupplicantInterface *interface,
5440 struct wifi_tethering_info *info = user_data;
5442 DBG("result %d ifname %s", result,
5443 g_supplicant_interface_get_ifname(interface));
5445 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5446 connman_inet_remove_from_bridge(info->wifi->index,
5447 info->wifi->bridge);
5449 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5450 connman_technology_tethering_notify(info->technology, false);
5451 g_free(info->wifi->tethering_param->ssid);
5452 g_free(info->wifi->tethering_param);
5453 info->wifi->tethering_param = NULL;
5457 g_free(info->ifname);
5463 info->wifi->interface = interface;
5464 g_supplicant_interface_set_data(interface, info->wifi);
5466 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5467 connman_error("Failed to set interface ap_scan property");
5469 g_supplicant_interface_connect(interface, info->ssid,
5470 ap_start_callback, info);
5473 static void sta_remove_callback(int result,
5474 GSupplicantInterface *interface,
5477 struct wifi_tethering_info *info = user_data;
5478 const char *driver = connman_option_get_string("wifi");
5480 DBG("ifname %s result %d ", info->ifname, result);
5482 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5483 info->wifi->tethering = false;
5484 connman_technology_tethering_notify(info->technology, false);
5486 g_free(info->ifname);
5490 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5491 g_free(info->wifi->tethering_param->ssid);
5492 g_free(info->wifi->tethering_param);
5493 info->wifi->tethering_param = NULL;
5498 info->wifi->interface = NULL;
5500 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5505 static int enable_wifi_tethering(struct connman_technology *technology,
5506 const char *bridge, const char *identifier,
5507 const char *passphrase, bool available)
5510 GSupplicantInterface *interface;
5511 struct wifi_data *wifi;
5512 struct wifi_tethering_info *info;
5517 for (list = iface_list; list; list = list->next) {
5520 DBG("wifi %p network %p pending_network %p", wifi,
5521 wifi->network, wifi->pending_network);
5523 interface = wifi->interface;
5528 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5532 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5533 DBG("%s does not support AP mode (detected)", ifname);
5537 mode = g_supplicant_interface_get_mode(interface);
5538 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5539 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5540 DBG("%s does not support AP mode (capability)", ifname);
5544 if (wifi->network && available)
5547 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5551 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5552 if (!wifi->tethering_param) {
5558 info->technology = technology;
5559 info->wifi->bridge = bridge;
5560 info->ssid = ssid_ap_init(identifier, passphrase);
5564 info->ifname = g_strdup(ifname);
5566 wifi->tethering_param->technology = technology;
5567 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5568 if (!wifi->tethering_param->ssid)
5571 info->wifi->tethering = true;
5572 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5574 berr = connman_technology_tethering_notify(technology, true);
5578 err = g_supplicant_interface_remove(interface,
5579 sta_remove_callback,
5582 DBG("tethering wifi %p ifname %s", wifi, ifname);
5587 g_free(info->ifname);
5590 g_free(wifi->tethering_param);
5591 wifi->tethering_param = NULL;
5594 * Remove bridge if it was correctly created but remove
5595 * operation failed. Instead, if bridge creation failed then
5596 * break out and do not try again on another interface,
5597 * bridge set-up does not depend on it.
5600 connman_technology_tethering_notify(technology, false);
5608 static int tech_set_tethering(struct connman_technology *technology,
5609 const char *identifier, const char *passphrase,
5610 const char *bridge, bool enabled)
5613 struct wifi_data *wifi;
5619 for (list = iface_list; list; list = list->next) {
5622 if (wifi->tethering) {
5623 wifi->tethering = false;
5625 connman_inet_remove_from_bridge(wifi->index,
5627 wifi->bridged = false;
5631 connman_technology_tethering_notify(technology, false);
5636 DBG("trying tethering for available devices");
5637 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5641 DBG("trying tethering for any device");
5642 err = enable_wifi_tethering(technology, bridge, identifier,
5649 static void regdom_callback(int result, const char *alpha2, void *user_data)
5653 if (!wifi_technology)
5659 connman_technology_regdom_notify(wifi_technology, alpha2);
5662 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5664 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5667 static struct connman_technology_driver tech_driver = {
5669 .type = CONNMAN_SERVICE_TYPE_WIFI,
5670 .probe = tech_probe,
5671 .remove = tech_remove,
5672 .set_tethering = tech_set_tethering,
5673 .set_regdom = tech_set_regdom,
5676 static int wifi_init(void)
5680 err = connman_network_driver_register(&network_driver);
5684 err = g_supplicant_register(&callbacks);
5686 connman_network_driver_unregister(&network_driver);
5690 err = connman_technology_driver_register(&tech_driver);
5692 g_supplicant_unregister(&callbacks);
5693 connman_network_driver_unregister(&network_driver);
5697 #if defined TIZEN_EXT
5698 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5703 static void wifi_exit(void)
5707 connman_technology_driver_unregister(&tech_driver);
5709 g_supplicant_unregister(&callbacks);
5711 connman_network_driver_unregister(&network_driver);
5713 #if defined TIZEN_EXT
5714 g_hash_table_unref(failed_bssids);
5718 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5719 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)