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 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
41 #define IFF_LOWER_UP 0x10000
44 #include <dbus/dbus.h>
47 #define CONNMAN_API_SUBJECT_TO_CHANGE
48 #include <connman/plugin.h>
49 #include <connman/inet.h>
50 #include <connman/device.h>
51 #include <connman/rtnl.h>
52 #include <connman/technology.h>
53 #include <connman/service.h>
54 #include <connman/peer.h>
55 #include <connman/log.h>
56 #include <connman/storage.h>
57 #include <include/setting.h>
58 #include <connman/provision.h>
59 #include <connman/utsname.h>
60 #include <connman/machine.h>
61 #include <connman/tethering.h>
63 #include <gsupplicant/gsupplicant.h>
65 #include "src/shared/util.h"
67 #define CLEANUP_TIMEOUT 8 /* in seconds */
68 #define INACTIVE_TIMEOUT 12 /* in seconds */
69 #define FAVORITE_MAXIMUM_RETRIES 2
71 #define BGSCAN_DEFAULT "simple:30:-65:300"
72 #define AUTOSCAN_EXPONENTIAL "exponential:3:300"
73 #define AUTOSCAN_SINGLE "single:3"
74 #define SCAN_MAX_DURATION 10
76 #define P2P_FIND_TIMEOUT 30
77 #define P2P_CONNECTION_TIMEOUT 100
78 #define P2P_LISTEN_PERIOD 500
79 #define P2P_LISTEN_INTERVAL 2000
81 #define ASSOC_STATUS_AUTH_TIMEOUT 16
82 #define ASSOC_STATUS_NO_CLIENT 17
84 #define LOAD_SHAPING_MAX_RETRIES 7
86 #define LOAD_SHAPING_MAX_RETRIES 3
90 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
92 /* Wi-Fi Signal Strength (for 2.4G (dB))
96 * Very weak : -83 ~ -88
99 * Wi-Fi Signal Strength (for 5G (dB))
103 * Very weak : -83 ~ -88
106 #define RSSI_LEVEL_2_5G -77
107 #define RSSI_LEVEL_2_2_4G -75
108 #define RSSI_LEVEL_3_5G -68
109 #define RSSI_LEVEL_3_2_4G -64
110 #define ROAM_SCAN_INTERVAL 60 /* 60 seconds */
112 static int min_snr = 0;
113 static int min_rssi_2_4GHz = 0;
114 static int min_rssi_5GHz = 0;
117 static struct connman_technology *wifi_technology = NULL;
118 static struct connman_technology *p2p_technology = NULL;
120 #if defined TIZEN_EXT
121 static GSupplicantState assoc_last_state = G_SUPPLICANT_STATE_UNKNOWN;
124 enum wifi_ap_capability{
126 WIFI_AP_SUPPORTED = 1,
127 WIFI_AP_NOT_SUPPORTED = 2,
130 enum wifi_scanning_type {
131 WIFI_SCANNING_UNKNOWN = 0,
132 WIFI_SCANNING_PASSIVE = 1,
133 WIFI_SCANNING_ACTIVE = 2,
136 struct hidden_params {
138 unsigned int ssid_len;
140 char *anonymous_identity;
142 char *altsubject_match;
143 char *domain_suffix_match;
147 GSupplicantScanParams *scan_params;
152 * Used for autoscan "emulation".
153 * Should be removed when wpa_s autoscan support will be by default.
155 struct autoscan_params {
159 unsigned int timeout;
162 struct wifi_tethering_info {
163 struct wifi_data *wifi;
164 struct connman_technology *technology;
166 GSupplicantSSID *ssid;
171 struct connman_device *device;
172 struct connman_network *network;
173 struct connman_network *pending_network;
175 GSupplicantInterface *interface;
176 GSupplicantState state;
180 enum wifi_ap_capability ap_supported;
182 bool interface_ready;
188 int load_shaping_retries;
189 struct hidden_params *hidden;
190 bool postpone_hidden;
191 struct wifi_tethering_info *tethering_param;
193 * autoscan "emulation".
195 struct autoscan_params *autoscan;
196 enum wifi_scanning_type scanning_type;
197 GSupplicantScanParams *scan_params;
198 unsigned int p2p_find_timeout;
199 unsigned int p2p_connection_timeout;
200 struct connman_peer *pending_peer;
205 #if defined TIZEN_EXT
206 int assoc_retry_count;
207 struct connman_network *scan_pending_network;
208 bool allow_full_scan;
209 unsigned int automaxspeed_timeout;
210 GSupplicantScanParams *hidden_scan_params;
211 unsigned int mac_policy;
212 unsigned int preassoc_mac_policy;
213 unsigned int mac_lifetime;
217 #if defined TIZEN_EXT_WIFI_MESH
219 struct wifi_mesh_info *mesh_info;
223 struct wifi_network {
224 unsigned int keymgmt;
227 struct disconnect_data {
228 struct wifi_data *wifi;
229 struct connman_network *network;
232 #if defined TIZEN_EXT
236 #define TIZEN_ASSOC_RETRY_COUNT 4
238 static gboolean wifi_first_scan = false;
239 static gboolean found_with_first_scan = false;
240 static gboolean is_wifi_notifier_registered = false;
241 static GHashTable *failed_bssids = NULL;
242 static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
245 static GList *iface_list = NULL;
247 static GList *pending_wifi_device = NULL;
248 static GList *p2p_iface_list = NULL;
249 static bool wfd_service_registered = false;
251 static void start_autoscan(struct connman_device *device);
252 static int tech_set_tethering(struct connman_technology *technology,
253 const char *bridge, bool enabled);
255 #if defined TIZEN_EXT
256 #define NETCONFIG_SERVICE "net.netconfig"
257 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
258 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
260 struct enc_method_call_data {
261 DBusConnection *connection;
262 struct connman_network *network;
265 static struct enc_method_call_data encrypt_request_data;
267 static GSupplicantSecurity network_security(const char *security);
269 static void encryption_request_reply(DBusPendingCall *call,
274 DBusMessageIter args;
276 struct connman_service *service;
277 gchar* encrypted_value = NULL;
278 struct connman_network *network = encrypt_request_data.network;
282 reply = dbus_pending_call_steal_reply(call);
284 dbus_error_init(&error);
285 if (dbus_set_error_from_message(&error, reply)) {
286 DBG("send_encryption_request() %s %s", error.name, error.message);
287 dbus_error_free(&error);
291 if (dbus_message_iter_init(reply, &args) == FALSE)
294 dbus_message_iter_get_basic(&args, &out_data);
296 encrypted_value = g_strdup((const gchar *)out_data);
297 service = connman_service_lookup_from_network(network);
300 DBG("encryption result: no service");
304 if (connman_service_get_favorite(service)) {
305 __connman_service_set_passphrase(service, encrypted_value);
306 __connman_service_save(service);
308 connman_network_set_string(network, "WiFi.Passphrase",
311 DBG("encryption result: succeeded");
314 dbus_message_unref(reply);
315 dbus_pending_call_unref(call);
316 dbus_connection_unref(encrypt_request_data.connection);
317 g_free(encrypted_value);
319 encrypt_request_data.connection = NULL;
320 encrypt_request_data.network = NULL;
323 static int send_encryption_request(const char *passphrase,
324 struct connman_network *network)
326 DBusConnection *connection = NULL;
327 DBusMessage *msg = NULL;
328 DBusPendingCall *call;
331 DBG("Invalid parameter");
335 connection = connman_dbus_get_connection();
337 DBG("dbus connection does not exist");
341 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
342 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
344 dbus_connection_unref(connection);
348 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
351 if (!dbus_connection_send_with_reply(connection, msg,
352 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
353 dbus_message_unref(msg);
354 dbus_connection_unref(connection);
359 dbus_message_unref(msg);
360 dbus_connection_unref(connection);
364 encrypt_request_data.connection = connection;
365 encrypt_request_data.network = network;
367 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
368 dbus_message_unref(msg);
374 static int p2p_tech_probe(struct connman_technology *technology)
376 p2p_technology = technology;
381 static void p2p_tech_remove(struct connman_technology *technology)
383 p2p_technology = NULL;
386 static struct connman_technology_driver p2p_tech_driver = {
388 .type = CONNMAN_SERVICE_TYPE_P2P,
389 .probe = p2p_tech_probe,
390 .remove = p2p_tech_remove,
393 static bool is_p2p_connecting(void)
397 for (list = iface_list; list; list = list->next) {
398 struct wifi_data *wifi = list->data;
400 if (wifi->p2p_connecting)
407 static void add_pending_wifi_device(struct wifi_data *wifi)
409 if (g_list_find(pending_wifi_device, wifi))
412 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
415 #if defined TIZEN_EXT_WIFI_MESH
416 struct wifi_mesh_info {
417 struct wifi_data *wifi;
418 GSupplicantInterface *interface;
419 struct connman_mesh *mesh;
426 struct mesh_change_peer_status_info {
428 enum connman_mesh_peer_status peer_status;
429 mesh_change_peer_status_cb_t callback;
433 static struct connman_technology_driver mesh_tech_driver = {
435 .type = CONNMAN_SERVICE_TYPE_MESH,
438 static void mesh_interface_create_callback(int result,
439 GSupplicantInterface *interface,
442 struct wifi_mesh_info *mesh_info = user_data;
443 struct wifi_data *wifi;
444 bool success = false;
446 DBG("result %d ifname %s, mesh_info %p", result,
447 g_supplicant_interface_get_ifname(interface),
450 if (result < 0 || !mesh_info)
453 wifi = mesh_info->wifi;
455 mesh_info->interface = interface;
456 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
457 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
458 DBG("Mesh Interface identifier %s", mesh_info->identifier);
459 wifi->mesh_interface = true;
460 wifi->mesh_info = mesh_info;
461 g_supplicant_interface_set_data(interface, wifi);
465 connman_mesh_notify_interface_create(success);
468 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
471 struct wifi_data *wifi;
472 struct wifi_mesh_info *mesh_info;
473 const char *wifi_ifname;
474 bool parent_found = false;
475 const char *driver = "nl80211";
477 for (list = iface_list; list; list = list->next) {
480 if (!g_supplicant_interface_has_mesh(wifi->interface))
483 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
487 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
494 DBG("Parent interface %s doesn't exist", parent_ifname);
498 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
502 mesh_info->wifi = wifi;
503 mesh_info->ifname = g_strdup(ifname);
504 mesh_info->parent_ifname = g_strdup(parent_ifname);
506 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
507 mesh_interface_create_callback, mesh_info);
511 static void mesh_interface_remove_callback(int result,
512 GSupplicantInterface *interface,
515 struct wifi_data *wifi = user_data;
516 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
517 bool success = false;
519 DBG("result %d mesh_info %p", result, mesh_info);
521 if (result < 0 || !mesh_info)
524 mesh_info->interface = NULL;
525 g_free(mesh_info->parent_ifname);
526 g_free(mesh_info->ifname);
527 g_free(mesh_info->identifier);
529 wifi->mesh_interface = false;
530 wifi->mesh_info = NULL;
534 connman_mesh_notify_interface_remove(success);
537 static int remove_mesh_interface(const char *ifname)
540 struct wifi_data *wifi;
541 struct wifi_mesh_info *mesh_info;
542 bool mesh_if_found = false;
545 for (list = iface_list; list; list = list->next) {
548 if (wifi->mesh_interface) {
549 mesh_if_found = true;
554 if (!mesh_if_found) {
555 DBG("Mesh interface %s doesn't exist", ifname);
559 mesh_info = wifi->mesh_info;
560 ret = g_supplicant_interface_remove(mesh_info->interface,
561 mesh_interface_remove_callback, wifi);
568 static void mesh_disconnect_callback(int result,
569 GSupplicantInterface *interface, void *user_data)
571 struct connman_mesh *mesh = user_data;
573 DBG("result %d interface %p mesh %p", result, interface, mesh);
576 static int mesh_peer_disconnect(struct connman_mesh *mesh)
579 struct wifi_data *wifi;
580 struct wifi_mesh_info *mesh_info;
581 bool mesh_if_found = false;
582 GSupplicantInterface *interface;
584 for (list = iface_list; list; list = list->next) {
587 if (wifi->mesh_interface) {
588 mesh_if_found = true;
593 if (!mesh_if_found) {
594 DBG("Mesh interface is not created");
598 mesh_info = wifi->mesh_info;
600 interface = mesh_info->interface;
601 return g_supplicant_interface_disconnect(interface,
602 mesh_disconnect_callback, mesh);
605 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
608 struct connman_mesh *mesh = user_data;
609 DBG("mesh %p result %d", mesh, result);
612 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
614 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
617 static GSupplicantSecurity mesh_network_security(const char *security)
619 if (g_str_equal(security, "none"))
620 return G_SUPPLICANT_SECURITY_NONE;
621 else if (g_str_equal(security, "sae"))
622 return G_SUPPLICANT_SECURITY_SAE;
624 return G_SUPPLICANT_SECURITY_UNKNOWN;
627 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
630 const char *security;
635 memset(ssid, 0, sizeof(*ssid));
636 ssid->mode = G_SUPPLICANT_MODE_MESH;
638 security = connman_mesh_get_security(mesh);
639 ssid->security = mesh_network_security(security);
641 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
642 ssid->passphrase = connman_mesh_get_passphrase(mesh);
644 ssid->freq = connman_mesh_get_frequency(mesh);
645 name = connman_mesh_get_name(mesh);
647 ssid->ssid_len = strlen(name);
648 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
649 memcpy(ssid->ssid, name, ssid->ssid_len);
654 static int mesh_peer_connect(struct connman_mesh *mesh)
657 struct wifi_data *wifi;
658 struct wifi_mesh_info *mesh_info;
659 bool mesh_if_found = false;
660 GSupplicantInterface *interface;
661 GSupplicantSSID *ssid;
663 for (list = iface_list; list; list = list->next) {
666 if (wifi->mesh_interface) {
667 mesh_if_found = true;
672 if (!mesh_if_found) {
673 DBG("Mesh interface is not created");
677 mesh_info = wifi->mesh_info;
679 interface = mesh_info->interface;
681 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
685 mesh_info->mesh = mesh;
687 mesh_ssid_init(ssid, mesh);
688 return g_supplicant_interface_connect(interface, ssid,
689 mesh_connect_callback, mesh);
692 static void mesh_peer_change_status_callback(int result,
693 GSupplicantInterface *interface,
696 struct mesh_change_peer_status_info *data = user_data;
698 DBG("result %d Peer Status %d", result, data->peer_status);
700 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
701 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
702 connman_mesh_remove_connected_peer(data->peer_address, 52);
706 data->callback(result, data->user_data);
708 g_free(data->peer_address);
713 static int mesh_change_peer_status(const char *peer_address,
714 enum connman_mesh_peer_status status,
715 mesh_change_peer_status_cb_t callback, void *user_data)
718 struct wifi_data *wifi;
719 struct wifi_mesh_info *mesh_info;
720 bool mesh_if_found = false;
721 GSupplicantInterface *interface;
722 struct mesh_change_peer_status_info *data;
725 for (list = iface_list; list; list = list->next) {
728 if (wifi->mesh_interface) {
729 mesh_if_found = true;
734 if (!mesh_if_found) {
735 DBG("Mesh interface is not created");
739 mesh_info = wifi->mesh_info;
741 interface = mesh_info->interface;
744 case CONNMAN_MESH_PEER_ADD:
745 method = "MeshPeerAdd";
747 case CONNMAN_MESH_PEER_REMOVE:
748 method = "MeshPeerRemove";
751 DBG("Invalid method");
755 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
757 DBG("Memory allocation failed");
761 data->peer_address = g_strdup(peer_address);
762 data->peer_status = status;
763 data->callback = callback;
764 data->user_data = user_data;
766 return g_supplicant_interface_mesh_peer_change_status(interface,
767 mesh_peer_change_status_callback, peer_address, method,
771 static struct connman_mesh_driver mesh_driver = {
772 .add_interface = add_mesh_interface,
773 .remove_interface = remove_mesh_interface,
774 .connect = mesh_peer_connect,
775 .disconnect = mesh_peer_disconnect,
776 .change_peer_status = mesh_change_peer_status,
779 static void mesh_support(GSupplicantInterface *interface)
783 if (!g_supplicant_interface_has_mesh(interface))
786 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
787 DBG("Could not register Mesh technology driver");
791 connman_mesh_driver_register(&mesh_driver);
794 static void check_mesh_technology(void)
796 bool mesh_exists = false;
799 for (list = iface_list; list; list = list->next) {
800 struct wifi_data *w = list->data;
803 g_supplicant_interface_has_mesh(w->interface))
808 connman_technology_driver_unregister(&mesh_tech_driver);
809 connman_mesh_driver_unregister(&mesh_driver);
813 static void mesh_group_started(GSupplicantInterface *interface)
815 struct wifi_data *wifi;
816 struct wifi_mesh_info *mesh_info;
817 struct connman_mesh *mesh;
818 const unsigned char *ssid;
819 unsigned int ssid_len;
822 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
823 memcpy(name, ssid, ssid_len);
824 name[ssid_len] = '\0';
825 DBG("name %s", name);
826 wifi = g_supplicant_interface_get_data(interface);
827 DBG("wifi %p", wifi);
832 mesh_info = wifi->mesh_info;
836 mesh = mesh_info->mesh;
840 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
843 static void mesh_group_removed(GSupplicantInterface *interface)
845 struct wifi_data *wifi;
846 struct wifi_mesh_info *mesh_info;
847 struct connman_mesh *mesh;
848 const unsigned char *ssid;
849 unsigned int ssid_len;
850 int disconnect_reason;
853 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
854 memcpy(name, ssid, ssid_len);
855 name[ssid_len] = '\0';
856 DBG("name %s", name);
858 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
859 DBG("Disconnect Reason %d", disconnect_reason);
861 wifi = g_supplicant_interface_get_data(interface);
862 DBG("wifi %p", wifi);
867 mesh_info = wifi->mesh_info;
871 mesh = connman_get_connected_mesh_from_name(name);
873 DBG("%s is not connected", name);
874 mesh = connman_get_connecting_mesh_from_name(name);
876 DBG("%s is not connecting", name);
881 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
882 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
885 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
887 const char *peer_address;
889 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
894 DBG("Peer %s connected", peer_address);
895 connman_mesh_add_connected_peer(peer_address);
898 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
900 const char *peer_address;
903 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
908 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
910 DBG("Peer %s disconnected with reason %d", peer_address, reason);
911 connman_mesh_remove_connected_peer(peer_address, reason);
915 static struct wifi_data *get_pending_wifi_data(const char *ifname)
919 for (list = pending_wifi_device; list; list = list->next) {
920 struct wifi_data *wifi;
921 const char *dev_name;
924 if (!wifi || !wifi->device)
927 dev_name = connman_device_get_string(wifi->device, "Interface");
928 if (!g_strcmp0(ifname, dev_name)) {
929 pending_wifi_device = g_list_delete_link(
930 pending_wifi_device, list);
938 static void remove_pending_wifi_device(struct wifi_data *wifi)
942 link = g_list_find(pending_wifi_device, wifi);
947 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
950 static void peer_cancel_timeout(struct wifi_data *wifi)
952 if (wifi->p2p_connection_timeout > 0)
953 g_source_remove(wifi->p2p_connection_timeout);
955 wifi->p2p_connection_timeout = 0;
956 wifi->p2p_connecting = false;
958 if (wifi->pending_peer) {
959 connman_peer_unref(wifi->pending_peer);
960 wifi->pending_peer = NULL;
964 static gboolean peer_connect_timeout(gpointer data)
966 struct wifi_data *wifi = data;
970 if (wifi->p2p_connecting) {
971 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
972 GSupplicantPeer *gs_peer =
973 g_supplicant_interface_peer_lookup(wifi->interface,
974 connman_peer_get_identifier(wifi->pending_peer));
976 if (g_supplicant_peer_has_requested_connection(gs_peer))
977 state = CONNMAN_PEER_STATE_IDLE;
979 connman_peer_set_state(wifi->pending_peer, state);
982 peer_cancel_timeout(wifi);
987 static void peer_connect_callback(int result, GSupplicantInterface *interface,
990 struct wifi_data *wifi = user_data;
991 struct connman_peer *peer = wifi->pending_peer;
993 DBG("peer %p - %d", peer, result);
999 peer_connect_timeout(wifi);
1003 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
1005 wifi->p2p_connection_timeout = g_timeout_add_seconds(
1006 P2P_CONNECTION_TIMEOUT,
1007 peer_connect_timeout, wifi);
1010 static int peer_connect(struct connman_peer *peer,
1011 enum connman_peer_wps_method wps_method,
1012 const char *wps_pin)
1014 struct connman_device *device = connman_peer_get_device(peer);
1015 GSupplicantPeerParams *peer_params;
1016 GSupplicantPeer *gs_peer;
1017 struct wifi_data *wifi;
1021 DBG("peer %p", peer);
1026 wifi = connman_device_get_data(device);
1027 if (!wifi || !wifi->interface)
1030 if (wifi->p2p_connecting)
1033 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1034 connman_peer_get_identifier(peer));
1038 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
1039 pin = g_supplicant_peer_is_wps_pin(gs_peer);
1041 switch (wps_method) {
1042 case CONNMAN_PEER_WPS_UNKNOWN:
1043 if ((pbc && pin) || pin)
1046 case CONNMAN_PEER_WPS_PBC:
1051 case CONNMAN_PEER_WPS_PIN:
1052 if (!pin || !wps_pin)
1057 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1061 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1063 peer_params->wps_pin = g_strdup(wps_pin);
1065 peer_params->master = connman_peer_service_is_master();
1067 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1068 peer_connect_callback, wifi);
1069 if (ret == -EINPROGRESS) {
1070 wifi->pending_peer = connman_peer_ref(peer);
1071 wifi->p2p_connecting = true;
1072 } else if (ret < 0) {
1073 g_free(peer_params->path);
1074 g_free(peer_params->wps_pin);
1075 g_free(peer_params);
1081 static int peer_disconnect(struct connman_peer *peer)
1083 struct connman_device *device = connman_peer_get_device(peer);
1084 GSupplicantPeerParams peer_params = {};
1085 GSupplicantPeer *gs_peer;
1086 struct wifi_data *wifi;
1089 DBG("peer %p", peer);
1094 wifi = connman_device_get_data(device);
1098 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1099 connman_peer_get_identifier(peer));
1103 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1105 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1107 g_free(peer_params.path);
1109 if (ret == -EINPROGRESS) {
1110 peer_cancel_timeout(wifi);
1111 wifi->p2p_device = false;
1117 struct peer_service_registration {
1118 peer_service_registration_cb_t callback;
1122 static bool is_service_wfd(const unsigned char *specs, int length)
1124 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1130 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1132 struct wifi_data *wifi = data;
1134 if (!wifi->interface ||
1135 !g_supplicant_interface_has_p2p(wifi->interface))
1138 if (!wifi->servicing) {
1139 g_supplicant_interface_p2p_listen(wifi->interface,
1140 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1146 static void register_wfd_service_cb(int result,
1147 GSupplicantInterface *iface, void *user_data)
1149 struct peer_service_registration *reg_data = user_data;
1154 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1156 if (reg_data && reg_data->callback) {
1157 reg_data->callback(result, reg_data->user_data);
1162 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1163 const unsigned char *spec,
1164 int spec_length, const unsigned char *query,
1165 int query_length, int version)
1167 GSupplicantP2PServiceParams *params;
1169 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1174 params->version = version;
1175 if (spec_length > 0) {
1176 params->service = g_malloc(spec_length);
1177 memcpy(params->service, spec, spec_length);
1179 } else if (query_length > 0 && spec_length > 0) {
1180 params->query = g_malloc(query_length);
1181 memcpy(params->query, query, query_length);
1182 params->query_length = query_length;
1184 params->response = g_malloc(spec_length);
1185 memcpy(params->response, spec, spec_length);
1186 params->response_length = spec_length;
1188 if (spec_length > 0) {
1189 params->wfd_ies = g_malloc(spec_length);
1190 memcpy(params->wfd_ies, spec, spec_length);
1192 params->wfd_ies_length = spec_length;
1198 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1203 g_free(params->service);
1204 g_free(params->query);
1205 g_free(params->response);
1206 g_free(params->wfd_ies);
1211 static int peer_register_wfd_service(const unsigned char *specification,
1212 int specification_length,
1213 peer_service_registration_cb_t callback,
1216 struct peer_service_registration *reg_data = NULL;
1217 static GSupplicantP2PServiceParams *params;
1222 if (wfd_service_registered)
1225 params = fill_in_peer_service_params(specification,
1226 specification_length, NULL, 0, 0);
1230 reg_data = g_try_malloc0(sizeof(*reg_data));
1236 reg_data->callback = callback;
1237 reg_data->user_data = user_data;
1239 ret = g_supplicant_set_widi_ies(params,
1240 register_wfd_service_cb, reg_data);
1241 if (ret < 0 && ret != -EINPROGRESS)
1244 wfd_service_registered = true;
1248 free_peer_service_params(params);
1254 static void register_peer_service_cb(int result,
1255 GSupplicantInterface *iface, void *user_data)
1257 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1258 struct peer_service_registration *reg_data = user_data;
1260 #if defined TIZEN_EXT
1268 apply_p2p_listen_on_iface(wifi, NULL);
1270 if (reg_data->callback)
1271 reg_data->callback(result, reg_data->user_data);
1276 static int peer_register_service(const unsigned char *specification,
1277 int specification_length,
1278 const unsigned char *query,
1279 int query_length, int version,
1280 peer_service_registration_cb_t callback,
1283 struct peer_service_registration *reg_data;
1284 GSupplicantP2PServiceParams *params;
1291 if (specification && !version && !query &&
1292 is_service_wfd(specification, specification_length)) {
1293 return peer_register_wfd_service(specification,
1294 specification_length, callback, user_data);
1297 reg_data = g_try_malloc0(sizeof(*reg_data));
1301 reg_data->callback = callback;
1302 reg_data->user_data = user_data;
1304 ret_f = -EOPNOTSUPP;
1306 for (list = iface_list; list; list = list->next) {
1307 struct wifi_data *wifi = list->data;
1308 GSupplicantInterface *iface = wifi->interface;
1310 if (!g_supplicant_interface_has_p2p(iface))
1313 params = fill_in_peer_service_params(specification,
1314 specification_length, query,
1315 query_length, version);
1320 ret_f = g_supplicant_interface_p2p_add_service(iface,
1321 register_peer_service_cb, params, reg_data);
1322 if (ret_f == 0 || ret_f == -EINPROGRESS)
1326 ret = g_supplicant_interface_p2p_add_service(iface,
1327 register_peer_service_cb, params, NULL);
1328 if (ret != 0 && ret != -EINPROGRESS)
1329 free_peer_service_params(params);
1332 if (ret_f != 0 && ret_f != -EINPROGRESS)
1338 static int peer_unregister_wfd_service(void)
1340 GSupplicantP2PServiceParams *params;
1343 if (!wfd_service_registered)
1346 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1350 wfd_service_registered = false;
1352 g_supplicant_set_widi_ies(params, NULL, NULL);
1354 for (list = iface_list; list; list = list->next) {
1355 struct wifi_data *wifi = list->data;
1357 if (!g_supplicant_interface_has_p2p(wifi->interface))
1361 if (!wifi->servicing || wifi->servicing < 0) {
1362 g_supplicant_interface_p2p_listen(wifi->interface,
1364 wifi->servicing = 0;
1371 static int peer_unregister_service(const unsigned char *specification,
1372 int specification_length,
1373 const unsigned char *query,
1374 int query_length, int version)
1376 GSupplicantP2PServiceParams *params;
1381 if (specification && !version && !query &&
1382 is_service_wfd(specification, specification_length)) {
1383 ret = peer_unregister_wfd_service();
1384 if (ret != 0 && ret != -EINPROGRESS)
1389 for (list = iface_list; list; list = list->next) {
1390 struct wifi_data *wifi = list->data;
1391 GSupplicantInterface *iface = wifi->interface;
1394 goto stop_listening;
1396 if (!g_supplicant_interface_has_p2p(iface))
1399 params = fill_in_peer_service_params(specification,
1400 specification_length, query,
1401 query_length, version);
1405 ret = g_supplicant_interface_p2p_del_service(iface, params);
1406 if (ret != 0 && ret != -EINPROGRESS)
1407 free_peer_service_params(params);
1410 if (!wifi->servicing || wifi->servicing < 0) {
1411 g_supplicant_interface_p2p_listen(iface, 0, 0);
1412 wifi->servicing = 0;
1419 static struct connman_peer_driver peer_driver = {
1420 .connect = peer_connect,
1421 .disconnect = peer_disconnect,
1422 .register_service = peer_register_service,
1423 .unregister_service = peer_unregister_service,
1426 static void handle_tethering(struct wifi_data *wifi)
1428 if (!wifi->tethering)
1437 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1439 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1442 wifi->bridged = true;
1445 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1447 struct connman_device *device = user_data;
1448 struct wifi_data *wifi = connman_device_get_data(device);
1453 DBG("index %d flags %d change %d", wifi->index, flags, change);
1455 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1457 DBG("interface up");
1459 DBG("interface down");
1462 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1463 if (flags & IFF_LOWER_UP)
1469 if (flags & IFF_LOWER_UP)
1470 handle_tethering(wifi);
1472 wifi->flags = flags;
1475 static int wifi_probe(struct connman_device *device)
1477 struct wifi_data *wifi;
1479 DBG("device %p", device);
1481 wifi = g_try_new0(struct wifi_data, 1);
1485 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1486 wifi->ap_supported = WIFI_AP_UNKNOWN;
1487 wifi->tethering_param = NULL;
1489 connman_device_set_data(device, wifi);
1490 wifi->device = connman_device_ref(device);
1492 wifi->index = connman_device_get_index(device);
1495 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1496 wifi_newlink, device);
1497 if (is_p2p_connecting())
1498 add_pending_wifi_device(wifi);
1500 iface_list = g_list_append(iface_list, wifi);
1505 static void remove_networks(struct connman_device *device,
1506 struct wifi_data *wifi)
1510 for (list = wifi->networks; list; list = list->next) {
1511 struct connman_network *network = list->data;
1513 connman_device_remove_network(device, network);
1514 connman_network_unref(network);
1517 g_slist_free(wifi->networks);
1518 wifi->networks = NULL;
1521 static void remove_peers(struct wifi_data *wifi)
1525 for (list = wifi->peers; list; list = list->next) {
1526 struct connman_peer *peer = list->data;
1528 connman_peer_unregister(peer);
1529 connman_peer_unref(peer);
1532 g_slist_free(wifi->peers);
1536 static void reset_autoscan(struct connman_device *device)
1538 struct wifi_data *wifi = connman_device_get_data(device);
1539 struct autoscan_params *autoscan;
1543 if (!wifi || !wifi->autoscan)
1546 autoscan = wifi->autoscan;
1548 autoscan->interval = 0;
1550 if (autoscan->timeout == 0)
1553 g_source_remove(autoscan->timeout);
1554 autoscan->timeout = 0;
1556 connman_device_unref(device);
1559 static void stop_autoscan(struct connman_device *device)
1561 const struct wifi_data *wifi = connman_device_get_data(device);
1563 if (!wifi || !wifi->autoscan)
1566 reset_autoscan(device);
1568 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1571 static void check_p2p_technology(void)
1573 bool p2p_exists = false;
1576 for (list = iface_list; list; list = list->next) {
1577 struct wifi_data *w = list->data;
1580 g_supplicant_interface_has_p2p(w->interface))
1585 connman_technology_driver_unregister(&p2p_tech_driver);
1586 connman_peer_driver_unregister(&peer_driver);
1590 struct last_connected {
1596 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1598 GTimeVal *aval = (GTimeVal *)a;
1599 GTimeVal *bval = (GTimeVal *)b;
1601 /* Note that the sort order is descending */
1602 if (aval->tv_sec < bval->tv_sec)
1605 if (aval->tv_sec > bval->tv_sec)
1611 static void free_entry(gpointer data)
1613 struct last_connected *entry = data;
1615 g_free(entry->ssid);
1619 static void wifi_remove(struct connman_device *device)
1621 struct wifi_data *wifi = connman_device_get_data(device);
1623 DBG("device %p wifi %p", device, wifi);
1628 stop_autoscan(device);
1630 if (wifi->p2p_device)
1631 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1633 iface_list = g_list_remove(iface_list, wifi);
1635 check_p2p_technology();
1636 #if defined TIZEN_EXT_WIFI_MESH
1637 check_mesh_technology();
1640 remove_pending_wifi_device(wifi);
1642 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
1643 g_source_remove(wifi->p2p_find_timeout);
1644 connman_device_unref(wifi->device);
1647 if (wifi->p2p_connection_timeout)
1648 g_source_remove(wifi->p2p_connection_timeout);
1650 #if defined TIZEN_EXT
1651 if (wifi->automaxspeed_timeout != 0) {
1652 g_source_remove(wifi->automaxspeed_timeout);
1653 wifi->automaxspeed_timeout = 0;
1657 remove_networks(device, wifi);
1660 connman_device_set_powered(device, false);
1661 connman_device_set_data(device, NULL);
1662 connman_device_unref(wifi->device);
1663 connman_rtnl_remove_watch(wifi->watch);
1665 g_supplicant_interface_set_data(wifi->interface, NULL);
1667 g_supplicant_interface_cancel(wifi->interface);
1669 if (wifi->scan_params)
1670 g_supplicant_free_scan_params(wifi->scan_params);
1671 #if defined TIZEN_EXT
1672 if (wifi->hidden_scan_params) {
1673 while (wifi->hidden_scan_params->ssids) {
1674 struct scan_ssid *ssid;
1675 ssid = wifi->hidden_scan_params->ssids->data;
1676 wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
1678 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1682 g_free(wifi->autoscan);
1683 g_free(wifi->identifier);
1687 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1691 for (iter = list; iter; iter = g_slist_next(iter)) {
1692 struct scan_ssid *scan_ssid = iter->data;
1694 if (ssid_len == scan_ssid->ssid_len &&
1695 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1702 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1703 int freq, GSupplicantScanParams *scan_data,
1704 int driver_max_scan_ssids, char *ssid_name)
1707 struct scan_ssid *scan_ssid;
1709 if ((driver_max_scan_ssids == 0 ||
1710 driver_max_scan_ssids > scan_data->num_ssids) &&
1711 (hex_ssid || raw_ssid)) {
1713 unsigned int j = 0, hex;
1716 size_t hex_ssid_len = strlen(hex_ssid);
1718 ssid = g_try_malloc0(hex_ssid_len / 2);
1722 for (i = 0; i < hex_ssid_len; i += 2) {
1723 sscanf(hex_ssid + i, "%02x", &hex);
1732 * If we have already added hidden AP to the list,
1733 * then do not do it again. This might happen if you have
1734 * used or are using multiple wifi cards, so in that case
1735 * you might have multiple service files for same AP.
1737 if (is_duplicate(scan_data->ssids, ssid, j)) {
1743 scan_ssid = g_try_new(struct scan_ssid, 1);
1750 memcpy(scan_ssid->ssid, ssid, j);
1751 scan_ssid->ssid_len = j;
1752 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1755 scan_data->num_ssids++;
1757 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1758 scan_data->num_ssids);
1765 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1767 if (!scan_data->freqs) {
1768 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1769 if (!scan_data->freqs) {
1770 g_slist_free_full(scan_data->ssids, g_free);
1774 scan_data->num_freqs = 1;
1775 scan_data->freqs[0] = freq;
1777 bool duplicate = false;
1779 /* Don't add duplicate entries */
1780 for (i = 0; i < scan_data->num_freqs; i++) {
1781 if (scan_data->freqs[i] == freq) {
1788 scan_data->num_freqs++;
1789 scan_data->freqs = g_try_realloc(scan_data->freqs,
1790 sizeof(uint16_t) * scan_data->num_freqs);
1791 if (!scan_data->freqs) {
1792 g_slist_free_full(scan_data->ssids, g_free);
1795 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1802 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1804 struct connman_config_entry **entries;
1806 #if defined TIZEN_EXT
1807 gchar **services = NULL;
1810 #endif /* defined TIZEN_EXT */
1814 int num_ssids = 0, add_param_failed = 0;
1815 #if defined TIZEN_EXT
1816 GSequenceIter *iter;
1817 GSequence *latest_list;
1818 struct last_connected *entry;
1821 latest_list = g_sequence_new(free_entry);
1825 services = connman_storage_get_services();
1826 for (i = 0; services && services[i]; i++) {
1827 if (strncmp(services[i], "wifi_", 5) != 0)
1830 keyfile = connman_storage_load_service(services[i]);
1834 value = g_key_file_get_boolean(keyfile,
1835 services[i], "Hidden", NULL);
1837 g_key_file_free(keyfile);
1841 value = g_key_file_get_boolean(keyfile,
1842 services[i], "Favorite", NULL);
1844 g_key_file_free(keyfile);
1848 #if defined TIZEN_EXT
1849 value = g_key_file_get_boolean(keyfile,
1850 services[i], "AutoConnect", NULL);
1852 g_key_file_free(keyfile);
1856 gchar *str = g_key_file_get_string(keyfile,
1857 services[i], "Modified", NULL);
1859 g_key_file_free(keyfile);
1862 g_time_val_from_iso8601(str, &modified);
1866 ssid = g_key_file_get_string(keyfile,
1867 services[i], "SSID", NULL);
1869 name = g_key_file_get_string(keyfile, services[i], "Name",
1872 #if defined TIZEN_EXT
1873 entry = g_try_new(struct last_connected, 1);
1875 g_sequence_free(latest_list);
1878 g_key_file_free(keyfile);
1882 entry->modified = modified;
1885 g_sequence_insert_sorted(latest_list, entry,
1888 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1897 g_key_file_free(keyfile);
1900 #if defined TIZEN_EXT
1901 gint length = g_sequence_get_length(latest_list);
1902 iter = g_sequence_get_begin_iter(latest_list);
1904 for (i = 0; i < length; i++) {
1905 entry = g_sequence_get(iter);
1907 ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid);
1913 iter = g_sequence_iter_next(iter);
1916 g_sequence_free(latest_list);
1920 * Check if there are any hidden AP that needs to be provisioned.
1922 entries = connman_config_get_entries("wifi");
1923 for (i = 0; entries && entries[i]; i++) {
1926 if (!entries[i]->hidden)
1929 if (!entries[i]->ssid) {
1930 ssid = entries[i]->name;
1933 ssid = entries[i]->ssid;
1934 len = entries[i]->ssid_len;
1940 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1947 connman_config_free_entries(entries);
1949 if (add_param_failed > 0)
1950 DBG("Unable to scan %d out of %d SSIDs",
1951 add_param_failed, num_ssids);
1953 g_strfreev(services);
1958 static int get_hidden_connections_params(struct wifi_data *wifi,
1959 GSupplicantScanParams *scan_params)
1961 int driver_max_ssids, i;
1962 GSupplicantScanParams *orig_params;
1965 * Scan hidden networks so that we can autoconnect to them.
1966 * We will assume 1 as a default number of ssid to scan.
1968 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1970 if (driver_max_ssids == 0)
1971 driver_max_ssids = 1;
1973 DBG("max ssids %d", driver_max_ssids);
1975 #if defined TIZEN_EXT
1976 if (!wifi->hidden_scan_params) {
1977 wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1978 if (!wifi->hidden_scan_params)
1981 if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
1982 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1983 wifi->hidden_scan_params = NULL;
1989 orig_params = wifi->hidden_scan_params;
1991 if (!wifi->scan_params) {
1992 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1993 if (!wifi->scan_params)
1996 if (get_hidden_connections(wifi->scan_params) == 0) {
1997 g_supplicant_free_scan_params(wifi->scan_params);
1998 wifi->scan_params = NULL;
2004 orig_params = wifi->scan_params;
2007 /* Let's transfer driver_max_ssids params */
2008 for (i = 0; i < driver_max_ssids; i++) {
2009 struct scan_ssid *ssid;
2011 #if defined TIZEN_EXT
2012 if (!wifi->hidden_scan_params->ssids)
2014 if (!wifi->scan_params->ssids)
2018 ssid = orig_params->ssids->data;
2019 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
2020 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
2024 scan_params->num_ssids = i;
2025 scan_params->ssids = g_slist_reverse(scan_params->ssids);
2027 if (orig_params->num_freqs <= 0)
2030 scan_params->freqs =
2031 g_malloc(sizeof(uint16_t) * orig_params->num_freqs);
2032 memcpy(scan_params->freqs, orig_params->freqs,
2033 sizeof(uint16_t) *orig_params->num_freqs);
2035 scan_params->num_freqs = orig_params->num_freqs;
2040 orig_params->num_ssids -= scan_params->num_ssids;
2042 return scan_params->num_ssids;
2045 g_slist_free_full(scan_params->ssids, g_free);
2046 #if defined TIZEN_EXT
2047 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2048 wifi->hidden_scan_params = NULL;
2050 g_supplicant_free_scan_params(wifi->scan_params);
2051 wifi->scan_params = NULL;
2057 static int throw_wifi_scan(struct connman_device *device,
2058 GSupplicantInterfaceCallback callback)
2060 struct wifi_data *wifi = connman_device_get_data(device);
2066 DBG("device %p %p", device, wifi->interface);
2068 if (wifi->tethering)
2071 #if defined TIZEN_EXT
2072 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)
2073 && !wifi->allow_full_scan)
2075 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
2079 connman_device_ref(device);
2081 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2084 connman_device_set_scanning(device,
2085 CONNMAN_SERVICE_TYPE_WIFI, true);
2087 connman_device_unref(device);
2092 static void hidden_free(struct hidden_params *hidden)
2097 if (hidden->scan_params)
2098 g_supplicant_free_scan_params(hidden->scan_params);
2099 g_free(hidden->identity);
2100 g_free(hidden->passphrase);
2101 g_free(hidden->security);
2105 #if defined TIZEN_EXT
2106 static void service_state_changed(struct connman_service *service,
2107 enum connman_service_state state);
2109 static int network_connect(struct connman_network *network);
2111 static struct connman_notifier notifier = {
2113 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
2114 .service_state_changed = service_state_changed,
2117 static void service_state_changed(struct connman_service *service,
2118 enum connman_service_state state)
2120 enum connman_service_type type;
2122 type = connman_service_get_type(service);
2123 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2126 DBG("service %p state %d", service, state);
2129 case CONNMAN_SERVICE_STATE_READY:
2130 case CONNMAN_SERVICE_STATE_ONLINE:
2131 case CONNMAN_SERVICE_STATE_FAILURE:
2132 connman_notifier_unregister(¬ifier);
2133 is_wifi_notifier_registered = FALSE;
2135 __connman_device_request_scan(type);
2143 static gboolean need_bss_transition(uint16_t freq, int snr, int strength)
2146 * Since bssid->strength is a positive value,
2147 * it need to be changed to its original value.
2149 int signal = strength - 120;
2152 * If the currently connected AP matches the following conditions,
2153 * scan for BSS transition is started.
2154 * - SNR is less than min_snr or RSSI is less than
2155 * min_rssi_2_4GHz or min_rssi_5GHz.
2157 if (min_snr != 0 && snr != 0 && snr < min_snr)
2159 else if (freq > 4000 && signal <= min_rssi_5GHz)
2161 else if (freq < 4000 && signal <= min_rssi_2_4GHz)
2167 static gboolean check_bss_diff(int cur_level, int sel_level, int to_5ghz,
2168 unsigned int cur_est, unsigned int sel_est)
2173 /* This code is from wpa_supplicant. */
2174 if (cur_level < -85) /* ..-86 dBm */
2176 else if (cur_level < -80) /* -85..-81 dBm */
2178 else if (cur_level < -75) /* -80..-76 dBm */
2180 else if (cur_level < -70) /* -75..-71 dBm */
2182 else if (cur_level < 0) /* -70..-1 dBm */
2184 else /* unspecified units (not in dBm) */
2187 if (cur_est > sel_est * 1.5)
2189 else if (cur_est > sel_est * 1.2)
2191 else if (cur_est > sel_est * 1.1)
2193 else if (cur_est > sel_est)
2195 else if (sel_est > cur_est * 1.5)
2197 else if (sel_est > cur_est * 1.2)
2199 else if (sel_est > cur_est * 1.1)
2201 else if (sel_est > cur_est)
2207 diff = sel_level - cur_level;
2209 if (diff < min_diff)
2215 static gboolean check_bss_condition(uint16_t freq, uint16_t strength,
2216 unsigned int est_throughput, uint16_t cur_freq, uint16_t cur_strength,
2217 unsigned int cur_est_throughput)
2220 * Since bssid->strength is a positive value,
2221 * it need to be changed to its original value.
2223 int signal = strength - 120;
2224 int cur_signal = cur_strength - 120;
2225 int to_5ghz = freq > 4000 && cur_freq < 4000;
2227 DBG("cur_freq=%d cur_level=%d cur_est=%d sel_freq=%d sel_level=%d sel_est=%d",
2228 cur_freq, cur_strength, cur_est_throughput,
2229 freq, strength, est_throughput);
2232 * If the AP that matches the following conditions exists in the SCAN result,
2233 * BSS transition is started.
2236 if (est_throughput > cur_est_throughput + 5000)
2239 if (cur_signal > signal + to_5ghz * 2 &&
2240 est_throughput < cur_est_throughput * 1.2)
2243 if (cur_est_throughput > est_throughput + 5000)
2246 return check_bss_diff(cur_signal, signal,
2247 to_5ghz, cur_est_throughput, est_throughput);
2250 static void scan_callback_hidden(int result,
2251 GSupplicantInterface *interface, void *user_data);
2253 static int network_disconnect(struct connman_network *network);
2255 static void start_roaming(struct wifi_data *wifi)
2257 bool roaming_ap_found = false;
2258 GSList *bssid_list = NULL;
2260 if (!wifi || !wifi->network)
2263 if (!connman_setting_get_bool("WifiRoaming"))
2266 struct connman_network *network = wifi->network;
2267 bssid_list = connman_network_get_bssid_list(network);
2269 if (g_slist_length(bssid_list) <= 1)
2272 if (!connman_network_get_connected(network))
2275 if (connman_network_get_bool(network, "WiFi.Roaming"))
2278 uint16_t cur_freq = connman_network_get_frequency(network);
2279 uint8_t cur_strength = connman_network_get_strength(network);
2280 unsigned int cur_est_throughput = connman_network_get_est_throughput(network);
2282 if (!need_bss_transition(
2284 connman_network_get_snr(network),
2288 unsigned char *cur_bssid = connman_network_get_bssid(network);
2290 for (; bssid_list; bssid_list = bssid_list->next) {
2291 struct g_connman_bssids *bssid = bssid_list->data;
2293 if (memcmp(cur_bssid, bssid->bssid, WIFI_BSSID_LEN_MAX) == 0)
2296 if (check_bss_condition(
2297 bssid->frequency, bssid->strength, bssid->est_throughput,
2298 cur_freq, cur_strength, cur_est_throughput)) {
2299 roaming_ap_found = true;
2301 char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
2302 char *bssid_str = bssid_buff;
2304 snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid->bssid));
2305 connman_network_set_string(network,
2306 "WiFi.RoamingDstBSSID", bssid_str);
2311 if (roaming_ap_found) {
2312 char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
2313 char *bssid_str = bssid_buff;
2314 unsigned char *bssid;
2316 bssid = connman_network_get_bssid(network);
2317 snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
2318 connman_network_set_string(network,
2319 "WiFi.RoamingCurBSSID", bssid_str);
2321 network_disconnect(network);
2322 wifi->pending_network = network;
2323 connman_network_set_bool(network, "WiFi.Roaming", true);
2328 static void scan_callback(int result, GSupplicantInterface *interface,
2331 struct connman_device *device = user_data;
2332 struct wifi_data *wifi = connman_device_get_data(device);
2334 #if defined TIZEN_EXT
2335 GSList *list = NULL;
2336 bool favorite_exists = false;
2337 struct connman_network *network = NULL;
2338 struct connman_service *service = NULL;
2341 DBG("result %d wifi %p", result, wifi);
2344 if (wifi->hidden && !wifi->postpone_hidden) {
2345 connman_network_clear_hidden(wifi->hidden->user_data);
2346 hidden_free(wifi->hidden);
2347 wifi->hidden = NULL;
2350 if (wifi->scan_params) {
2351 g_supplicant_free_scan_params(wifi->scan_params);
2352 wifi->scan_params = NULL;
2355 #if defined TIZEN_EXT
2356 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2357 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2358 wifi->hidden_scan_params = NULL;
2364 connman_device_reset_scanning(device);
2366 /* User is connecting to a hidden AP, let's wait for finished event */
2367 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2368 GSupplicantScanParams *scan_params;
2371 wifi->postpone_hidden = false;
2372 scan_params = wifi->hidden->scan_params;
2373 wifi->hidden->scan_params = NULL;
2375 reset_autoscan(device);
2377 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2378 scan_callback, device);
2382 /* On error, let's recall scan_callback, which will cleanup */
2383 return scan_callback(ret, interface, user_data);
2386 #if defined TIZEN_EXT
2388 for (list = wifi->networks; list; list = list->next) {
2389 network = list->data;
2390 service = connman_service_lookup_from_network(network);
2392 if (service != NULL &&
2393 (connman_service_get_favorite(service) == true) &&
2394 (connman_service_get_autoconnect(service) == true)) {
2395 DBG("Favorite service exists [%s]",
2396 connman_network_get_string(network, "Name"));
2397 favorite_exists = true;
2403 if (favorite_exists == false) {
2404 if (wifi && wifi->allow_full_scan) {
2406 DBG("Trigger full channel scan");
2407 wifi->allow_full_scan = false;
2409 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2410 scan_callback_hidden, device);
2414 /* On error, let's recall scan_callback, which will cleanup */
2415 return scan_callback(ret, interface, user_data);
2418 wifi->allow_full_scan = false;
2421 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
2424 connman_device_set_scanning(device,
2425 CONNMAN_SERVICE_TYPE_WIFI, false);
2428 if (result != -ENOLINK)
2429 #if defined TIZEN_EXT
2432 start_autoscan(device);
2435 * If we are here then we were scanning; however, if we are
2436 * also mid-flight disabling the interface, then wifi_disable
2437 * has already cleared the device scanning state and
2438 * unreferenced the device, obviating the need to do it here.
2442 connman_device_unref(device);
2444 #if defined TIZEN_EXT
2448 if (wifi->scan_pending_network && result != -EIO) {
2449 network_connect(wifi->scan_pending_network);
2450 wifi->scan_pending_network = NULL;
2451 connman_network_set_connecting(wifi->network);
2453 start_roaming(wifi);
2457 if (is_wifi_notifier_registered != true &&
2458 wifi_first_scan == true && found_with_first_scan == true) {
2459 wifi_first_scan = false;
2460 found_with_first_scan = false;
2462 connman_notifier_register(¬ifier);
2463 is_wifi_notifier_registered = true;
2468 static void scan_callback_hidden(int result,
2469 GSupplicantInterface *interface, void *user_data)
2471 struct connman_device *device = user_data;
2472 struct wifi_data *wifi = connman_device_get_data(device);
2473 GSupplicantScanParams *scan_params;
2476 DBG("result %d wifi %p", result, wifi);
2481 /* User is trying to connect to a hidden AP */
2482 if (wifi->hidden && wifi->postpone_hidden)
2485 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2489 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2490 ret = g_supplicant_interface_scan(wifi->interface,
2492 #if defined TIZEN_EXT
2495 scan_callback_hidden,
2502 g_supplicant_free_scan_params(scan_params);
2505 scan_callback(result, interface, user_data);
2508 static gboolean autoscan_timeout(gpointer data)
2510 struct connman_device *device = data;
2511 struct wifi_data *wifi = connman_device_get_data(device);
2512 struct autoscan_params *autoscan;
2518 autoscan = wifi->autoscan;
2520 #if defined TIZEN_EXT
2525 if (autoscan->interval <= 0) {
2526 interval = autoscan->base;
2529 interval = autoscan->interval * autoscan->base;
2531 #if defined TIZEN_EXT
2532 if (autoscan->interval >= autoscan->limit)
2534 if (interval > autoscan->limit)
2536 interval = autoscan->limit;
2538 throw_wifi_scan(wifi->device, scan_callback_hidden);
2541 * In case BackgroundScanning is disabled, interval will reach the
2542 * limit exactly after the very first passive scanning. It allows
2543 * to ensure at most one passive scan is performed in such cases.
2545 if (!connman_setting_get_bool("BackgroundScanning") &&
2546 interval == autoscan->limit) {
2547 g_source_remove(autoscan->timeout);
2548 autoscan->timeout = 0;
2550 connman_device_unref(device);
2556 DBG("interval %d", interval);
2558 autoscan->interval = interval;
2560 autoscan->timeout = g_timeout_add_seconds(interval,
2561 autoscan_timeout, device);
2566 static void start_autoscan(struct connman_device *device)
2568 struct wifi_data *wifi = connman_device_get_data(device);
2569 struct autoscan_params *autoscan;
2576 if (wifi->p2p_device)
2579 if (wifi->connected)
2582 autoscan = wifi->autoscan;
2586 if (autoscan->timeout > 0 || autoscan->interval > 0)
2589 connman_device_ref(device);
2591 autoscan_timeout(device);
2594 static struct autoscan_params *parse_autoscan_params(const char *params)
2596 struct autoscan_params *autoscan;
2603 list_params = g_strsplit(params, ":", 0);
2604 if (list_params == 0)
2607 if (!g_strcmp0(list_params[0], "exponential") &&
2608 g_strv_length(list_params) == 3) {
2609 base = atoi(list_params[1]);
2610 limit = atoi(list_params[2]);
2611 } else if (!g_strcmp0(list_params[0], "single") &&
2612 g_strv_length(list_params) == 2)
2613 base = limit = atoi(list_params[1]);
2615 g_strfreev(list_params);
2619 DBG("Setup %s autoscanning", list_params[0]);
2621 g_strfreev(list_params);
2623 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2625 DBG("Could not allocate memory for autoscan");
2629 DBG("base %d - limit %d", base, limit);
2630 autoscan->base = base;
2631 autoscan->limit = limit;
2636 static void setup_autoscan(struct wifi_data *wifi)
2639 * If BackgroundScanning is enabled, setup exponential
2640 * autoscanning if it has not been previously done.
2642 if (connman_setting_get_bool("BackgroundScanning")) {
2643 wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
2646 #if defined TIZEN_EXT
2648 if (wifi->autoscan) {
2649 g_free(wifi->autoscan);
2650 wifi->autoscan = NULL;
2653 DBG("BackgroundScanning is disabled");
2660 * On the contrary, if BackgroundScanning is disabled, update autoscan
2661 * parameters based on the type of scanning that is being performed.
2663 if (wifi->autoscan) {
2664 g_free(wifi->autoscan);
2665 wifi->autoscan = NULL;
2668 switch (wifi->scanning_type) {
2669 case WIFI_SCANNING_PASSIVE:
2670 /* Do not setup autoscan. */
2672 case WIFI_SCANNING_ACTIVE:
2673 /* Setup one single passive scan after active. */
2674 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2676 case WIFI_SCANNING_UNKNOWN:
2677 /* Setup autoscan in this case but we should never fall here. */
2678 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2684 static void finalize_interface_creation(struct wifi_data *wifi)
2686 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2688 if (!wifi->device) {
2689 connman_error("WiFi device not set");
2693 connman_device_set_powered(wifi->device, true);
2695 if (wifi->p2p_device)
2698 if (!wifi->autoscan)
2699 setup_autoscan(wifi);
2701 start_autoscan(wifi->device);
2704 static void interface_create_callback(int result,
2705 GSupplicantInterface *interface,
2708 struct wifi_data *wifi = user_data;
2709 char *bgscan_range_max;
2712 DBG("result %d ifname %s, wifi %p", result,
2713 g_supplicant_interface_get_ifname(interface),
2716 if (result < 0 || !wifi)
2719 wifi->interface = interface;
2720 g_supplicant_interface_set_data(interface, wifi);
2722 if (g_supplicant_interface_get_ready(interface)) {
2723 wifi->interface_ready = true;
2724 finalize_interface_creation(wifi);
2728 * Set the BSS expiration age to match the long scanning
2729 * interval to avoid the loss of unconnected networks between
2732 bgscan_range_max = strrchr(BGSCAN_DEFAULT, ':');
2733 if (!bgscan_range_max || strlen(bgscan_range_max) < 1)
2736 value = strtol(bgscan_range_max + 1, NULL, 10);
2737 if (value <= 0 || errno == ERANGE)
2740 if (g_supplicant_interface_set_bss_expiration_age(interface,
2741 value + SCAN_MAX_DURATION) < 0) {
2742 connman_warn("Failed to set bss expiration age");
2746 static int wifi_enable(struct connman_device *device)
2748 struct wifi_data *wifi = connman_device_get_data(device);
2751 const char *driver = connman_setting_get_string("wifi");
2754 DBG("device %p %p", device, wifi);
2756 index = connman_device_get_index(device);
2757 if (!wifi || index < 0)
2760 if (is_p2p_connecting())
2761 return -EINPROGRESS;
2763 interface = connman_inet_ifname(index);
2764 ret = g_supplicant_interface_create(interface, driver, NULL,
2766 connman_device_get_mac_policy(device),
2767 connman_device_get_preassoc_mac_policy(device),
2768 connman_device_get_random_mac_lifetime(device),
2769 #endif /* TIZEN_EXT */
2770 interface_create_callback,
2777 return -EINPROGRESS;
2780 static int wifi_disable(struct connman_device *device)
2782 struct wifi_data *wifi = connman_device_get_data(device);
2785 DBG("device %p wifi %p", device, wifi);
2790 wifi->connected = false;
2791 wifi->disconnecting = false;
2793 if (wifi->pending_network)
2794 wifi->pending_network = NULL;
2796 #if !defined TIZEN_EXT
2797 stop_autoscan(device);
2800 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
2801 g_source_remove(wifi->p2p_find_timeout);
2802 wifi->p2p_find_timeout = 0;
2803 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2804 connman_device_unref(wifi->device);
2807 #if defined TIZEN_EXT
2808 if (wifi->automaxspeed_timeout != 0) {
2809 g_source_remove(wifi->automaxspeed_timeout);
2810 wifi->automaxspeed_timeout = 0;
2814 /* In case of a user scan, device is still referenced */
2815 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) {
2816 connman_device_set_scanning(device,
2817 CONNMAN_SERVICE_TYPE_WIFI, false);
2818 connman_device_unref(wifi->device);
2821 #if defined TIZEN_EXT
2822 stop_autoscan(device);
2825 remove_networks(device, wifi);
2828 #if defined TIZEN_EXT
2829 wifi->scan_pending_network = NULL;
2831 if (is_wifi_notifier_registered == true) {
2832 connman_notifier_unregister(¬ifier);
2833 is_wifi_notifier_registered = false;
2837 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2841 return -EINPROGRESS;
2844 static int get_latest_connections(int max_ssids,
2845 GSupplicantScanParams *scan_data)
2847 GSequenceIter *iter;
2848 GSequence *latest_list;
2849 struct last_connected *entry;
2858 latest_list = g_sequence_new(free_entry);
2862 services = connman_storage_get_services();
2863 for (i = 0; services && services[i]; i++) {
2864 if (strncmp(services[i], "wifi_", 5) != 0)
2867 keyfile = connman_storage_load_service(services[i]);
2871 str = g_key_file_get_string(keyfile,
2872 services[i], "Favorite", NULL);
2873 if (!str || g_strcmp0(str, "true")) {
2875 g_key_file_free(keyfile);
2880 str = g_key_file_get_string(keyfile,
2881 services[i], "AutoConnect", NULL);
2882 if (!str || g_strcmp0(str, "true")) {
2884 g_key_file_free(keyfile);
2889 str = g_key_file_get_string(keyfile,
2890 services[i], "Modified", NULL);
2892 g_key_file_free(keyfile);
2895 #if defined TIZEN_EXT
2897 util_iso8601_to_timeval(str, (struct timeval *)&modified);
2899 util_iso8601_to_timeval(str, &modified);
2903 ssid = g_key_file_get_string(keyfile,
2904 services[i], "SSID", NULL);
2906 freq = g_key_file_get_integer(keyfile, services[i],
2909 entry = g_try_new(struct last_connected, 1);
2911 g_sequence_free(latest_list);
2912 g_key_file_free(keyfile);
2914 #if defined TIZEN_EXT
2915 g_strfreev(services);
2921 entry->modified = modified;
2924 g_sequence_insert_sorted(latest_list, entry,
2930 g_key_file_free(keyfile);
2933 g_strfreev(services);
2935 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2937 iter = g_sequence_get_begin_iter(latest_list);
2939 for (i = 0; i < num_ssids; i++) {
2940 entry = g_sequence_get(iter);
2942 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2943 entry->modified.tv_sec);
2945 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2946 max_ssids, entry->ssid);
2948 iter = g_sequence_iter_next(iter);
2951 g_sequence_free(latest_list);
2955 static void wifi_update_scanner_type(struct wifi_data *wifi,
2956 enum wifi_scanning_type new_type)
2960 if (!wifi || wifi->scanning_type == new_type)
2963 wifi->scanning_type = new_type;
2965 setup_autoscan(wifi);
2968 static int wifi_scan_simple(struct connman_device *device)
2970 struct wifi_data *wifi = connman_device_get_data(device);
2972 reset_autoscan(device);
2974 /* Distinguish between devices performing passive and active scanning */
2976 wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE);
2978 return throw_wifi_scan(device, scan_callback_hidden);
2981 static gboolean p2p_find_stop(gpointer data)
2983 struct connman_device *device = data;
2984 struct wifi_data *wifi = connman_device_get_data(device);
2989 wifi->p2p_find_timeout = 0;
2991 g_supplicant_interface_p2p_stop_find(wifi->interface);
2994 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2996 connman_device_unref(device);
2997 start_autoscan(device);
3002 static void p2p_find_callback(int result, GSupplicantInterface *interface,
3005 struct connman_device *device = user_data;
3006 struct wifi_data *wifi = connman_device_get_data(device);
3008 DBG("result %d wifi %p", result, wifi);
3013 if (wifi->p2p_find_timeout) {
3014 g_source_remove(wifi->p2p_find_timeout);
3015 wifi->p2p_find_timeout = 0;
3021 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
3022 p2p_find_stop, device);
3023 if (!wifi->p2p_find_timeout)
3028 p2p_find_stop(device);
3031 static int p2p_find(struct connman_device *device)
3033 struct wifi_data *wifi;
3038 if (!p2p_technology)
3041 wifi = connman_device_get_data(device);
3043 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
3046 reset_autoscan(device);
3047 connman_device_ref(device);
3049 ret = g_supplicant_interface_p2p_find(wifi->interface,
3050 p2p_find_callback, device);
3052 connman_device_unref(device);
3053 start_autoscan(device);
3055 connman_device_set_scanning(device,
3056 CONNMAN_SERVICE_TYPE_P2P, true);
3062 #if defined TIZEN_EXT
3063 static void specific_scan_callback(int result, GSupplicantInterface *interface,
3066 struct connman_device *device = user_data;
3067 struct wifi_data *wifi = connman_device_get_data(device);
3070 DBG("result %d device %p wifi %p", result, device, wifi);
3072 if (wifi && wifi->scan_params) {
3073 g_supplicant_free_scan_params(wifi->scan_params);
3074 wifi->scan_params = NULL;
3077 scanning = connman_device_get_scanning(device,
3078 CONNMAN_SERVICE_TYPE_WIFI);
3080 connman_device_set_scanning(device,
3081 CONNMAN_SERVICE_TYPE_WIFI, false);
3082 connman_device_unref(device);
3085 start_roaming(wifi);
3088 static int wifi_specific_scan(enum connman_service_type type,
3089 struct connman_device *device, int scan_type,
3090 GSList *specific_scan_list, void *user_data)
3092 GSList *list = NULL;
3094 struct wifi_data *wifi = connman_device_get_data(device);
3095 GSupplicantScanParams *scan_params = NULL;
3096 struct scan_ssid *scan_ssid = NULL;
3105 if (wifi->p2p_device)
3108 if (type == CONNMAN_SERVICE_TYPE_P2P)
3109 return p2p_find(device);
3111 if (wifi->tethering)
3115 connman_device_get_scanning(device,
3116 CONNMAN_SERVICE_TYPE_WIFI);
3120 DBG("scan_type: %d", scan_type);
3121 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
3122 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3124 DBG("Failed to allocate memory.");
3128 for (list = specific_scan_list; list; list = list->next) {
3129 ssid = (char *)list->data;
3130 int ssid_len = strlen(ssid);
3132 scan_ssid = g_try_new0(struct scan_ssid, 1);
3134 DBG("Failed to allocate memory.");
3135 g_supplicant_free_scan_params(scan_params);
3139 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
3140 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
3141 scan_ssid->ssid_len = ssid_len;
3142 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3145 scan_params->num_ssids = count;
3147 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
3149 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3151 DBG("Failed to allocate memory.");
3155 guint num_freqs = g_slist_length(specific_scan_list);
3156 DBG("num_freqs: %d", num_freqs);
3158 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
3159 if (!scan_params->freqs) {
3160 DBG("Failed to allocate memory.");
3161 g_free(scan_params);
3166 for (list = specific_scan_list; list; list = list->next) {
3167 freq = GPOINTER_TO_INT(list->data);
3169 scan_params->freqs[count] = freq;
3170 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
3173 scan_params->num_freqs = count;
3175 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
3176 int freq_count, ap_count;
3177 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3179 DBG("Failed to allocate memory.");
3183 guint size = g_slist_length(specific_scan_list);
3185 scan_params->freqs = g_try_new0(uint16_t, size/2);
3186 if (!scan_params->freqs) {
3187 DBG("Failed to allocate memory.");
3188 g_free(scan_params);
3192 ap_count = freq_count = 0;
3193 for (list = specific_scan_list; list; list = list->next) {
3194 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
3195 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
3196 int ssid_len = strlen(ssid);
3198 scan_ssid = g_try_new0(struct scan_ssid, 1);
3200 DBG("Failed to allocate memory.");
3201 g_supplicant_free_scan_params(scan_params);
3205 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
3206 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
3207 scan_ssid->ssid_len = ssid_len;
3208 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3212 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
3213 scan_params->freqs[freq_count] = freq;
3214 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
3218 scan_params->num_ssids = ap_count;
3219 scan_params->num_freqs = freq_count;
3221 DBG("Invalid scan");
3225 reset_autoscan(device);
3226 connman_device_ref(device);
3228 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3229 specific_scan_callback, device);
3232 connman_device_set_scanning(device,
3233 CONNMAN_SERVICE_TYPE_WIFI, true);
3235 g_supplicant_free_scan_params(scan_params);
3236 connman_device_unref(device);
3242 static void wifi_mac_policy_callback(int result,
3243 unsigned int policy,
3246 struct connman_device *device = user_data;
3249 connman_device_mac_policy_notify(device, result, policy);
3251 connman_device_unref(device);
3254 int wifi_set_mac_policy(struct connman_device *device, unsigned int policy)
3256 struct wifi_data *wifi = connman_device_get_data(device);
3262 connman_device_ref(device);
3264 ret = g_supplicant_interface_set_mac_policy(wifi->interface,
3265 wifi_mac_policy_callback,
3268 connman_device_unref(device);
3273 static void wifi_preassoc_mac_policy_callback(int result,
3274 unsigned int policy,
3277 struct connman_device *device = user_data;
3280 connman_device_preassoc_mac_policy_notify(device, result, policy);
3282 connman_device_unref(device);
3285 int wifi_set_preassoc_mac_policy(struct connman_device *device, unsigned int policy)
3287 struct wifi_data *wifi = connman_device_get_data(device);
3293 connman_device_ref(device);
3295 ret = g_supplicant_interface_set_preassoc_mac_policy(wifi->interface,
3296 wifi_preassoc_mac_policy_callback,
3299 connman_device_unref(device);
3304 static void wifi_random_mac_lifetime_callback(int result,
3305 unsigned int lifetime,
3308 struct connman_device *device = user_data;
3311 connman_device_random_mac_lifetime_notify(device, result, lifetime);
3313 connman_device_unref(device);
3316 int wifi_set_random_mac_lifetime(struct connman_device *device, unsigned int lifetime)
3318 struct wifi_data *wifi = connman_device_get_data(device);
3324 connman_device_ref(device);
3326 ret = g_supplicant_interface_set_random_mac_lifetime(wifi->interface,
3327 wifi_random_mac_lifetime_callback,
3330 connman_device_unref(device);
3336 #if defined TIZEN_EXT_WIFI_MESH
3337 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
3340 struct connman_device *device = user_data;
3341 struct wifi_data *wifi = connman_device_get_data(device);
3344 DBG("result %d wifi %p", result, wifi);
3346 scanning = connman_device_get_scanning(device,
3347 CONNMAN_SERVICE_TYPE_MESH);
3349 connman_device_set_scanning(device,
3350 CONNMAN_SERVICE_TYPE_MESH, false);
3353 connman_device_unref(device);
3356 static int mesh_scan(struct connman_device *device)
3358 struct wifi_data *wifi;
3359 struct wifi_mesh_info *mesh_info;
3364 wifi = connman_device_get_data(device);
3366 if (!wifi || !wifi->mesh_interface)
3369 mesh_info = wifi->mesh_info;
3370 reset_autoscan(device);
3371 connman_device_ref(device);
3373 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
3374 mesh_scan_callback, device);
3376 connman_device_unref(device);
3378 connman_device_set_scanning(device,
3379 CONNMAN_SERVICE_TYPE_MESH, true);
3384 static void abort_scan_callback(int result, GSupplicantInterface *interface,
3387 struct connman_device *device = user_data;
3388 struct wifi_data *wifi = connman_device_get_data(device);
3390 DBG("result %d wifi %p", result, wifi);
3392 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
3395 static int mesh_abort_scan(enum connman_service_type type,
3396 struct connman_device *device)
3398 struct wifi_data *wifi = connman_device_get_data(device);
3399 struct wifi_mesh_info *mesh_info;
3403 if (!wifi || !wifi->mesh_interface)
3406 if (type != CONNMAN_SERVICE_TYPE_MESH)
3409 mesh_info = wifi->mesh_info;
3411 scanning = connman_device_get_scanning(device,
3412 CONNMAN_SERVICE_TYPE_MESH);
3416 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
3417 abort_scan_callback, device);
3422 static int mesh_specific_scan(enum connman_service_type type,
3423 struct connman_device *device, const char *ssid,
3424 unsigned int freq, void *user_data)
3426 struct wifi_data *wifi = connman_device_get_data(device);
3427 GSupplicantScanParams *scan_params = NULL;
3428 struct wifi_mesh_info *mesh_info;
3429 struct scan_ssid *scan_ssid;
3433 if (!wifi || !wifi->mesh_interface)
3436 if (type != CONNMAN_SERVICE_TYPE_MESH)
3439 if (wifi->p2p_device)
3442 mesh_info = wifi->mesh_info;
3444 scanning = connman_device_get_scanning(device,
3445 CONNMAN_SERVICE_TYPE_MESH);
3449 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3453 scan_ssid = g_try_new(struct scan_ssid, 1);
3455 g_free(scan_params);
3459 scan_ssid->ssid_len = strlen(ssid);
3460 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
3461 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3462 scan_params->num_ssids = 1;
3464 scan_params->freqs = g_try_new(uint16_t, 1);
3465 if (!scan_params->freqs) {
3466 g_slist_free_full(scan_params->ssids, g_free);
3467 g_free(scan_params);
3471 scan_params->freqs[0] = freq;
3472 scan_params->num_freqs = 1;
3474 reset_autoscan(device);
3475 connman_device_ref(device);
3477 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
3478 mesh_scan_callback, device);
3481 connman_device_set_scanning(device,
3482 CONNMAN_SERVICE_TYPE_MESH, true);
3484 g_supplicant_free_scan_params(scan_params);
3485 connman_device_unref(device);
3493 * Note that the hidden scan is only used when connecting to this specific
3494 * hidden AP first time. It is not used when system autoconnects to hidden AP.
3496 static int wifi_scan(struct connman_device *device,
3497 struct connman_device_scan_params *params)
3499 struct wifi_data *wifi = connman_device_get_data(device);
3500 GSupplicantScanParams *scan_params = NULL;
3501 struct scan_ssid *scan_ssid;
3502 struct hidden_params *hidden;
3504 int driver_max_ssids = 0;
3511 if (wifi->p2p_device)
3514 if (wifi->tethering)
3517 if (params->type == CONNMAN_SERVICE_TYPE_P2P)
3518 return p2p_find(device);
3520 #if defined TIZEN_EXT_WIFI_MESH
3521 if (params->type == CONNMAN_SERVICE_TYPE_MESH)
3522 return mesh_scan(device);
3525 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface,
3528 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
3530 if (!params->ssid || params->ssid_len == 0 || params->ssid_len > 32) {
3534 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
3536 DBG("max ssids %d", driver_max_ssids);
3537 if (driver_max_ssids == 0)
3538 return wifi_scan_simple(device);
3542 if (scanning && wifi->hidden && wifi->postpone_hidden)
3548 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3553 scan_ssid = g_try_new(struct scan_ssid, 1);
3555 g_free(scan_params);
3559 memcpy(scan_ssid->ssid, params->ssid, params->ssid_len);
3560 scan_ssid->ssid_len = params->ssid_len;
3561 scan_params->ssids = g_slist_prepend(scan_params->ssids,
3563 scan_params->num_ssids = 1;
3565 hidden = g_try_new0(struct hidden_params, 1);
3567 g_supplicant_free_scan_params(scan_params);
3572 hidden_free(wifi->hidden);
3573 wifi->hidden = NULL;
3576 memcpy(hidden->ssid, params->ssid, params->ssid_len);
3577 hidden->ssid_len = params->ssid_len;
3578 hidden->identity = g_strdup(params->identity);
3579 hidden->passphrase = g_strdup(params->passphrase);
3580 hidden->security = g_strdup(params->security);
3581 hidden->user_data = params->user_data;
3582 wifi->hidden = hidden;
3585 /* Let's keep this active scan for later,
3586 * when current scan will be over. */
3587 wifi->postpone_hidden = TRUE;
3588 hidden->scan_params = scan_params;
3592 } else if (wifi->connected) {
3593 g_supplicant_free_scan_params(scan_params);
3594 return wifi_scan_simple(device);
3595 } else if (!params->force_full_scan) {
3596 ret = get_latest_connections(driver_max_ssids, scan_params);
3598 g_supplicant_free_scan_params(scan_params);
3599 return wifi_scan_simple(device);
3603 /* Distinguish between devices performing passive and active scanning */
3604 wifi_update_scanner_type(wifi, WIFI_SCANNING_ACTIVE);
3606 connman_device_ref(device);
3608 reset_autoscan(device);
3609 #if defined TIZEN_EXT
3611 * When doing a full scan, stored hidden networks also need to be scanned
3612 * so that we can autoconnect to them.
3614 if (params->force_full_scan)
3615 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3616 scan_callback_hidden, device);
3619 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3620 scan_callback, device);
3622 connman_device_set_scanning(device,
3623 CONNMAN_SERVICE_TYPE_WIFI, true);
3624 #if defined TIZEN_EXT
3626 * To allow the Full Scan after ssid based scan, set the flag here
3627 * It is required because Tizen does not use the ConnMan specific
3628 * backgroung Scan feature.Tizen has added the BG Scan feature in
3629 * net-config. To sync with up ConnMan, we need to issue the Full Scan
3630 * after SSID specific scan.
3632 if (!params->force_full_scan && !do_hidden)
3633 wifi->allow_full_scan = TRUE;
3636 g_supplicant_free_scan_params(scan_params);
3637 connman_device_unref(device);
3640 hidden_free(wifi->hidden);
3641 wifi->hidden = NULL;
3648 static void wifi_stop_scan(enum connman_service_type type,
3649 struct connman_device *device)
3651 struct wifi_data *wifi = connman_device_get_data(device);
3653 DBG("device %p wifi %p", device, wifi);
3658 if (type == CONNMAN_SERVICE_TYPE_P2P) {
3659 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
3660 g_source_remove(wifi->p2p_find_timeout);
3661 p2p_find_stop(device);
3666 static void wifi_regdom_callback(int result,
3670 struct connman_device *device = user_data;
3672 connman_device_regdom_notify(device, result, alpha2);
3674 connman_device_unref(device);
3677 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3679 struct wifi_data *wifi = connman_device_get_data(device);
3685 connman_device_ref(device);
3687 ret = g_supplicant_interface_set_country(wifi->interface,
3688 wifi_regdom_callback,
3691 connman_device_unref(device);
3696 static struct connman_device_driver wifi_ng_driver = {
3698 .type = CONNMAN_DEVICE_TYPE_WIFI,
3699 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3700 .probe = wifi_probe,
3701 .remove = wifi_remove,
3702 .enable = wifi_enable,
3703 .disable = wifi_disable,
3705 .stop_scan = wifi_stop_scan,
3706 .set_regdom = wifi_set_regdom,
3707 #if defined TIZEN_EXT
3708 .specific_scan = wifi_specific_scan,
3709 .set_mac_policy = wifi_set_mac_policy,
3710 .set_preassoc_mac_policy = wifi_set_preassoc_mac_policy,
3711 .set_random_mac_lifetime = wifi_set_random_mac_lifetime,
3713 #if defined TIZEN_EXT_WIFI_MESH
3714 .abort_scan = mesh_abort_scan,
3715 .mesh_specific_scan = mesh_specific_scan,
3719 static void system_ready(void)
3723 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3724 connman_error("Failed to register WiFi driver");
3727 static void system_killed(void)
3731 connman_device_driver_unregister(&wifi_ng_driver);
3734 static int network_probe(struct connman_network *network)
3736 #if defined TIZEN_EXT
3737 if (!simplified_log)
3739 DBG("network %p", network);
3744 static void network_remove(struct connman_network *network)
3746 struct connman_device *device = connman_network_get_device(network);
3747 struct wifi_data *wifi;
3748 #if defined TIZEN_EXT
3749 GSupplicantSSID *ssid;
3750 const void *ssid_data;
3751 const char *security;
3754 DBG("network %p", network);
3756 wifi = connman_device_get_data(device);
3760 if (wifi->network != network)
3763 wifi->network = NULL;
3765 #if defined TIZEN_EXT
3766 wifi->disconnecting = false;
3768 if (wifi->pending_network == network)
3769 wifi->pending_network = NULL;
3771 if (wifi->scan_pending_network == network)
3772 wifi->scan_pending_network = NULL;
3775 * If this remove network is for the same network
3776 * for which wpa_supplicant already has a profile
3777 * then need to remove that profile.
3779 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3783 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3786 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3792 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3795 security = connman_network_get_string(network, "WiFi.Security");
3796 ssid->security = network_security(security);
3798 g_supplicant_interface_remove_network(wifi->interface, ssid);
3805 static void connect_callback(int result, GSupplicantInterface *interface,
3808 #if defined TIZEN_EXT
3810 struct wifi_data *wifi;
3812 struct connman_network *network = user_data;
3814 DBG("network %p result %d", network, result);
3816 #if defined TIZEN_EXT
3817 const char *ifname = g_supplicant_interface_get_ifname(interface);
3818 set_connman_bssid(RESET_BSSID, NULL, ifname);
3820 for (list = iface_list; list; list = list->next) {
3823 if (wifi && wifi->network == network)
3827 /* wifi_data may be invalid because wifi is already disabled */
3831 if (connman_network_get_bool(network, "WiFi.Roaming")) {
3833 connman_network_set_bool(network, "WiFi.Roaming", false);
3834 connman_network_set_string(network,
3835 "WiFi.RoamingCurBSSID", NULL);
3837 char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
3838 char *bssid_str = bssid_buff;
3839 unsigned char *bssid;
3840 const char *cur_bssid;
3842 bssid = g_supplicant_interface_get_add_network_bssid(interface);
3844 connman_network_set_bool(network, "WiFi.Roaming", false);
3845 connman_network_set_string(network,
3846 "WiFi.RoamingCurBSSID", NULL);
3850 MACSTR, MAC2STR(bssid));
3852 connman_network_set_string(network,
3853 "WiFi.RoamingDstBSSID", bssid_str);
3855 cur_bssid = connman_network_get_string(network,
3856 "WiFi.RoamingCurBSSID");
3858 __connman_technology_notify_roaming_state(ifname,
3859 "started", cur_bssid, bssid_str);
3864 if (result == -ENOKEY) {
3865 connman_network_set_error(network,
3866 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3867 } else if (result < 0) {
3868 connman_network_set_error(network,
3869 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3872 connman_network_unref(network);
3875 static GSupplicantSecurity network_security(const char *security)
3877 if (g_str_equal(security, "none"))
3878 return G_SUPPLICANT_SECURITY_NONE;
3879 else if (g_str_equal(security, "wep"))
3880 return G_SUPPLICANT_SECURITY_WEP;
3881 else if (g_str_equal(security, "psk"))
3882 return G_SUPPLICANT_SECURITY_PSK;
3883 else if (g_str_equal(security, "wpa"))
3884 return G_SUPPLICANT_SECURITY_PSK;
3885 else if (g_str_equal(security, "rsn"))
3886 return G_SUPPLICANT_SECURITY_PSK;
3887 else if (g_str_equal(security, "ieee8021x"))
3888 return G_SUPPLICANT_SECURITY_IEEE8021X;
3889 #if defined TIZEN_EXT
3890 else if (g_str_equal(security, "ft_psk") == TRUE)
3891 return G_SUPPLICANT_SECURITY_FT_PSK;
3892 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3893 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3894 else if (g_str_equal(security, "sae"))
3895 return G_SUPPLICANT_SECURITY_SAE;
3896 else if (g_str_equal(security, "owe"))
3897 return G_SUPPLICANT_SECURITY_OWE;
3898 else if (g_str_equal(security, "dpp"))
3899 return G_SUPPLICANT_SECURITY_DPP;
3900 else if (g_str_equal(security, "psk_sha256") == TRUE)
3901 return G_SUPPLICANT_SECURITY_PSK_SHA256;
3904 return G_SUPPLICANT_SECURITY_UNKNOWN;
3907 #if defined TIZEN_EXT
3908 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3910 if (security == NULL)
3911 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3913 if (g_str_equal(security, "FT") == TRUE)
3914 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3915 else if (g_str_equal(security, "CCKM") == TRUE)
3916 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3918 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3922 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3924 struct wifi_network *network_data = connman_network_get_data(network);
3925 const char *security;
3926 #if defined TIZEN_EXT
3927 const void *ssid_data;
3930 memset(ssid, 0, sizeof(*ssid));
3931 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3932 #if defined TIZEN_EXT
3933 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3935 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3940 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3942 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3945 ssid->scan_ssid = 1;
3946 security = connman_network_get_string(network, "WiFi.Security");
3947 #if defined TIZEN_EXT
3948 if (connman_network_get_psk_sha256(network))
3949 security = "psk_sha256";
3951 ssid->security = network_security(security);
3953 ssid->keymgmt = network_data->keymgmt;
3954 ssid->ieee80211w = G_SUPPLICANT_MFP_OPTIONAL;
3955 ssid->passphrase = connman_network_get_string(network,
3958 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3961 * If our private key password is unset,
3962 * we use the supplied passphrase. That is needed
3963 * for PEAP where 2 passphrases (identity and client
3964 * cert may have to be provided.
3966 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3967 connman_network_set_string(network,
3968 "WiFi.PrivateKeyPassphrase",
3970 /* We must have an identity for both PEAP and TLS */
3971 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3973 /* Use agent provided identity as a fallback */
3974 if (!ssid->identity || strlen(ssid->identity) == 0)
3975 ssid->identity = connman_network_get_string(network,
3976 "WiFi.AgentIdentity");
3978 ssid->anonymous_identity = connman_network_get_string(network,
3979 "WiFi.AnonymousIdentity");
3980 ssid->ca_cert_path = connman_network_get_string(network,
3982 ssid->subject_match = connman_network_get_string(network,
3983 "WiFi.SubjectMatch");
3984 ssid->altsubject_match = connman_network_get_string(network,
3985 "WiFi.AltSubjectMatch");
3986 ssid->domain_suffix_match = connman_network_get_string(network,
3987 "WiFi.DomainSuffixMatch");
3988 ssid->domain_match = connman_network_get_string(network,
3989 "WiFi.DomainMatch");
3990 ssid->client_cert_path = connman_network_get_string(network,
3991 "WiFi.ClientCertFile");
3992 ssid->private_key_path = connman_network_get_string(network,
3993 "WiFi.PrivateKeyFile");
3994 ssid->private_key_passphrase = connman_network_get_string(network,
3995 "WiFi.PrivateKeyPassphrase");
3996 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3998 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3999 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
4000 #if defined TIZEN_EXT
4001 ssid->connector = connman_network_get_string(network,
4003 ssid->c_sign_key = connman_network_get_string(network,
4005 ssid->net_access_key = connman_network_get_string(network,
4006 "WiFi.NetAccessKey");
4009 #if defined TIZEN_EXT
4010 const char *ifname = connman_device_get_string(
4011 connman_network_get_device(network), "Interface");
4012 if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) {
4013 ssid->bssid_for_connect_len = 6;
4014 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect, ifname);
4015 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
4016 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
4017 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
4018 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
4020 ssid->freq = connman_network_get_frequency(network);
4023 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4024 if (bssid_list && g_slist_length(bssid_list) > 1) {
4026 /* If there are more than one bssid,
4027 * the user-specified bssid is tried only once at the beginning.
4028 * After that, the bssids in the list are tried in order.
4030 if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) {
4031 set_connman_bssid(RESET_BSSID, NULL, ifname);
4036 char buff[WIFI_BSSID_STR_LEN];
4037 const char *dst_bssid = connman_network_get_string(network,
4038 "WiFi.RoamingDstBSSID");
4039 for (list = bssid_list; list; list = list->next) {
4040 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
4042 g_snprintf(buff, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssids->bssid));
4043 buff[WIFI_BSSID_STR_LEN - 1] = '\0';
4046 if (g_strcmp0(dst_bssid, (const gchar *)buff) == 0) {
4047 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
4048 ssid->bssid = buff_bssid;
4049 ssid->freq = (unsigned int)bssids->frequency;
4055 gchar *curr_bssid = g_strdup((const gchar *)buff);
4057 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
4058 DBG("bssid match, try next bssid");
4062 g_hash_table_add(failed_bssids, curr_bssid);
4064 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
4065 ssid->bssid = buff_bssid;
4066 ssid->freq = (unsigned int)bssids->frequency;
4072 connman_network_set_string(network, "WiFi.RoamingDstBSSID", NULL);
4075 ssid->bssid = connman_network_get_bssid(network);
4076 g_hash_table_remove_all(failed_bssids);
4079 ssid->bssid = connman_network_get_bssid(network);
4082 ssid->eap_keymgmt = network_eap_keymgmt(
4083 connman_network_get_string(network, "WiFi.KeymgmtType"));
4084 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
4086 if (g_strcmp0(ssid->eap, "fast") == 0)
4087 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
4089 ssid->keymgmt = connman_network_get_keymgmt(network);
4092 if (connman_setting_get_bool("BackgroundScanning"))
4093 ssid->bgscan = BGSCAN_DEFAULT;
4096 static int network_connect(struct connman_network *network)
4098 struct connman_device *device = connman_network_get_device(network);
4099 struct wifi_data *wifi;
4100 GSupplicantInterface *interface;
4101 GSupplicantSSID *ssid;
4103 DBG("network %p", network);
4108 wifi = connman_device_get_data(device);
4112 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
4116 interface = wifi->interface;
4118 ssid_init(ssid, network);
4120 if (wifi->disconnecting) {
4121 wifi->pending_network = network;
4122 #if defined TIZEN_EXT
4127 wifi->network = connman_network_ref(network);
4129 #if defined TIZEN_EXT
4130 wifi->scan_pending_network = NULL;
4133 return g_supplicant_interface_connect(interface, ssid,
4134 connect_callback, network);
4137 return -EINPROGRESS;
4140 static void disconnect_callback(int result, GSupplicantInterface *interface,
4143 struct disconnect_data *dd = user_data;
4144 struct connman_network *network = dd->network;
4145 #if defined TIZEN_EXT
4147 struct wifi_data *wifi = NULL;
4150 DBG("network %p result %d", network, result);
4152 for (list = iface_list; list; list = list->next) {
4155 if (wifi->network == NULL && wifi->disconnecting == true)
4156 wifi->disconnecting = false;
4158 if (wifi->network == network)
4162 if (wifi && network == wifi->pending_network)
4163 wifi->pending_network = NULL;
4165 /* wifi_data may be invalid because wifi is already disabled */
4170 struct wifi_data *wifi = dd->wifi;
4174 DBG("result %d supplicant interface %p wifi %p networks: current %p "
4175 "pending %p disconnected %p", result, interface, wifi,
4176 wifi->network, wifi->pending_network, network);
4178 if (result == -ECONNABORTED) {
4179 DBG("wifi interface no longer available");
4183 #if defined TIZEN_EXT
4184 if (g_slist_find(wifi->networks, network) &&
4185 wifi->network != wifi->pending_network)
4187 if (g_slist_find(wifi->networks, network))
4189 connman_network_set_connected(network, false);
4191 wifi->disconnecting = false;
4193 if (network != wifi->network) {
4194 if (network == wifi->pending_network)
4195 wifi->pending_network = NULL;
4196 DBG("current wifi network has changed since disconnection");
4200 wifi->network = NULL;
4202 wifi->connected = false;
4204 if (wifi->pending_network) {
4205 network_connect(wifi->pending_network);
4206 wifi->pending_network = NULL;
4209 start_autoscan(wifi->device);
4212 static int network_disconnect(struct connman_network *network)
4214 struct connman_device *device = connman_network_get_device(network);
4215 struct disconnect_data *dd;
4216 struct wifi_data *wifi;
4218 #if defined TIZEN_EXT
4219 struct connman_service *service;
4222 DBG("network %p", network);
4224 wifi = connman_device_get_data(device);
4225 if (!wifi || !wifi->interface)
4228 #if defined TIZEN_EXT
4229 if (connman_network_get_associating(network) == true) {
4230 connman_network_clear_associating(network);
4231 connman_network_set_bool(network, "WiFi.UseWPS", false);
4233 service = connman_service_lookup_from_network(network);
4235 if (service != NULL &&
4236 (__connman_service_is_connected_state(service,
4237 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
4238 __connman_service_is_connected_state(service,
4239 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
4240 (connman_service_get_favorite(service) == false))
4241 __connman_service_set_passphrase(service, NULL);
4244 if (wifi->pending_network == network)
4245 wifi->pending_network = NULL;
4247 if (wifi->scan_pending_network == network)
4248 wifi->scan_pending_network = NULL;
4251 connman_network_set_associating(network, false);
4253 if (wifi->disconnecting)
4256 wifi->disconnecting = true;
4258 dd = g_malloc0(sizeof(*dd));
4260 dd->network = network;
4262 err = g_supplicant_interface_disconnect(wifi->interface,
4263 disconnect_callback, dd);
4265 wifi->disconnecting = false;
4272 #if defined TIZEN_EXT
4273 static void set_connection_mode(struct connman_network *network,
4276 ieee80211_modes_e phy_mode;
4277 connection_mode_e conn_mode;
4279 phy_mode = connman_network_get_phy_mode(network);
4281 case IEEE80211_MODE_B:
4282 if (linkspeed > 0 && linkspeed <= 11)
4283 conn_mode = CONNECTION_MODE_IEEE80211B;
4285 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4288 case IEEE80211_MODE_BG:
4289 if (linkspeed > 0 && linkspeed <= 11)
4290 conn_mode = CONNECTION_MODE_IEEE80211B;
4291 else if (linkspeed > 11 && linkspeed <= 54)
4292 conn_mode = CONNECTION_MODE_IEEE80211G;
4294 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4297 case IEEE80211_MODE_BGN:
4298 if (linkspeed > 0 && linkspeed <= 11)
4299 conn_mode = CONNECTION_MODE_IEEE80211B;
4300 else if (linkspeed > 11 && linkspeed <= 54)
4301 conn_mode = CONNECTION_MODE_IEEE80211G;
4302 else if (linkspeed > 54 && linkspeed <= 450)
4303 conn_mode = CONNECTION_MODE_IEEE80211N;
4305 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4308 case IEEE80211_MODE_A:
4309 if (linkspeed > 0 && linkspeed <= 54)
4310 conn_mode = CONNECTION_MODE_IEEE80211A;
4312 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4315 case IEEE80211_MODE_AN:
4316 if (linkspeed > 0 && linkspeed <= 54)
4317 conn_mode = CONNECTION_MODE_IEEE80211A;
4318 else if (linkspeed > 54 && linkspeed <= 450)
4319 conn_mode = CONNECTION_MODE_IEEE80211N;
4321 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4324 case IEEE80211_MODE_ANAC:
4325 if (linkspeed > 0 && linkspeed <= 54)
4326 conn_mode = CONNECTION_MODE_IEEE80211A;
4327 else if (linkspeed > 54 && linkspeed <= 450)
4328 conn_mode = CONNECTION_MODE_IEEE80211N;
4329 else if (linkspeed > 450 && linkspeed <= 1300)
4330 conn_mode = CONNECTION_MODE_IEEE80211AC;
4332 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4336 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4340 DBG("connection mode(%d)", conn_mode);
4341 connman_network_set_connection_mode(network, conn_mode);
4344 static void signalpoll_callback(int result, int maxspeed, int strength,
4345 int snr, void *user_data, unsigned int est_throughput)
4347 char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
4348 char *bssid_str = bssid_buff;
4349 unsigned char *bssid;
4350 struct timespec curr_time = {0};
4351 __time_t roam_scan_time;
4352 const char *interface = NULL;
4353 struct connman_device *device;
4354 struct connman_network *network = user_data;
4355 GSupplicantNetwork *supplicant_network;
4356 struct wifi_data *wifi = NULL;
4357 uint16_t freq = connman_network_get_frequency(network);
4358 const char *group = connman_network_get_group(network);
4361 DBG("Failed to get maxspeed from signalpoll !");
4362 connman_network_unref(network);
4366 device = connman_network_get_device(network);
4368 wifi = connman_device_get_data(device);
4370 if (group && wifi) {
4371 supplicant_network = g_supplicant_interface_get_network(wifi->interface, group);
4372 if (supplicant_network) {
4373 g_supplicant_network_set_signal(supplicant_network, strength);
4374 g_supplicant_network_set_bss_signal(supplicant_network, strength, snr);
4382 bssid = connman_network_get_bssid(network);
4383 snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
4385 DBG("network %p, bssid %s, freq %u, maxspeed %d, strength %d, snr %d, est_throughput %u",
4386 network, bssid_str, freq, maxspeed, strength, snr, est_throughput);
4388 connman_network_set_strength(network, (uint8_t)strength);
4389 connman_network_set_snr(network, snr);
4390 connman_network_set_est_throughput(network, est_throughput);
4391 connman_network_set_maxspeed(network, maxspeed);
4392 set_connection_mode(network, maxspeed);
4394 if (connman_network_get_max_bssid_count(network) <= 1)
4397 clock_gettime(CLOCK_MONOTONIC, &curr_time);
4398 roam_scan_time = connman_network_get_roam_scan_time(network);
4399 if (curr_time.tv_sec <= roam_scan_time + ROAM_SCAN_INTERVAL)
4402 if (device && need_bss_transition(freq, snr, strength)) {
4404 interface = connman_device_get_string(device, "Interface");
4405 __connman_technology_notify_roaming_state(interface, "required", bssid_str, NULL);
4407 if (connman_setting_get_bool("WifiRoamingScan") == false)
4410 throw_wifi_scan(device, scan_callback);
4411 connman_network_set_roam_scan_time(network, curr_time.tv_sec);
4415 connman_network_unref(network);
4418 static int network_signalpoll(struct wifi_data *wifi)
4420 GSupplicantInterface *interface;
4421 struct connman_network *network;
4423 if (!wifi || !wifi->network)
4426 wifi->network = connman_network_ref(wifi->network);
4428 interface = wifi->interface;
4429 network = wifi->network;
4431 DBG("network %p", network);
4433 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
4436 static gboolean autosignalpoll_timeout(gpointer data)
4438 struct wifi_data *wifi = data;
4440 if (!wifi || !wifi->automaxspeed_timeout) {
4441 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
4445 int ret = network_signalpoll(wifi);
4447 DBG("Fail to get max speed !!");
4448 wifi->automaxspeed_timeout = 0;
4451 connman_network_unref(wifi->network);
4460 static struct connman_network_driver network_driver = {
4462 .type = CONNMAN_NETWORK_TYPE_WIFI,
4463 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
4464 .probe = network_probe,
4465 .remove = network_remove,
4466 .connect = network_connect,
4467 .disconnect = network_disconnect,
4470 static void interface_added(GSupplicantInterface *interface)
4472 const char *ifname = g_supplicant_interface_get_ifname(interface);
4473 const char *driver = g_supplicant_interface_get_driver(interface);
4474 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4476 * Note: If supplicant interface's driver is wired then skip it,
4477 * because it meanti only for ethernet not Wi-Fi.
4479 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
4481 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4483 #if defined TIZEN_EXT
4484 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
4487 struct wifi_data *wifi;
4489 wifi = g_supplicant_interface_get_data(interface);
4491 wifi = get_pending_wifi_data(ifname);
4495 wifi->interface = interface;
4496 g_supplicant_interface_set_data(interface, wifi);
4497 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
4498 wifi->p2p_device = true;
4501 DBG("ifname %s driver %s wifi %p tethering %d",
4502 ifname, driver, wifi, wifi->tethering);
4504 if (!wifi->device) {
4505 connman_error("WiFi device not set");
4509 connman_device_set_powered(wifi->device, true);
4510 #if defined TIZEN_EXT
4511 connman_device_set_wifi_5ghz_supported(wifi->device, is_5_0_ghz_supported);
4512 /* Max number of SSIDs supported by wlan chipset that can be scanned */
4513 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
4514 connman_device_set_max_scan_ssids(wifi->device, max_scan_ssids);
4518 static bool is_idle(struct wifi_data *wifi)
4520 DBG("state %d", wifi->state);
4522 switch (wifi->state) {
4523 case G_SUPPLICANT_STATE_UNKNOWN:
4524 case G_SUPPLICANT_STATE_DISABLED:
4525 case G_SUPPLICANT_STATE_DISCONNECTED:
4526 case G_SUPPLICANT_STATE_INACTIVE:
4527 case G_SUPPLICANT_STATE_SCANNING:
4530 case G_SUPPLICANT_STATE_AUTHENTICATING:
4531 case G_SUPPLICANT_STATE_ASSOCIATING:
4532 case G_SUPPLICANT_STATE_ASSOCIATED:
4533 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4534 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4535 case G_SUPPLICANT_STATE_COMPLETED:
4542 static bool is_idle_wps(GSupplicantInterface *interface,
4543 struct wifi_data *wifi)
4545 /* First, let's check if WPS processing did not went wrong */
4546 if (g_supplicant_interface_get_wps_state(interface) ==
4547 G_SUPPLICANT_WPS_STATE_FAIL)
4550 /* Unlike normal connection, being associated while processing wps
4551 * actually means that we are idling. */
4552 switch (wifi->state) {
4553 case G_SUPPLICANT_STATE_UNKNOWN:
4554 case G_SUPPLICANT_STATE_DISABLED:
4555 case G_SUPPLICANT_STATE_DISCONNECTED:
4556 case G_SUPPLICANT_STATE_INACTIVE:
4557 case G_SUPPLICANT_STATE_SCANNING:
4558 case G_SUPPLICANT_STATE_ASSOCIATED:
4560 case G_SUPPLICANT_STATE_AUTHENTICATING:
4561 case G_SUPPLICANT_STATE_ASSOCIATING:
4562 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4563 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4564 case G_SUPPLICANT_STATE_COMPLETED:
4571 static bool handle_wps_completion(GSupplicantInterface *interface,
4572 struct connman_network *network,
4573 struct connman_device *device,
4574 struct wifi_data *wifi)
4578 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4580 const unsigned char *ssid, *wps_ssid;
4581 unsigned int ssid_len, wps_ssid_len;
4582 struct disconnect_data *dd;
4583 const char *wps_key;
4585 /* Checking if we got associated with requested
4587 ssid = connman_network_get_blob(network, "WiFi.SSID",
4590 wps_ssid = g_supplicant_interface_get_wps_ssid(
4591 interface, &wps_ssid_len);
4593 if (!wps_ssid || wps_ssid_len != ssid_len ||
4594 memcmp(ssid, wps_ssid, ssid_len) != 0) {
4595 dd = g_malloc0(sizeof(*dd));
4597 dd->network = network;
4599 connman_network_set_associating(network, false);
4600 g_supplicant_interface_disconnect(wifi->interface,
4601 disconnect_callback, dd);
4602 #if defined TIZEN_EXT
4603 connman_network_set_bool(network, "WiFi.UseWPS", false);
4604 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4609 wps_key = g_supplicant_interface_get_wps_key(interface);
4610 #if defined TIZEN_EXT
4611 /* Check the passphrase and encrypt it
4614 gchar *passphrase = g_strdup(wps_key);
4616 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4618 if (check_passphrase_ext(network, passphrase) < 0) {
4619 DBG("[WPS] Invalid passphrase");
4624 ret = send_encryption_request(passphrase, network);
4629 DBG("[WPS] Encryption request succeeded");
4631 DBG("[WPS] Encryption request failed %d", ret);
4634 connman_network_set_string(network, "WiFi.Passphrase",
4637 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4644 static bool handle_assoc_status_code(GSupplicantInterface *interface,
4645 struct wifi_data *wifi)
4647 #if defined TIZEN_EXT
4648 if ((wifi->state == G_SUPPLICANT_STATE_ASSOCIATING ||
4649 wifi->state == G_SUPPLICANT_STATE_AUTHENTICATING ||
4650 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) &&
4652 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
4653 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
4655 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
4656 wifi->load_shaping_retries ++;
4659 wifi->load_shaping_retries = 0;
4663 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
4664 struct connman_network *network,
4665 struct wifi_data *wifi)
4667 struct connman_service *service;
4669 #if defined TIZEN_EXT
4670 const char *security;
4671 if (wifi->connected)
4674 security = connman_network_get_string(network, "WiFi.Security");
4676 if (security && g_str_equal(security, "ieee8021x") == true &&
4677 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4679 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4684 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4687 if ((wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) &&
4688 !((wifi->state == G_SUPPLICANT_STATE_ASSOCIATING) &&
4689 (wifi->assoc_code == ASSOC_STATUS_AUTH_TIMEOUT)))
4692 if (wifi->connected)
4696 service = connman_service_lookup_from_network(network);
4702 if (connman_service_get_favorite(service)) {
4703 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
4708 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4713 #if defined TIZEN_EXT
4714 static bool handle_wifi_assoc_retry(struct connman_network *network,
4715 struct wifi_data *wifi)
4717 const char *security;
4719 if (!wifi->network || wifi->connected || wifi->disconnecting ||
4720 connman_network_get_connecting(network) != true) {
4721 wifi->assoc_retry_count = 0;
4725 if (wifi->state != G_SUPPLICANT_STATE_AUTHENTICATING &&
4726 wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
4727 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
4728 wifi->assoc_retry_count = 0;
4732 security = connman_network_get_string(network, "WiFi.Security");
4733 if (security && g_str_equal(security, "ieee8021x") == true &&
4734 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4735 wifi->assoc_retry_count = 0;
4739 if (wifi->state > assoc_last_state)
4740 assoc_last_state = wifi->state;
4742 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
4743 wifi->assoc_retry_count = 0;
4745 /* Honestly it's not an invalid-key error,
4746 * however QA team recommends that the invalid-key error
4747 * might be better to display for user experience.
4749 switch (assoc_last_state) {
4750 case G_SUPPLICANT_STATE_AUTHENTICATING:
4751 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL);
4753 case G_SUPPLICANT_STATE_ASSOCIATED:
4754 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4757 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
4767 static void handle_wifi_roaming_complete(struct connman_network *network)
4769 const char *cur_bssid;
4770 const char *dst_bssid;
4772 struct connman_device *device;
4773 struct connman_service *service;
4774 struct connman_ipconfig *ipconfig_ipv4;
4775 enum connman_ipconfig_type type;
4776 enum connman_ipconfig_method method;
4778 if (!connman_setting_get_bool("WifiRoaming") ||
4779 !connman_network_get_bool(network, "WiFi.Roaming"))
4782 device = connman_network_get_device(network);
4784 ifname = connman_device_get_string(device, "Interface");
4785 cur_bssid = connman_network_get_string(network,
4786 "WiFi.RoamingCurBSSID");
4787 dst_bssid = connman_network_get_string(network,
4788 "WiFi.RoamingDstBSSID");
4791 if (device && ifname && cur_bssid && dst_bssid) {
4792 __connman_technology_notify_roaming_state(ifname,
4793 "success", cur_bssid, dst_bssid);
4794 connman_network_set_bool(network,
4795 "WiFi.Roaming", false);
4796 connman_network_set_string(network,
4797 "WiFi.RoamingCurBSSID", NULL);
4798 connman_network_set_string(network,
4799 "WiFi.RoamingDstBSSID", NULL);
4801 service = connman_service_lookup_from_network(network);
4805 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4806 if (!ipconfig_ipv4) {
4807 connman_error("Service has no IPv4 configuration");
4811 type = __connman_ipconfig_get_config_type(ipconfig_ipv4);
4812 if (type != CONNMAN_IPCONFIG_TYPE_IPV4)
4815 method = __connman_ipconfig_get_method(ipconfig_ipv4);
4816 if (method != CONNMAN_IPCONFIG_METHOD_DHCP)
4819 connman_network_set_bool(network, "WiFi.RoamingDHCP", true);
4821 if (set_connected_dhcp(network) != 0)
4822 connman_network_set_bool(network, "WiFi.RoamingDHCP", false);
4827 static void interface_state(GSupplicantInterface *interface)
4829 struct connman_network *network;
4830 struct connman_device *device;
4831 struct wifi_data *wifi;
4832 GSupplicantState state = g_supplicant_interface_get_state(interface);
4833 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4835 * Note: If supplicant interface's driver is wired then skip it,
4836 * because it meanti only for ethernet not Wi-Fi.
4838 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
4840 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4845 wifi = g_supplicant_interface_get_data(interface);
4847 DBG("wifi %p interface state %d", wifi, state);
4852 device = wifi->device;
4856 if (state == G_SUPPLICANT_STATE_COMPLETED) {
4857 if (wifi->tethering_param) {
4858 g_free(wifi->tethering_param->ssid);
4859 g_free(wifi->tethering_param);
4860 wifi->tethering_param = NULL;
4863 if (wifi->tethering)
4864 stop_autoscan(device);
4867 if (g_supplicant_interface_get_ready(interface) &&
4868 !wifi->interface_ready) {
4869 wifi->interface_ready = true;
4870 finalize_interface_creation(wifi);
4873 network = wifi->network;
4878 case G_SUPPLICANT_STATE_SCANNING:
4879 #if defined TIZEN_EXT
4880 if (wifi->automaxspeed_timeout != 0) {
4881 g_source_remove(wifi->automaxspeed_timeout);
4882 wifi->automaxspeed_timeout = 0;
4883 DBG("Remove signalpoll timer!!");
4886 if (!connman_network_get_bool(wifi->network, "WiFi.Roaming"))
4888 if (wifi->connected)
4889 connman_network_set_connected(network, false);
4893 case G_SUPPLICANT_STATE_AUTHENTICATING:
4894 case G_SUPPLICANT_STATE_ASSOCIATING:
4895 #if defined TIZEN_EXT
4896 reset_autoscan(device);
4898 stop_autoscan(device);
4900 #if defined TIZEN_EXT
4901 if (!connman_network_get_bool(wifi->network, "WiFi.Roaming"))
4903 if (!wifi->connected)
4904 connman_network_set_associating(network, true);
4908 case G_SUPPLICANT_STATE_COMPLETED:
4909 #if defined TIZEN_EXT
4910 /* though it should be already reset: */
4911 reset_autoscan(device);
4913 wifi->assoc_retry_count = 0;
4915 wifi->scan_pending_network = NULL;
4917 /* should be cleared scanning flag */
4918 bool scanning = connman_device_get_scanning(device,
4919 CONNMAN_SERVICE_TYPE_WIFI);
4921 connman_device_set_scanning(device,
4922 CONNMAN_SERVICE_TYPE_WIFI, false);
4923 connman_device_unref(device);
4926 if (!wifi->automaxspeed_timeout) {
4927 DBG("Going to start signalpoll timer!!");
4928 int ret = network_signalpoll(wifi);
4930 DBG("Fail to get max speed !!");
4932 wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
4935 g_hash_table_remove_all(failed_bssids);
4936 handle_wifi_roaming_complete(network);
4938 /* though it should be already stopped: */
4939 stop_autoscan(device);
4942 if (!handle_wps_completion(interface, network, device, wifi))
4945 connman_network_set_connected(network, true);
4947 wifi->disconnect_code = 0;
4948 wifi->assoc_code = 0;
4949 wifi->load_shaping_retries = 0;
4952 case G_SUPPLICANT_STATE_DISCONNECTED:
4953 #if defined TIZEN_EXT
4954 connman_network_set_strength(network, 0);
4955 connman_network_set_maxspeed(network, 0);
4957 if (wifi->automaxspeed_timeout != 0) {
4958 g_source_remove(wifi->automaxspeed_timeout);
4959 wifi->automaxspeed_timeout = 0;
4960 DBG("Remove signalpoll timer!!");
4964 * If we're in one of the idle modes, we have
4965 * not started association yet and thus setting
4966 * those ones to FALSE could cancel an association
4969 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4971 if (is_idle_wps(interface, wifi))
4977 #if defined TIZEN_EXT
4978 if (!wifi->connected && handle_assoc_status_code(interface, wifi)) {
4979 GSList *bssid_list = NULL;
4980 guint bssid_length = 0;
4982 #if defined TIZEN_EXT_INS
4983 const char *group = connman_network_get_group(network);
4984 GSupplicantNetwork *supplicant_network;
4987 supplicant_network = g_supplicant_interface_get_network(interface, group);
4989 connman_network_set_assoc_reject_table(network,
4990 g_supplicant_network_clone_assoc_reject_table(supplicant_network));
4992 g_supplicant_network_update_assoc_reject(interface, supplicant_network);
4996 bssid_list = (GSList *)connman_network_get_bssid_list(network);
4998 bssid_length = g_slist_length(bssid_list);
5000 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
5001 network_connect(network);
5005 wifi->load_shaping_retries = 0;
5008 if (handle_assoc_status_code(interface, wifi))
5012 /* If previous state was 4way-handshake, then
5013 * it's either: psk was incorrect and thus we retry
5014 * or if we reach the maximum retries we declare the
5016 if (handle_4way_handshake_failure(interface,
5020 /* See table 8-36 Reason codes in IEEE Std 802.11 */
5021 switch (wifi->disconnect_code) {
5022 #if defined TIZEN_EXT
5023 case 1: /* Unspecified reason */
5024 /* Let's assume it's because we got blocked */
5026 case 6: /* Class 2 frame received from nonauthenticated STA */
5027 connman_network_set_error(network,
5028 CONNMAN_NETWORK_ERROR_BLOCKED);
5035 #if defined TIZEN_EXT
5036 if (wifi->assoc_retry_count == 0)
5037 assoc_last_state = G_SUPPLICANT_STATE_UNKNOWN;
5039 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
5040 * Retry association until its retry count is expired */
5041 if (handle_wifi_assoc_retry(network, wifi) == true) {
5042 throw_wifi_scan(wifi->device, scan_callback);
5043 wifi->scan_pending_network = wifi->network;
5047 if (wifi->disconnect_code > 0){
5048 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
5049 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
5053 if (network != wifi->pending_network) {
5054 connman_network_set_connected(network, false);
5055 connman_network_set_associating(network, false);
5057 wifi->disconnecting = false;
5059 start_autoscan(device);
5063 case G_SUPPLICANT_STATE_INACTIVE:
5064 #if defined TIZEN_EXT
5065 if (handle_wps_completion(interface, network, device, wifi) == false)
5068 connman_network_set_associating(network, false);
5069 start_autoscan(device);
5073 case G_SUPPLICANT_STATE_UNKNOWN:
5074 case G_SUPPLICANT_STATE_DISABLED:
5075 case G_SUPPLICANT_STATE_ASSOCIATED:
5076 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5077 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5081 old_connected = wifi->connected;
5082 wifi->state = state;
5084 /* Saving wpa_s state policy:
5085 * If connected and if the state changes are roaming related:
5086 * --> We stay connected
5088 * --> We are connected
5090 * --> We are not connected
5093 case G_SUPPLICANT_STATE_AUTHENTICATING:
5094 case G_SUPPLICANT_STATE_ASSOCIATING:
5095 case G_SUPPLICANT_STATE_ASSOCIATED:
5096 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5097 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5098 if (wifi->connected)
5099 connman_warn("Probably roaming right now!"
5100 " Staying connected...");
5102 case G_SUPPLICANT_STATE_SCANNING:
5103 wifi->connected = false;
5106 start_autoscan(device);
5108 case G_SUPPLICANT_STATE_COMPLETED:
5109 wifi->connected = true;
5112 wifi->connected = false;
5119 static void interface_removed(GSupplicantInterface *interface)
5121 const char *ifname = g_supplicant_interface_get_ifname(interface);
5122 struct wifi_data *wifi;
5123 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5125 * Note: If supplicant interface's driver is wired then skip it,
5126 * because it meanti only for ethernet not Wi-Fi.
5128 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5130 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5133 DBG("ifname %s", ifname);
5135 wifi = g_supplicant_interface_get_data(interface);
5137 #if defined TIZEN_EXT_WIFI_MESH
5138 if (wifi && wifi->mesh_interface) {
5139 DBG("Notify mesh interface remove");
5140 connman_mesh_notify_interface_remove(true);
5141 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
5142 g_free(mesh_info->parent_ifname);
5143 g_free(mesh_info->ifname);
5144 g_free(mesh_info->identifier);
5146 wifi->mesh_interface = false;
5147 wifi->mesh_info = NULL;
5153 wifi->interface = NULL;
5155 if (wifi && wifi->tethering)
5158 if (!wifi || !wifi->device) {
5159 DBG("wifi interface already removed");
5163 connman_device_set_powered(wifi->device, false);
5165 check_p2p_technology();
5166 #if defined TIZEN_EXT_WIFI_MESH
5167 check_mesh_technology();
5171 static void set_device_type(const char *type, char dev_type[17])
5173 const char *oui = "0050F204";
5174 const char *category = "0001";
5175 const char *sub_category = "0000";
5177 if (!g_strcmp0(type, "handset")) {
5179 sub_category = "0005";
5180 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
5181 sub_category = "0001";
5182 else if (!g_strcmp0(type, "server"))
5183 sub_category = "0002";
5184 else if (!g_strcmp0(type, "laptop"))
5185 sub_category = "0005";
5186 else if (!g_strcmp0(type, "desktop"))
5187 sub_category = "0006";
5188 else if (!g_strcmp0(type, "tablet"))
5189 sub_category = "0009";
5190 else if (!g_strcmp0(type, "watch"))
5193 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
5196 static void p2p_support(GSupplicantInterface *interface)
5198 char dev_type[17] = {};
5199 const char *hostname;
5200 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5202 * Note: If supplicant interface's driver is wired then skip it,
5203 * because it meanti only for ethernet not Wi-Fi.
5205 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5207 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5215 if (!g_supplicant_interface_has_p2p(interface))
5218 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
5219 DBG("Could not register P2P technology driver");
5223 hostname = connman_utsname_get_hostname();
5225 hostname = "ConnMan";
5227 set_device_type(connman_machine_get_type(), dev_type);
5228 g_supplicant_interface_set_p2p_device_config(interface,
5229 hostname, dev_type);
5230 connman_peer_driver_register(&peer_driver);
5233 static void scan_started(GSupplicantInterface *interface)
5235 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5237 * Note: If supplicant interface's driver is wired then skip it,
5238 * because it meanti only for ethernet not Wi-Fi.
5240 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5242 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5247 static void scan_finished(GSupplicantInterface *interface)
5249 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5251 * Note: If supplicant interface's driver is wired then skip it,
5252 * because it meanti only for ethernet not Wi-Fi.
5254 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5256 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5258 #if defined TIZEN_EXT
5259 struct wifi_data *wifi;
5260 bool is_associating = false;
5261 static bool is_scanning = true;
5266 #if defined TIZEN_EXT
5267 wifi = g_supplicant_interface_get_data(interface);
5268 if (wifi && wifi->scan_pending_network) {
5269 network_connect(wifi->scan_pending_network);
5270 wifi->scan_pending_network = NULL;
5273 //service state - associating
5274 if(!wifi || !wifi->network)
5277 is_associating = connman_network_get_associating(wifi->network);
5278 if(is_associating && is_scanning){
5279 is_scanning = false;
5280 DBG("send scan for connecting");
5281 throw_wifi_scan(wifi->device, scan_callback);
5292 static void ap_create_fail(GSupplicantInterface *interface)
5294 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5296 * Note: If supplicant interface's driver is wired then skip it,
5297 * because it meanti only for ethernet not Wi-Fi.
5299 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5301 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5303 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5306 if ((wifi->tethering) && (wifi->tethering_param)) {
5307 DBG("%s create AP fail \n",
5308 g_supplicant_interface_get_ifname(wifi->interface));
5310 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
5311 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5312 wifi->tethering = false;
5314 ret = tech_set_tethering(wifi->tethering_param->technology,
5315 wifi->bridge, true);
5317 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
5318 connman_technology_tethering_notify(wifi_technology,false);
5321 g_free(wifi->tethering_param->ssid);
5322 g_free(wifi->tethering_param);
5323 wifi->tethering_param = NULL;
5327 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
5329 unsigned char strength;
5331 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
5332 #if !defined TIZEN_EXT
5340 #if defined TIZEN_EXT_WIFI_MESH
5341 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
5343 GSupplicantInterface *interface;
5344 struct wifi_data *wifi;
5345 const char *name, *security;
5346 struct connman_mesh *connman_mesh;
5347 struct wifi_mesh_info *mesh_info;
5348 const unsigned char *bssid;
5349 const char *identifier;
5354 interface = g_supplicant_network_get_interface(supplicant_network);
5355 wifi = g_supplicant_interface_get_data(interface);
5356 if (!wifi || !wifi->mesh_interface) {
5357 DBG("Virtual Mesh interface not created");
5361 bssid = g_supplicant_network_get_bssid(supplicant_network);
5362 address = g_malloc0(19);
5363 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
5364 bssid[2], bssid[3], bssid[4], bssid[5]);
5366 identifier = g_supplicant_network_get_identifier(supplicant_network);
5367 name = g_supplicant_network_get_name(supplicant_network);
5368 security = g_supplicant_network_get_security(supplicant_network);
5369 frequency = g_supplicant_network_get_frequency(supplicant_network);
5371 mesh_info = wifi->mesh_info;
5372 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
5376 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
5378 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
5379 connman_mesh_set_name(connman_mesh, name);
5380 connman_mesh_set_security(connman_mesh, security);
5381 connman_mesh_set_frequency(connman_mesh, frequency);
5382 connman_mesh_set_address(connman_mesh, address);
5383 connman_mesh_set_index(connman_mesh, mesh_info->index);
5384 connman_mesh_set_strength(connman_mesh,
5385 calculate_strength(supplicant_network));
5386 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
5388 ret = connman_mesh_register(connman_mesh);
5389 if (ret == -EALREADY)
5390 DBG("Mesh Peer is already registered");
5396 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
5398 GSupplicantInterface *interface;
5399 struct wifi_data *wifi;
5400 struct connman_mesh *connman_mesh;
5401 struct wifi_mesh_info *mesh_info;
5402 const char *identifier;
5404 interface = g_supplicant_network_get_interface(supplicant_network);
5405 wifi = g_supplicant_interface_get_data(interface);
5406 if (!wifi || !wifi->mesh_interface) {
5407 DBG("Virtual Mesh interface not created");
5411 identifier = g_supplicant_network_get_identifier(supplicant_network);
5413 DBG("Failed to get Mesh Peer identifier");
5417 mesh_info = wifi->mesh_info;
5418 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
5420 /* Do not unregister connected mesh peer */
5421 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
5422 DBG("Mesh Peer %s is connected", identifier);
5425 DBG("Mesh Peer identifier %s removed", identifier);
5426 connman_mesh_unregister(connman_mesh);
5432 #if defined TIZEN_EXT
5433 static GSList *get_supported_security_list(unsigned int keymgmt,
5434 bool owe_transition_mode,
5435 GSupplicantNetwork *supplicant_network)
5437 GSList *sec_list = NULL;
5438 dbus_bool_t privacy = g_supplicant_network_get_privacy(supplicant_network);
5439 const char *enc_mode = g_supplicant_network_get_enc_mode(supplicant_network);
5442 (G_SUPPLICANT_KEYMGMT_WPA_EAP |
5443 G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
5444 sec_list = g_slist_prepend (sec_list, "ieee8021x");
5445 else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
5446 sec_list = g_slist_prepend (sec_list, "ft_ieee8021x");
5452 (G_SUPPLICANT_KEYMGMT_WPA_PSK |
5453 G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) {
5454 if (!g_strcmp0(enc_mode, "aes"))
5455 sec_list = g_slist_prepend (sec_list, "rsn");
5456 else if (!g_strcmp0(enc_mode, "tkip"))
5457 sec_list = g_slist_prepend (sec_list, "psk");
5458 else if (!g_strcmp0(enc_mode, "mixed")) {
5459 sec_list = g_slist_prepend (sec_list, "psk");
5460 sec_list = g_slist_prepend (sec_list, "rsn");
5464 if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
5465 sec_list = g_slist_prepend (sec_list, "ft_psk");
5467 if (keymgmt & G_SUPPLICANT_KEYMGMT_SAE)
5468 sec_list = g_slist_prepend (sec_list, "sae");
5469 if (keymgmt & G_SUPPLICANT_KEYMGMT_FT_SAE)
5470 sec_list = g_slist_prepend (sec_list, "ft_sae");
5472 if (keymgmt & G_SUPPLICANT_KEYMGMT_OWE || owe_transition_mode)
5473 sec_list = g_slist_prepend (sec_list, "owe");
5474 if (keymgmt & G_SUPPLICANT_KEYMGMT_DPP)
5475 sec_list = g_slist_prepend (sec_list, "dpp");
5481 sec_list = g_slist_prepend (sec_list, "wep");
5483 sec_list = g_slist_prepend (sec_list, "none");
5489 static void network_added(GSupplicantNetwork *supplicant_network)
5491 struct connman_network *network;
5492 GSupplicantInterface *interface;
5493 struct wifi_data *wifi;
5494 struct wifi_network *network_data;
5495 const char *name, *identifier, *security, *group, *mode;
5496 const unsigned char *ssid;
5497 unsigned int ssid_len;
5501 bool wps_advertizing;
5503 #if defined TIZEN_EXT
5504 bool owe_transition_mode;
5505 const unsigned char *transition_mode_ssid;
5506 const unsigned char *transition_mode_bssid;
5507 unsigned int transition_mode_ssid_len;
5508 unsigned int keymgmt;
5509 GSList *vsie_list = NULL;
5510 GSList *sec_list = NULL;
5511 const unsigned char *country_code;
5512 ieee80211_modes_e phy_mode;
5515 mode = g_supplicant_network_get_mode(supplicant_network);
5516 identifier = g_supplicant_network_get_identifier(supplicant_network);
5517 #if defined TIZEN_EXT
5518 if (!simplified_log)
5520 DBG("%s", identifier);
5522 if (!g_strcmp0(mode, "adhoc"))
5525 #if defined TIZEN_EXT_WIFI_MESH
5526 if (!g_strcmp0(mode, "mesh")) {
5527 mesh_peer_added(supplicant_network);
5532 interface = g_supplicant_network_get_interface(supplicant_network);
5533 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5535 * Note: If supplicant interface's driver is wired then skip it,
5536 * because it meanti only for ethernet not Wi-Fi.
5538 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5540 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5542 wifi = g_supplicant_interface_get_data(interface);
5543 name = g_supplicant_network_get_name(supplicant_network);
5544 security = g_supplicant_network_get_security(supplicant_network);
5545 group = g_supplicant_network_get_identifier(supplicant_network);
5546 wps = g_supplicant_network_get_wps(supplicant_network);
5547 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
5548 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
5549 wps_advertizing = g_supplicant_network_is_wps_advertizing(
5550 supplicant_network);
5555 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
5557 network = connman_device_get_network(wifi->device, identifier);
5560 network = connman_network_create(identifier,
5561 CONNMAN_NETWORK_TYPE_WIFI);
5565 connman_network_set_index(network, wifi->index);
5567 if (connman_device_add_network(wifi->device, network) < 0) {
5568 connman_network_unref(network);
5572 wifi->networks = g_slist_prepend(wifi->networks, network);
5574 network_data = g_new0(struct wifi_network, 1);
5575 connman_network_set_data(network, network_data);
5578 network_data = connman_network_get_data(network);
5579 network_data->keymgmt =
5580 g_supplicant_network_get_keymgmt(supplicant_network);
5582 if (name && name[0] != '\0')
5583 connman_network_set_name(network, name);
5585 connman_network_set_blob(network, "WiFi.SSID",
5587 #if defined TIZEN_EXT
5588 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
5590 connman_network_set_vsie_list(network, vsie_list);
5592 DBG("vsie_list is NULL");
5593 country_code = g_supplicant_network_get_countrycode(supplicant_network);
5594 connman_network_set_countrycode(network, country_code);
5595 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
5596 connman_network_set_phy_mode(network, phy_mode);
5598 if (g_strcmp0(security, "psk_sha256") == 0) {
5599 connman_network_set_psk_sha256(network, true);
5603 connman_network_set_string(network, "WiFi.Security", security);
5604 connman_network_set_strength(network,
5605 calculate_strength(supplicant_network));
5606 connman_network_set_bool(network, "WiFi.WPS", wps);
5607 connman_network_set_bool(network, "WiFi.WPSAdvertising",
5611 /* Is AP advertizing for WPS association?
5612 * If so, we decide to use WPS by default */
5613 if (wps_ready && wps_pbc &&
5615 #if !defined TIZEN_EXT
5616 connman_network_set_bool(network, "WiFi.UseWPS", true);
5618 DBG("wps is activating by ap but ignore it.");
5622 connman_network_set_frequency(network,
5623 g_supplicant_network_get_frequency(supplicant_network));
5625 #if defined TIZEN_EXT
5626 keymgmt = g_supplicant_network_get_keymgmt(supplicant_network);
5627 connman_network_set_bssid(network,
5628 g_supplicant_network_get_bssid(supplicant_network));
5629 owe_transition_mode = (bool)g_supplicant_network_get_transition_mode(supplicant_network);
5630 connman_network_set_bool(network, "WiFi.TRANSITION_MODE", owe_transition_mode);
5631 if (owe_transition_mode) {
5632 transition_mode_ssid = (unsigned char *)g_supplicant_network_get_transition_mode_ssid(supplicant_network, &transition_mode_ssid_len);
5633 connman_network_set_blob(network, "WiFi.TRANSITION_MODE_SSID",
5634 transition_mode_ssid, transition_mode_ssid_len);
5635 transition_mode_bssid = g_supplicant_network_get_transition_mode_bssid(supplicant_network);
5636 connman_network_set_transition_mode_bssid(network, transition_mode_bssid);
5639 sec_list = get_supported_security_list(keymgmt,
5640 owe_transition_mode, supplicant_network);
5642 connman_network_set_sec_list(network, sec_list);
5643 connman_network_set_maxrate(network,
5644 g_supplicant_network_get_maxrate(supplicant_network));
5645 connman_network_set_enc_mode(network,
5646 g_supplicant_network_get_enc_mode(supplicant_network));
5647 connman_network_set_rsn_mode(network,
5648 g_supplicant_network_get_rsn_mode(supplicant_network));
5649 connman_network_set_bool(network, "WiFi.PMFRequired",
5650 (bool)g_supplicant_network_is_pmf_required(supplicant_network));
5651 connman_network_set_keymgmt(network, keymgmt);
5652 connman_network_set_bool(network, "WiFi.HS20AP",
5653 g_supplicant_network_is_hs20AP(supplicant_network));
5654 connman_network_set_bssid_list(network,
5655 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
5657 #if defined TIZEN_EXT_INS
5658 connman_network_set_last_connected_bssid(network,
5659 g_supplicant_network_get_last_connected_bssid(supplicant_network));
5660 connman_network_set_assoc_reject_table(network,
5661 g_supplicant_network_clone_assoc_reject_table(supplicant_network));
5664 connman_network_set_available(network, true);
5665 connman_network_set_string(network, "WiFi.Mode", mode);
5667 #if defined TIZEN_EXT
5672 connman_network_set_group(network, group);
5674 #if defined TIZEN_EXT_INS
5675 g_supplicant_network_set_last_connected_bssid(supplicant_network,
5676 connman_network_get_last_connected_bssid(network));
5679 #if defined TIZEN_EXT
5680 if (wifi_first_scan == true)
5681 found_with_first_scan = true;
5684 if (wifi->hidden && ssid) {
5685 #if defined TIZEN_EXT
5686 if (network_security(wifi->hidden->security) ==
5687 network_security(security) &&
5689 if (!g_strcmp0(wifi->hidden->security, security) &&
5691 wifi->hidden->ssid_len == ssid_len &&
5692 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
5693 connman_network_connect_hidden(network,
5694 wifi->hidden->identity,
5695 wifi->hidden->passphrase,
5696 wifi->hidden->user_data);
5697 wifi->hidden->user_data = NULL;
5698 hidden_free(wifi->hidden);
5699 wifi->hidden = NULL;
5704 static void network_removed(GSupplicantNetwork *network)
5706 GSupplicantInterface *interface;
5707 struct wifi_data *wifi;
5708 const char *name, *identifier;
5709 struct connman_network *connman_network;
5711 #if defined TIZEN_EXT_WIFI_MESH
5713 mode = g_supplicant_network_get_mode(network);
5714 if (!g_strcmp0(mode, "mesh")) {
5715 mesh_peer_removed(network);
5720 interface = g_supplicant_network_get_interface(network);
5721 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5723 * Note: If supplicant interface's driver is wired then skip it,
5724 * because it meanti only for ethernet not Wi-Fi.
5726 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5728 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5730 wifi = g_supplicant_interface_get_data(interface);
5731 identifier = g_supplicant_network_get_identifier(network);
5732 name = g_supplicant_network_get_name(network);
5734 DBG("name %s", name);
5739 connman_network = connman_device_get_network(wifi->device, identifier);
5740 if (!connman_network)
5743 #if defined TIZEN_EXT
5744 if (connman_network == wifi->scan_pending_network)
5745 wifi->scan_pending_network = NULL;
5747 if (connman_network == wifi->pending_network)
5748 wifi->pending_network = NULL;
5750 if(connman_network_get_connecting(connman_network) == true){
5751 connman_network_set_connected(connman_network, false);
5755 wifi->networks = g_slist_remove(wifi->networks, connman_network);
5757 g_free(connman_network_get_data(connman_network));
5758 connman_device_remove_network(wifi->device, connman_network);
5759 connman_network_unref(connman_network);
5762 static void network_changed(GSupplicantNetwork *network, const char *property)
5764 GSupplicantInterface *interface;
5765 struct wifi_data *wifi;
5766 const char *name, *identifier;
5767 struct connman_network *connman_network;
5770 #if defined TIZEN_EXT
5771 const unsigned char *bssid;
5772 unsigned int maxrate;
5775 const unsigned char *country_code;
5776 ieee80211_modes_e phy_mode;
5780 interface = g_supplicant_network_get_interface(network);
5781 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5783 * Note: If supplicant interface's driver is wired then skip it,
5784 * because it meanti only for ethernet not Wi-Fi.
5786 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5788 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5790 wifi = g_supplicant_interface_get_data(interface);
5791 identifier = g_supplicant_network_get_identifier(network);
5792 name = g_supplicant_network_get_name(network);
5794 #if defined TIZEN_EXT
5795 if (!simplified_log)
5796 DBG("name %s property %s", name, property);
5798 DBG("name %s", name);
5804 connman_network = connman_device_get_network(wifi->device, identifier);
5805 if (!connman_network)
5808 if (g_str_equal(property, "WPSCapabilities")) {
5812 bool wps_advertizing;
5814 wps = g_supplicant_network_get_wps(network);
5815 wps_pbc = g_supplicant_network_is_wps_pbc(network);
5816 wps_ready = g_supplicant_network_is_wps_active(network);
5818 g_supplicant_network_is_wps_advertizing(network);
5820 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
5821 connman_network_set_bool(connman_network,
5822 "WiFi.WPSAdvertising", wps_advertizing);
5826 * Is AP advertizing for WPS association?
5827 * If so, we decide to use WPS by default
5829 if (wps_ready && wps_pbc && wps_advertizing)
5830 connman_network_set_bool(connman_network,
5831 "WiFi.UseWPS", true);
5834 update_needed = true;
5835 } else if (g_str_equal(property, "Signal")) {
5836 connman_network_set_strength(connman_network,
5837 calculate_strength(network));
5838 update_needed = true;
5840 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
5841 else if (g_str_equal(property, "LastConnectedBSSID")) {
5842 const char *ident, *group;
5843 char *service_ident;
5846 ident = connman_device_get_ident(wifi->device);
5847 group = connman_network_get_group(connman_network);
5848 if (ident && group) {
5849 service_ident = g_strdup_printf("%s_%s_%s",
5850 __connman_network_get_type(connman_network), ident, group);
5852 need_save = connman_device_set_last_connected_ident(wifi->device, service_ident);
5854 connman_device_save_last_connected(wifi->device);
5856 g_free(service_ident);
5859 connman_network_set_last_connected_bssid(connman_network,
5860 g_supplicant_network_get_last_connected_bssid(network));
5862 update_needed = true;
5863 } else if (g_str_equal(property, "UpdateAssocReject")) {
5864 connman_network_set_assoc_reject_table(connman_network,
5865 g_supplicant_network_clone_assoc_reject_table(network));
5866 update_needed = true;
5868 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
5870 update_needed = false;
5873 connman_network_update(connman_network);
5875 #if defined TIZEN_EXT
5876 bssid = g_supplicant_network_get_bssid(network);
5877 maxrate = g_supplicant_network_get_maxrate(network);
5878 frequency = g_supplicant_network_get_frequency(network);
5879 wps = g_supplicant_network_get_wps(network);
5880 phy_mode = g_supplicant_network_get_phy_mode(network);
5882 connman_network_set_bssid(connman_network, bssid);
5883 connman_network_set_maxrate(connman_network, maxrate);
5884 connman_network_set_frequency(connman_network, frequency);
5885 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
5886 country_code = g_supplicant_network_get_countrycode(network);
5887 connman_network_set_countrycode(connman_network, country_code);
5888 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
5889 connman_network_set_bssid_list(connman_network, bssid_list);
5890 connman_network_set_phy_mode(connman_network, phy_mode);
5892 if (g_str_equal(property, "CheckMultiBssidConnect") &&
5893 connman_network_get_associating(connman_network))
5894 network_connect(connman_network);
5898 static void network_associated(GSupplicantNetwork *network)
5900 GSupplicantInterface *interface;
5901 struct wifi_data *wifi;
5902 struct connman_network *connman_network;
5903 const char *identifier;
5907 interface = g_supplicant_network_get_interface(network);
5910 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5912 * Note: If supplicant interface's driver is wired then skip it,
5913 * because it meanti only for ethernet not Wi-Fi.
5915 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5917 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5920 wifi = g_supplicant_interface_get_data(interface);
5924 /* P2P networks must not be treated as WiFi networks */
5925 if (wifi->p2p_connecting || wifi->p2p_device)
5928 identifier = g_supplicant_network_get_identifier(network);
5930 connman_network = connman_device_get_network(wifi->device, identifier);
5931 if (!connman_network)
5934 if (wifi->network) {
5935 if (wifi->network == connman_network)
5938 unsigned int ssid_len;
5939 DBG("network1 ssid[%s] , OWE[%d],ssid[%s]",
5940 (char *)connman_network_get_blob(wifi->network,"WiFi.SSID", &ssid_len),
5941 connman_network_get_bool(wifi->network,"WiFi.TRANSITION_MODE"),
5942 (char *)connman_network_get_blob(wifi->network,"WiFi.TRANSITION_MODE_SSID", &ssid_len));
5944 DBG("network1 ssid[%s], OWE[%d], ssid[%s]",
5945 (char *)connman_network_get_blob(connman_network,"WiFi.SSID",&ssid_len),
5946 connman_network_get_bool(connman_network,"WiFi.TRANSITION_MODE"),
5947 (char *)connman_network_get_blob(connman_network,"WiFi.TRANSITION_MODE_SSID", &ssid_len));
5948 if (connman_network_check_transition_mode(wifi->network, connman_network)) {//OWE trasition mode check
5949 DBG("OWE transition mode is TRUE");
5954 * This should never happen, we got associated with
5955 * a network different than the one we were expecting.
5957 DBG("Associated to %p while expecting %p",
5958 connman_network, wifi->network);
5960 connman_network_set_associating(wifi->network, false);
5963 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
5965 wifi->network = connman_network_ref(connman_network);
5969 * Interface state changes callback (interface_state) is always
5970 * called before network_associated callback thus we need to call
5971 * interface_state again in order to process the new state now that
5972 * we have the network properly set.
5974 interface_state(interface);
5977 static void sta_authorized(GSupplicantInterface *interface,
5980 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5982 * Note: If supplicant interface's driver is wired then skip it,
5983 * because it meanti only for ethernet not Wi-Fi.
5985 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5987 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5989 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5991 DBG("wifi %p station %s authorized", wifi, addr);
5993 if (!wifi || !wifi->tethering)
5996 __connman_tethering_client_register(addr);
5999 static void sta_deauthorized(GSupplicantInterface *interface,
6002 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6004 * Note: If supplicant interface's driver is wired then skip it,
6005 * because it meanti only for ethernet not Wi-Fi.
6007 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
6009 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6011 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
6013 DBG("wifi %p station %s deauthorized", wifi, addr);
6015 if (!wifi || !wifi->tethering)
6018 __connman_tethering_client_unregister(addr);
6021 static void apply_peer_services(GSupplicantPeer *peer,
6022 struct connman_peer *connman_peer)
6024 const unsigned char *data;
6029 connman_peer_reset_services(connman_peer);
6031 data = g_supplicant_peer_get_widi_ies(peer, &length);
6033 connman_peer_add_service(connman_peer,
6034 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
6038 static void peer_found(GSupplicantPeer *peer)
6040 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
6041 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
6042 struct connman_peer *connman_peer;
6043 const char *identifier, *name;
6046 #if defined TIZEN_EXT
6050 identifier = g_supplicant_peer_get_identifier(peer);
6051 name = g_supplicant_peer_get_name(peer);
6053 DBG("ident: %s", identifier);
6055 connman_peer = connman_peer_get(wifi->device, identifier);
6059 connman_peer = connman_peer_create(identifier);
6060 connman_peer_set_name(connman_peer, name);
6061 connman_peer_set_device(connman_peer, wifi->device);
6062 apply_peer_services(peer, connman_peer);
6064 ret = connman_peer_register(connman_peer);
6065 if (ret < 0 && ret != -EALREADY)
6066 connman_peer_unref(connman_peer);
6068 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
6071 static void peer_lost(GSupplicantPeer *peer)
6073 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
6074 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
6075 struct connman_peer *connman_peer;
6076 const char *identifier;
6081 identifier = g_supplicant_peer_get_identifier(peer);
6083 DBG("ident: %s", identifier);
6085 connman_peer = connman_peer_get(wifi->device, identifier);
6087 if (wifi->p2p_connecting &&
6088 wifi->pending_peer == connman_peer) {
6089 peer_connect_timeout(wifi);
6091 connman_peer_unregister(connman_peer);
6092 connman_peer_unref(connman_peer);
6095 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
6098 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
6100 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
6101 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
6102 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
6103 struct connman_peer *connman_peer;
6104 const char *identifier;
6106 identifier = g_supplicant_peer_get_identifier(peer);
6108 DBG("ident: %s", identifier);
6113 connman_peer = connman_peer_get(wifi->device, identifier);
6118 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
6119 apply_peer_services(peer, connman_peer);
6120 connman_peer_services_changed(connman_peer);
6122 case G_SUPPLICANT_PEER_GROUP_CHANGED:
6123 if (!g_supplicant_peer_is_in_a_group(peer))
6124 p_state = CONNMAN_PEER_STATE_IDLE;
6126 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
6128 case G_SUPPLICANT_PEER_GROUP_STARTED:
6130 case G_SUPPLICANT_PEER_GROUP_FINISHED:
6131 p_state = CONNMAN_PEER_STATE_IDLE;
6133 case G_SUPPLICANT_PEER_GROUP_JOINED:
6134 connman_peer_set_iface_address(connman_peer,
6135 g_supplicant_peer_get_iface_address(peer));
6137 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
6138 p_state = CONNMAN_PEER_STATE_IDLE;
6140 case G_SUPPLICANT_PEER_GROUP_FAILED:
6141 if (g_supplicant_peer_has_requested_connection(peer))
6142 p_state = CONNMAN_PEER_STATE_IDLE;
6144 p_state = CONNMAN_PEER_STATE_FAILURE;
6148 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
6149 p_state == CONNMAN_PEER_STATE_FAILURE) {
6150 if (wifi->p2p_connecting
6151 && connman_peer == wifi->pending_peer)
6152 peer_cancel_timeout(wifi);
6154 p_state = CONNMAN_PEER_STATE_UNKNOWN;
6157 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
6160 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
6161 GSupplicantInterface *g_iface;
6162 struct wifi_data *g_wifi;
6164 g_iface = g_supplicant_peer_get_group_interface(peer);
6168 g_wifi = g_supplicant_interface_get_data(g_iface);
6172 connman_peer_set_as_master(connman_peer,
6173 !g_supplicant_peer_is_client(peer));
6174 connman_peer_set_sub_device(connman_peer, g_wifi->device);
6177 * If wpa_supplicant didn't create a dedicated p2p-group
6178 * interface then mark this interface as p2p_device to avoid
6179 * scan and auto-scan are launched on it while P2P is connected.
6181 if (!g_list_find(p2p_iface_list, g_wifi))
6182 wifi->p2p_device = true;
6185 connman_peer_set_state(connman_peer, p_state);
6188 static void peer_request(GSupplicantPeer *peer)
6190 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
6191 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
6192 struct connman_peer *connman_peer;
6193 const char *identifier;
6195 #if defined TIZEN_EXT
6200 identifier = g_supplicant_peer_get_identifier(peer);
6202 DBG("ident: %s", identifier);
6204 connman_peer = connman_peer_get(wifi->device, identifier);
6208 connman_peer_request_connection(connman_peer);
6211 #if defined TIZEN_EXT
6212 static void system_power_off(void)
6215 struct wifi_data *wifi;
6216 struct connman_service *service;
6217 struct connman_ipconfig *ipconfig_ipv4;
6219 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
6220 for (list = iface_list; list; list = list->next) {
6223 if (wifi->network != NULL) {
6224 service = connman_service_lookup_from_network(wifi->network);
6225 ipconfig_ipv4 = __connman_service_get_ip4config(service);
6226 __connman_dhcp_stop(ipconfig_ipv4);
6232 static void network_merged(GSupplicantNetwork *network)
6234 GSupplicantInterface *interface;
6235 GSupplicantState state;
6236 struct wifi_data *wifi;
6237 const char *identifier;
6238 struct connman_network *connman_network;
6242 interface = g_supplicant_network_get_interface(network);
6246 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6248 * Note: If supplicant interface's driver is wired then skip it,
6249 * because it meanti only for ethernet not Wi-Fi.
6251 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
6253 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6255 state = g_supplicant_interface_get_state(interface);
6256 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
6259 wifi = g_supplicant_interface_get_data(interface);
6263 identifier = g_supplicant_network_get_identifier(network);
6265 connman_network = connman_device_get_network(wifi->device, identifier);
6266 if (!connman_network)
6269 DBG("merged identifier %s", identifier);
6271 if (wifi->connected == FALSE) {
6273 case G_SUPPLICANT_STATE_AUTHENTICATING:
6274 case G_SUPPLICANT_STATE_ASSOCIATING:
6275 case G_SUPPLICANT_STATE_ASSOCIATED:
6276 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
6277 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
6278 connman_network_set_associating(connman_network, TRUE);
6280 case G_SUPPLICANT_STATE_COMPLETED:
6281 connman_network_set_connected(connman_network, TRUE);
6284 DBG("Not handled the state : %d", state);
6289 ishs20AP = g_supplicant_network_is_hs20AP(network);
6292 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
6293 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
6294 connman_network_set_string(connman_network, "WiFi.EAP",
6296 connman_network_set_string(connman_network, "WiFi.Identity",
6297 g_supplicant_network_get_identity(network));
6298 connman_network_set_string(connman_network, "WiFi.Phase2",
6299 g_supplicant_network_get_phase2(network));
6304 wifi->network = connman_network;
6307 static void assoc_failed(void *user_data)
6309 struct connman_network *network = user_data;
6310 connman_network_set_associating(network, false);
6313 static void scan_done(GSupplicantInterface *interface)
6315 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6317 * Note: If supplicant interface's driver is wired then skip it,
6318 * because it meanti only for ethernet not Wi-Fi.
6320 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
6322 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6325 int scan_type = CONNMAN_SCAN_TYPE_WPA_SUPPLICANT;
6326 struct wifi_data *wifi;
6329 for (list = iface_list; list; list = list->next) {
6332 if (interface == wifi->interface) {
6333 scanning = connman_device_get_scanning(wifi->device,
6334 CONNMAN_SERVICE_TYPE_WIFI);
6336 __connman_technology_notify_scan_done(
6337 connman_device_get_string(wifi->device, "Interface"), scan_type);
6344 static void debug(const char *str)
6346 #if defined TIZEN_EXT
6347 if (connman_setting_get_bool("ConnmanSupplicantDebug"))
6349 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
6351 connman_debug("%s", str);
6354 static void disconnect_reasoncode(GSupplicantInterface *interface,
6357 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6359 * Note: If supplicant interface's driver is wired then skip it,
6360 * because it meanti only for ethernet not Wi-Fi.
6362 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
6364 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6366 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
6369 wifi->disconnect_code = reasoncode;
6373 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
6375 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6377 * Note: If supplicant interface's driver is wired then skip it,
6378 * because it meanti only for ethernet not Wi-Fi.
6380 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
6382 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6384 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
6387 wifi->assoc_code = status_code;
6391 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6392 static GSupplicantCallbacks callbacks = {
6393 #else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6394 static const GSupplicantCallbacks callbacks = {
6395 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6396 .system_ready = system_ready,
6397 .system_killed = system_killed,
6398 .interface_added = interface_added,
6399 .interface_state = interface_state,
6400 .interface_removed = interface_removed,
6401 .p2p_support = p2p_support,
6402 .scan_started = scan_started,
6403 .scan_finished = scan_finished,
6404 .ap_create_fail = ap_create_fail,
6405 .network_added = network_added,
6406 .network_removed = network_removed,
6407 .network_changed = network_changed,
6408 .network_associated = network_associated,
6409 .sta_authorized = sta_authorized,
6410 .sta_deauthorized = sta_deauthorized,
6411 .peer_found = peer_found,
6412 .peer_lost = peer_lost,
6413 .peer_changed = peer_changed,
6414 .peer_request = peer_request,
6415 #if defined TIZEN_EXT
6416 .system_power_off = system_power_off,
6417 .network_merged = network_merged,
6418 .assoc_failed = assoc_failed,
6419 .scan_done = scan_done,
6422 .disconnect_reasoncode = disconnect_reasoncode,
6423 .assoc_status_code = assoc_status_code,
6424 #if defined TIZEN_EXT_WIFI_MESH
6425 .mesh_support = mesh_support,
6426 .mesh_group_started = mesh_group_started,
6427 .mesh_group_removed = mesh_group_removed,
6428 .mesh_peer_connected = mesh_peer_connected,
6429 .mesh_peer_disconnected = mesh_peer_disconnected,
6434 static int tech_probe(struct connman_technology *technology)
6436 wifi_technology = technology;
6441 static void tech_remove(struct connman_technology *technology)
6443 wifi_technology = NULL;
6446 static GSupplicantSSID *ssid_ap_init(const struct connman_technology *technology)
6448 GSupplicantSSID *ap;
6449 const char *ssid, *passphrase;
6453 ap = g_try_malloc0(sizeof(GSupplicantSSID));
6457 ret = connman_technology_get_wifi_tethering(technology,
6461 #if defined TIZEN_EXT
6467 ap->mode = G_SUPPLICANT_MODE_MASTER;
6468 #if defined TIZEN_EXT
6469 ap->ssid = (void *) ssid;
6473 ap->ssid_len = strlen(ssid);
6480 if (!passphrase || strlen(passphrase) == 0) {
6481 ap->security = G_SUPPLICANT_SECURITY_NONE;
6482 ap->passphrase = NULL;
6484 ap->security = G_SUPPLICANT_SECURITY_PSK;
6485 ap->protocol = G_SUPPLICANT_PROTO_RSN;
6486 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
6487 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
6488 ap->passphrase = passphrase;
6494 static void ap_start_callback(int result, GSupplicantInterface *interface,
6497 struct wifi_tethering_info *info = user_data;
6499 DBG("result %d index %d bridge %s",
6500 result, info->wifi->index, info->wifi->bridge);
6502 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
6503 connman_inet_remove_from_bridge(info->wifi->index,
6504 info->wifi->bridge);
6506 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
6507 connman_technology_tethering_notify(info->technology, false);
6508 g_free(info->wifi->tethering_param->ssid);
6509 g_free(info->wifi->tethering_param);
6510 info->wifi->tethering_param = NULL;
6514 g_free(info->ifname);
6518 static void ap_create_callback(int result,
6519 GSupplicantInterface *interface,
6522 struct wifi_tethering_info *info = user_data;
6524 DBG("result %d ifname %s", result,
6525 g_supplicant_interface_get_ifname(interface));
6527 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
6528 connman_inet_remove_from_bridge(info->wifi->index,
6529 info->wifi->bridge);
6531 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
6532 connman_technology_tethering_notify(info->technology, false);
6533 g_free(info->wifi->tethering_param->ssid);
6534 g_free(info->wifi->tethering_param);
6535 info->wifi->tethering_param = NULL;
6539 g_free(info->ifname);
6545 info->wifi->interface = interface;
6546 g_supplicant_interface_set_data(interface, info->wifi);
6548 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
6549 connman_error("Failed to set interface ap_scan property");
6551 g_supplicant_interface_connect(interface, info->ssid,
6552 ap_start_callback, info);
6555 static void sta_remove_callback(int result,
6556 GSupplicantInterface *interface,
6559 struct wifi_tethering_info *info = user_data;
6560 const char *driver = connman_setting_get_string("wifi");
6562 DBG("ifname %s result %d ", info->ifname, result);
6564 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
6565 info->wifi->tethering = false;
6566 connman_technology_tethering_notify(info->technology, false);
6568 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
6569 g_free(info->wifi->tethering_param->ssid);
6570 g_free(info->wifi->tethering_param);
6571 info->wifi->tethering_param = NULL;
6574 g_free(info->ifname);
6580 info->wifi->interface = NULL;
6582 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
6585 #endif /* TIZEN_EXT */
6590 static int enable_wifi_tethering(struct connman_technology *technology,
6591 const char *bridge, bool available)
6594 GSupplicantInterface *interface;
6595 struct wifi_data *wifi;
6596 struct wifi_tethering_info *info;
6601 for (list = iface_list; list; list = list->next) {
6604 DBG("wifi %p network %p pending_network %p", wifi,
6605 wifi->network, wifi->pending_network);
6607 interface = wifi->interface;
6612 ifname = g_supplicant_interface_get_ifname(wifi->interface);
6616 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
6617 DBG("%s does not support AP mode (detected)", ifname);
6621 mode = g_supplicant_interface_get_mode(interface);
6622 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
6623 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
6624 DBG("%s does not support AP mode (capability)", ifname);
6628 if (wifi->network && available)
6631 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
6635 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
6636 if (!wifi->tethering_param) {
6642 info->technology = technology;
6643 info->wifi->bridge = bridge;
6644 info->ssid = ssid_ap_init(technology);
6648 info->ifname = g_strdup(ifname);
6650 wifi->tethering_param->technology = technology;
6651 wifi->tethering_param->ssid = ssid_ap_init(technology);
6652 if (!wifi->tethering_param->ssid)
6655 info->wifi->tethering = true;
6656 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
6658 berr = connman_technology_tethering_notify(technology, true);
6662 err = g_supplicant_interface_remove(interface,
6663 sta_remove_callback,
6666 DBG("tethering wifi %p ifname %s", wifi, ifname);
6671 g_free(info->ifname);
6674 g_free(wifi->tethering_param);
6675 wifi->tethering_param = NULL;
6678 * Remove bridge if it was correctly created but remove
6679 * operation failed. Instead, if bridge creation failed then
6680 * break out and do not try again on another interface,
6681 * bridge set-up does not depend on it.
6684 connman_technology_tethering_notify(technology, false);
6692 static int tech_set_tethering(struct connman_technology *technology,
6693 const char *bridge, bool enabled)
6696 struct wifi_data *wifi;
6702 for (list = iface_list; list; list = list->next) {
6705 if (wifi->tethering) {
6706 wifi->tethering = false;
6708 connman_inet_remove_from_bridge(wifi->index,
6710 wifi->bridged = false;
6714 connman_technology_tethering_notify(technology, false);
6719 DBG("trying tethering for available devices");
6720 err = enable_wifi_tethering(technology, bridge, true);
6723 DBG("trying tethering for any device");
6724 err = enable_wifi_tethering(technology, bridge, false);
6730 static void regdom_callback(int result, const char *alpha2, void *user_data)
6734 if (!wifi_technology)
6740 connman_technology_regdom_notify(wifi_technology, alpha2);
6743 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
6745 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
6748 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
6749 static void supp_ins_init(void)
6752 GSupplicantINSPreferredFreq preferred_freq;
6754 string = connman_setting_get_string("INSPreferredFreqBSSID");
6755 if (g_strcmp0(string, "5GHz") == 0)
6756 preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ;
6757 else if (g_strcmp0(string, "2.4GHz") == 0)
6758 preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ;
6760 preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_UNKNOWN;
6762 g_supplicant_set_ins_settings(preferred_freq,
6763 connman_setting_get_bool("INSLastConnectedBSSID"),
6764 connman_setting_get_bool("INSAssocReject"),
6765 connman_setting_get_bool("INSSignalBSSID"),
6766 connman_setting_get_uint("INSPreferredFreqBSSIDScore"),
6767 connman_setting_get_uint("INSLastConnectedBSSIDScore"),
6768 connman_setting_get_uint("INSAssocRejectScore"),
6769 connman_setting_get_int("INSSignalLevel3_5GHz"),
6770 connman_setting_get_int("INSSignalLevel3_2_4GHz")
6773 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
6775 static struct connman_technology_driver tech_driver = {
6777 .type = CONNMAN_SERVICE_TYPE_WIFI,
6778 .probe = tech_probe,
6779 .remove = tech_remove,
6780 .set_tethering = tech_set_tethering,
6781 .set_regdom = tech_set_regdom,
6784 static int wifi_init(void)
6788 err = connman_network_driver_register(&network_driver);
6792 err = g_supplicant_register(&callbacks);
6794 connman_network_driver_unregister(&network_driver);
6798 err = connman_technology_driver_register(&tech_driver);
6800 g_supplicant_unregister(&callbacks);
6801 connman_network_driver_unregister(&network_driver);
6805 #if defined TIZEN_EXT
6806 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
6808 min_snr = connman_setting_get_int("WifiRoamingMinSNR");
6810 min_rssi_2_4GHz = connman_setting_get_int("WifiRoamingMinRSSI_2_4GHz");
6811 if (min_rssi_2_4GHz >= 0)
6812 min_rssi_2_4GHz = RSSI_LEVEL_2_2_4G;
6814 min_rssi_5GHz = connman_setting_get_int("WifiRoamingMinRSSI_5GHz");
6815 if (min_rssi_5GHz >= 0)
6816 min_rssi_5GHz = RSSI_LEVEL_2_5G;
6818 DBG("Min SNR: %d, Min RSSI: %d(2.4GHz), %d(5GHz)",
6819 min_snr, min_rssi_2_4GHz, min_rssi_5GHz);
6823 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
6825 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
6829 static void wifi_exit(void)
6833 connman_technology_driver_unregister(&tech_driver);
6835 g_supplicant_unregister(&callbacks);
6837 connman_network_driver_unregister(&network_driver);
6839 #if defined TIZEN_EXT
6840 g_hash_table_unref(failed_bssids);
6844 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
6845 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)