5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <net/ethernet.h>
34 #include <linux/wireless.h>
37 #define IFF_LOWER_UP 0x10000
40 #include <dbus/dbus.h>
43 #define CONNMAN_API_SUBJECT_TO_CHANGE
44 #include <connman/plugin.h>
45 #include <connman/inet.h>
46 #include <connman/device.h>
47 #include <connman/rtnl.h>
48 #include <connman/technology.h>
49 #include <connman/service.h>
50 #include <connman/peer.h>
51 #include <connman/log.h>
52 #include <connman/storage.h>
53 #include <include/setting.h>
54 #include <connman/provision.h>
55 #include <connman/utsname.h>
56 #include <connman/machine.h>
57 #include <connman/tethering.h>
59 #include <gsupplicant/gsupplicant.h>
61 #include "src/shared/util.h"
63 #define CLEANUP_TIMEOUT 8 /* in seconds */
64 #define INACTIVE_TIMEOUT 12 /* in seconds */
65 #define FAVORITE_MAXIMUM_RETRIES 2
67 #define BGSCAN_DEFAULT "simple:30:-65:300"
68 #define AUTOSCAN_EXPONENTIAL "exponential:3:300"
69 #define AUTOSCAN_SINGLE "single:3"
70 #define SCAN_MAX_DURATION 10
72 #define P2P_FIND_TIMEOUT 30
73 #define P2P_CONNECTION_TIMEOUT 100
74 #define P2P_LISTEN_PERIOD 500
75 #define P2P_LISTEN_INTERVAL 2000
77 #define ASSOC_STATUS_AUTH_TIMEOUT 16
78 #define ASSOC_STATUS_NO_CLIENT 17
80 #define LOAD_SHAPING_MAX_RETRIES 7
82 #define LOAD_SHAPING_MAX_RETRIES 3
86 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
88 /* Wi-Fi Signal Strength (for 2.4G (dB))
92 * Very weak : -83 ~ -88
95 * Wi-Fi Signal Strength (for 5G (dB))
99 * Very weak : -83 ~ -88
102 #define RSSI_LEVEL_2_5G -77
103 #define RSSI_LEVEL_2_24G -75
104 #define RSSI_LEVEL_3_5G -68
105 #define RSSI_LEVEL_3_24G -64
106 #define WIFI_BSSID_STR_LEN 18
107 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
108 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
109 #define ROAM_SCAN_INTERVAL 60 /* 60 seconds */
112 static struct connman_technology *wifi_technology = NULL;
113 static struct connman_technology *p2p_technology = NULL;
115 enum wifi_ap_capability{
117 WIFI_AP_SUPPORTED = 1,
118 WIFI_AP_NOT_SUPPORTED = 2,
121 enum wifi_scanning_type {
122 WIFI_SCANNING_UNKNOWN = 0,
123 WIFI_SCANNING_PASSIVE = 1,
124 WIFI_SCANNING_ACTIVE = 2,
127 struct hidden_params {
129 unsigned int ssid_len;
131 char *anonymous_identity;
133 char *altsubject_match;
134 char *domain_suffix_match;
138 GSupplicantScanParams *scan_params;
143 * Used for autoscan "emulation".
144 * Should be removed when wpa_s autoscan support will be by default.
146 struct autoscan_params {
150 unsigned int timeout;
153 struct wifi_tethering_info {
154 struct wifi_data *wifi;
155 struct connman_technology *technology;
157 GSupplicantSSID *ssid;
162 struct connman_device *device;
163 struct connman_network *network;
164 struct connman_network *pending_network;
166 GSupplicantInterface *interface;
167 GSupplicantState state;
171 enum wifi_ap_capability ap_supported;
173 bool interface_ready;
179 int load_shaping_retries;
180 struct hidden_params *hidden;
181 bool postpone_hidden;
182 struct wifi_tethering_info *tethering_param;
184 * autoscan "emulation".
186 struct autoscan_params *autoscan;
187 enum wifi_scanning_type scanning_type;
188 GSupplicantScanParams *scan_params;
189 unsigned int p2p_find_timeout;
190 unsigned int p2p_connection_timeout;
191 struct connman_peer *pending_peer;
196 #if defined TIZEN_EXT
197 int assoc_retry_count;
198 struct connman_network *scan_pending_network;
199 bool allow_full_scan;
200 unsigned int automaxspeed_timeout;
201 GSupplicantScanParams *hidden_scan_params;
202 unsigned int mac_policy;
203 unsigned int preassoc_mac_policy;
204 unsigned int mac_lifetime;
208 #if defined TIZEN_EXT_WIFI_MESH
210 struct wifi_mesh_info *mesh_info;
214 struct disconnect_data {
215 struct wifi_data *wifi;
216 struct connman_network *network;
219 #if defined TIZEN_EXT
223 #define TIZEN_ASSOC_RETRY_COUNT 4
225 static gboolean wifi_first_scan = false;
226 static gboolean found_with_first_scan = false;
227 static gboolean is_wifi_notifier_registered = false;
228 static GHashTable *failed_bssids = NULL;
229 static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
232 static GList *iface_list = NULL;
234 static GList *pending_wifi_device = NULL;
235 static GList *p2p_iface_list = NULL;
236 static bool wfd_service_registered = false;
238 static void start_autoscan(struct connman_device *device);
239 static int tech_set_tethering(struct connman_technology *technology,
240 const char *identifier, const char *passphrase,
241 const char *bridge, bool enabled);
243 #if defined TIZEN_EXT
244 #define NETCONFIG_SERVICE "net.netconfig"
245 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
246 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
248 struct enc_method_call_data {
249 DBusConnection *connection;
250 struct connman_network *network;
253 static struct enc_method_call_data encrypt_request_data;
255 static void encryption_request_reply(DBusPendingCall *call,
260 DBusMessageIter args;
262 struct connman_service *service;
263 gchar* encrypted_value = NULL;
264 struct connman_network *network = encrypt_request_data.network;
268 reply = dbus_pending_call_steal_reply(call);
270 dbus_error_init(&error);
271 if (dbus_set_error_from_message(&error, reply)) {
272 DBG("send_encryption_request() %s %s", error.name, error.message);
273 dbus_error_free(&error);
277 if (dbus_message_iter_init(reply, &args) == FALSE)
280 dbus_message_iter_get_basic(&args, &out_data);
282 encrypted_value = g_strdup((const gchar *)out_data);
283 service = connman_service_lookup_from_network(network);
286 DBG("encryption result: no service");
290 if (connman_service_get_favorite(service)) {
291 __connman_service_set_passphrase(service, encrypted_value);
292 __connman_service_save(service);
294 connman_network_set_string(network, "WiFi.Passphrase",
297 DBG("encryption result: succeeded");
300 dbus_message_unref(reply);
301 dbus_pending_call_unref(call);
302 dbus_connection_unref(encrypt_request_data.connection);
303 g_free(encrypted_value);
305 encrypt_request_data.connection = NULL;
306 encrypt_request_data.network = NULL;
309 static int send_encryption_request(const char *passphrase,
310 struct connman_network *network)
312 DBusConnection *connection = NULL;
313 DBusMessage *msg = NULL;
314 DBusPendingCall *call;
317 DBG("Invalid parameter");
321 connection = connman_dbus_get_connection();
323 DBG("dbus connection does not exist");
327 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
328 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
330 dbus_connection_unref(connection);
334 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
337 if (!dbus_connection_send_with_reply(connection, msg,
338 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
339 dbus_message_unref(msg);
340 dbus_connection_unref(connection);
345 dbus_message_unref(msg);
346 dbus_connection_unref(connection);
350 encrypt_request_data.connection = connection;
351 encrypt_request_data.network = network;
353 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
354 dbus_message_unref(msg);
360 static int p2p_tech_probe(struct connman_technology *technology)
362 p2p_technology = technology;
367 static void p2p_tech_remove(struct connman_technology *technology)
369 p2p_technology = NULL;
372 static struct connman_technology_driver p2p_tech_driver = {
374 .type = CONNMAN_SERVICE_TYPE_P2P,
375 .probe = p2p_tech_probe,
376 .remove = p2p_tech_remove,
379 static bool is_p2p_connecting(void)
383 for (list = iface_list; list; list = list->next) {
384 struct wifi_data *wifi = list->data;
386 if (wifi->p2p_connecting)
393 static void add_pending_wifi_device(struct wifi_data *wifi)
395 if (g_list_find(pending_wifi_device, wifi))
398 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
401 #if defined TIZEN_EXT_WIFI_MESH
402 struct wifi_mesh_info {
403 struct wifi_data *wifi;
404 GSupplicantInterface *interface;
405 struct connman_mesh *mesh;
412 struct mesh_change_peer_status_info {
414 enum connman_mesh_peer_status peer_status;
415 mesh_change_peer_status_cb_t callback;
419 static struct connman_technology_driver mesh_tech_driver = {
421 .type = CONNMAN_SERVICE_TYPE_MESH,
424 static void mesh_interface_create_callback(int result,
425 GSupplicantInterface *interface,
428 struct wifi_mesh_info *mesh_info = user_data;
429 struct wifi_data *wifi;
430 bool success = false;
432 DBG("result %d ifname %s, mesh_info %p", result,
433 g_supplicant_interface_get_ifname(interface),
436 if (result < 0 || !mesh_info)
439 wifi = mesh_info->wifi;
441 mesh_info->interface = interface;
442 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
443 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
444 DBG("Mesh Interface identifier %s", mesh_info->identifier);
445 wifi->mesh_interface = true;
446 wifi->mesh_info = mesh_info;
447 g_supplicant_interface_set_data(interface, wifi);
451 connman_mesh_notify_interface_create(success);
454 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
457 struct wifi_data *wifi;
458 struct wifi_mesh_info *mesh_info;
459 const char *wifi_ifname;
460 bool parent_found = false;
461 const char *driver = "nl80211";
463 for (list = iface_list; list; list = list->next) {
466 if (!g_supplicant_interface_has_mesh(wifi->interface))
469 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
473 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
480 DBG("Parent interface %s doesn't exist", parent_ifname);
484 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
488 mesh_info->wifi = wifi;
489 mesh_info->ifname = g_strdup(ifname);
490 mesh_info->parent_ifname = g_strdup(parent_ifname);
492 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
493 mesh_interface_create_callback, mesh_info);
497 static void mesh_interface_remove_callback(int result,
498 GSupplicantInterface *interface,
501 struct wifi_data *wifi = user_data;
502 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
503 bool success = false;
505 DBG("result %d mesh_info %p", result, mesh_info);
507 if (result < 0 || !mesh_info)
510 mesh_info->interface = NULL;
511 g_free(mesh_info->parent_ifname);
512 g_free(mesh_info->ifname);
513 g_free(mesh_info->identifier);
515 wifi->mesh_interface = false;
516 wifi->mesh_info = NULL;
520 connman_mesh_notify_interface_remove(success);
523 static int remove_mesh_interface(const char *ifname)
526 struct wifi_data *wifi;
527 struct wifi_mesh_info *mesh_info;
528 bool mesh_if_found = false;
531 for (list = iface_list; list; list = list->next) {
534 if (wifi->mesh_interface) {
535 mesh_if_found = true;
540 if (!mesh_if_found) {
541 DBG("Mesh interface %s doesn't exist", ifname);
545 mesh_info = wifi->mesh_info;
546 ret = g_supplicant_interface_remove(mesh_info->interface,
547 mesh_interface_remove_callback, wifi);
554 static void mesh_disconnect_callback(int result,
555 GSupplicantInterface *interface, void *user_data)
557 struct connman_mesh *mesh = user_data;
559 DBG("result %d interface %p mesh %p", result, interface, mesh);
562 static int mesh_peer_disconnect(struct connman_mesh *mesh)
565 struct wifi_data *wifi;
566 struct wifi_mesh_info *mesh_info;
567 bool mesh_if_found = false;
568 GSupplicantInterface *interface;
570 for (list = iface_list; list; list = list->next) {
573 if (wifi->mesh_interface) {
574 mesh_if_found = true;
579 if (!mesh_if_found) {
580 DBG("Mesh interface is not created");
584 mesh_info = wifi->mesh_info;
586 interface = mesh_info->interface;
587 return g_supplicant_interface_disconnect(interface,
588 mesh_disconnect_callback, mesh);
591 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
594 struct connman_mesh *mesh = user_data;
595 DBG("mesh %p result %d", mesh, result);
598 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
600 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
603 static GSupplicantSecurity mesh_network_security(const char *security)
605 if (g_str_equal(security, "none"))
606 return G_SUPPLICANT_SECURITY_NONE;
607 else if (g_str_equal(security, "sae"))
608 return G_SUPPLICANT_SECURITY_SAE;
610 return G_SUPPLICANT_SECURITY_UNKNOWN;
613 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
616 const char *security;
621 memset(ssid, 0, sizeof(*ssid));
622 ssid->mode = G_SUPPLICANT_MODE_MESH;
624 security = connman_mesh_get_security(mesh);
625 ssid->security = mesh_network_security(security);
627 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
628 ssid->passphrase = connman_mesh_get_passphrase(mesh);
630 ssid->freq = connman_mesh_get_frequency(mesh);
631 name = connman_mesh_get_name(mesh);
633 ssid->ssid_len = strlen(name);
634 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
635 memcpy(ssid->ssid, name, ssid->ssid_len);
640 static int mesh_peer_connect(struct connman_mesh *mesh)
643 struct wifi_data *wifi;
644 struct wifi_mesh_info *mesh_info;
645 bool mesh_if_found = false;
646 GSupplicantInterface *interface;
647 GSupplicantSSID *ssid;
649 for (list = iface_list; list; list = list->next) {
652 if (wifi->mesh_interface) {
653 mesh_if_found = true;
658 if (!mesh_if_found) {
659 DBG("Mesh interface is not created");
663 mesh_info = wifi->mesh_info;
665 interface = mesh_info->interface;
667 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
671 mesh_info->mesh = mesh;
673 mesh_ssid_init(ssid, mesh);
674 return g_supplicant_interface_connect(interface, ssid,
675 mesh_connect_callback, mesh);
678 static void mesh_peer_change_status_callback(int result,
679 GSupplicantInterface *interface,
682 struct mesh_change_peer_status_info *data = user_data;
684 DBG("result %d Peer Status %d", result, data->peer_status);
686 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
687 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
688 connman_mesh_remove_connected_peer(data->peer_address, 52);
692 data->callback(result, data->user_data);
694 g_free(data->peer_address);
699 static int mesh_change_peer_status(const char *peer_address,
700 enum connman_mesh_peer_status status,
701 mesh_change_peer_status_cb_t callback, void *user_data)
704 struct wifi_data *wifi;
705 struct wifi_mesh_info *mesh_info;
706 bool mesh_if_found = false;
707 GSupplicantInterface *interface;
708 struct mesh_change_peer_status_info *data;
711 for (list = iface_list; list; list = list->next) {
714 if (wifi->mesh_interface) {
715 mesh_if_found = true;
720 if (!mesh_if_found) {
721 DBG("Mesh interface is not created");
725 mesh_info = wifi->mesh_info;
727 interface = mesh_info->interface;
730 case CONNMAN_MESH_PEER_ADD:
731 method = "MeshPeerAdd";
733 case CONNMAN_MESH_PEER_REMOVE:
734 method = "MeshPeerRemove";
737 DBG("Invalid method");
741 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
743 DBG("Memory allocation failed");
747 data->peer_address = g_strdup(peer_address);
748 data->peer_status = status;
749 data->callback = callback;
750 data->user_data = user_data;
752 return g_supplicant_interface_mesh_peer_change_status(interface,
753 mesh_peer_change_status_callback, peer_address, method,
757 static struct connman_mesh_driver mesh_driver = {
758 .add_interface = add_mesh_interface,
759 .remove_interface = remove_mesh_interface,
760 .connect = mesh_peer_connect,
761 .disconnect = mesh_peer_disconnect,
762 .change_peer_status = mesh_change_peer_status,
765 static void mesh_support(GSupplicantInterface *interface)
769 if (!g_supplicant_interface_has_mesh(interface))
772 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
773 DBG("Could not register Mesh technology driver");
777 connman_mesh_driver_register(&mesh_driver);
780 static void check_mesh_technology(void)
782 bool mesh_exists = false;
785 for (list = iface_list; list; list = list->next) {
786 struct wifi_data *w = list->data;
789 g_supplicant_interface_has_mesh(w->interface))
794 connman_technology_driver_unregister(&mesh_tech_driver);
795 connman_mesh_driver_unregister(&mesh_driver);
799 static void mesh_group_started(GSupplicantInterface *interface)
801 struct wifi_data *wifi;
802 struct wifi_mesh_info *mesh_info;
803 struct connman_mesh *mesh;
804 const unsigned char *ssid;
805 unsigned int ssid_len;
808 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
809 memcpy(name, ssid, ssid_len);
810 name[ssid_len] = '\0';
811 DBG("name %s", name);
812 wifi = g_supplicant_interface_get_data(interface);
813 DBG("wifi %p", wifi);
818 mesh_info = wifi->mesh_info;
822 mesh = mesh_info->mesh;
826 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
829 static void mesh_group_removed(GSupplicantInterface *interface)
831 struct wifi_data *wifi;
832 struct wifi_mesh_info *mesh_info;
833 struct connman_mesh *mesh;
834 const unsigned char *ssid;
835 unsigned int ssid_len;
836 int disconnect_reason;
839 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
840 memcpy(name, ssid, ssid_len);
841 name[ssid_len] = '\0';
842 DBG("name %s", name);
844 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
845 DBG("Disconnect Reason %d", disconnect_reason);
847 wifi = g_supplicant_interface_get_data(interface);
848 DBG("wifi %p", wifi);
853 mesh_info = wifi->mesh_info;
857 mesh = connman_get_connected_mesh_from_name(name);
859 DBG("%s is not connected", name);
860 mesh = connman_get_connecting_mesh_from_name(name);
862 DBG("%s is not connecting", name);
867 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
868 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
871 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
873 const char *peer_address;
875 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
880 DBG("Peer %s connected", peer_address);
881 connman_mesh_add_connected_peer(peer_address);
884 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
886 const char *peer_address;
889 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
894 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
896 DBG("Peer %s disconnected with reason %d", peer_address, reason);
897 connman_mesh_remove_connected_peer(peer_address, reason);
901 static struct wifi_data *get_pending_wifi_data(const char *ifname)
905 for (list = pending_wifi_device; list; list = list->next) {
906 struct wifi_data *wifi;
907 const char *dev_name;
910 if (!wifi || !wifi->device)
913 dev_name = connman_device_get_string(wifi->device, "Interface");
914 if (!g_strcmp0(ifname, dev_name)) {
915 pending_wifi_device = g_list_delete_link(
916 pending_wifi_device, list);
924 static void remove_pending_wifi_device(struct wifi_data *wifi)
928 link = g_list_find(pending_wifi_device, wifi);
933 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
936 static void peer_cancel_timeout(struct wifi_data *wifi)
938 if (wifi->p2p_connection_timeout > 0)
939 g_source_remove(wifi->p2p_connection_timeout);
941 wifi->p2p_connection_timeout = 0;
942 wifi->p2p_connecting = false;
944 if (wifi->pending_peer) {
945 connman_peer_unref(wifi->pending_peer);
946 wifi->pending_peer = NULL;
950 static gboolean peer_connect_timeout(gpointer data)
952 struct wifi_data *wifi = data;
956 if (wifi->p2p_connecting) {
957 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
958 GSupplicantPeer *gs_peer =
959 g_supplicant_interface_peer_lookup(wifi->interface,
960 connman_peer_get_identifier(wifi->pending_peer));
962 if (g_supplicant_peer_has_requested_connection(gs_peer))
963 state = CONNMAN_PEER_STATE_IDLE;
965 connman_peer_set_state(wifi->pending_peer, state);
968 peer_cancel_timeout(wifi);
973 static void peer_connect_callback(int result, GSupplicantInterface *interface,
976 struct wifi_data *wifi = user_data;
977 struct connman_peer *peer = wifi->pending_peer;
979 DBG("peer %p - %d", peer, result);
985 peer_connect_timeout(wifi);
989 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
991 wifi->p2p_connection_timeout = g_timeout_add_seconds(
992 P2P_CONNECTION_TIMEOUT,
993 peer_connect_timeout, wifi);
996 static int peer_connect(struct connman_peer *peer,
997 enum connman_peer_wps_method wps_method,
1000 struct connman_device *device = connman_peer_get_device(peer);
1001 GSupplicantPeerParams *peer_params;
1002 GSupplicantPeer *gs_peer;
1003 struct wifi_data *wifi;
1007 DBG("peer %p", peer);
1012 wifi = connman_device_get_data(device);
1013 if (!wifi || !wifi->interface)
1016 if (wifi->p2p_connecting)
1019 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1020 connman_peer_get_identifier(peer));
1024 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
1025 pin = g_supplicant_peer_is_wps_pin(gs_peer);
1027 switch (wps_method) {
1028 case CONNMAN_PEER_WPS_UNKNOWN:
1029 if ((pbc && pin) || pin)
1032 case CONNMAN_PEER_WPS_PBC:
1037 case CONNMAN_PEER_WPS_PIN:
1038 if (!pin || !wps_pin)
1043 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1047 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1049 peer_params->wps_pin = g_strdup(wps_pin);
1051 peer_params->master = connman_peer_service_is_master();
1053 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1054 peer_connect_callback, wifi);
1055 if (ret == -EINPROGRESS) {
1056 wifi->pending_peer = connman_peer_ref(peer);
1057 wifi->p2p_connecting = true;
1058 } else if (ret < 0) {
1059 g_free(peer_params->path);
1060 g_free(peer_params->wps_pin);
1061 g_free(peer_params);
1067 static int peer_disconnect(struct connman_peer *peer)
1069 struct connman_device *device = connman_peer_get_device(peer);
1070 GSupplicantPeerParams peer_params = {};
1071 GSupplicantPeer *gs_peer;
1072 struct wifi_data *wifi;
1075 DBG("peer %p", peer);
1080 wifi = connman_device_get_data(device);
1084 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1085 connman_peer_get_identifier(peer));
1089 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1091 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1093 g_free(peer_params.path);
1095 if (ret == -EINPROGRESS) {
1096 peer_cancel_timeout(wifi);
1097 wifi->p2p_device = false;
1103 struct peer_service_registration {
1104 peer_service_registration_cb_t callback;
1108 static bool is_service_wfd(const unsigned char *specs, int length)
1110 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1116 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1118 struct wifi_data *wifi = data;
1120 if (!wifi->interface ||
1121 !g_supplicant_interface_has_p2p(wifi->interface))
1124 if (!wifi->servicing) {
1125 g_supplicant_interface_p2p_listen(wifi->interface,
1126 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1132 static void register_wfd_service_cb(int result,
1133 GSupplicantInterface *iface, void *user_data)
1135 struct peer_service_registration *reg_data = user_data;
1140 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1142 if (reg_data && reg_data->callback) {
1143 reg_data->callback(result, reg_data->user_data);
1148 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1149 const unsigned char *spec,
1150 int spec_length, const unsigned char *query,
1151 int query_length, int version)
1153 GSupplicantP2PServiceParams *params;
1155 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1160 params->version = version;
1161 if (spec_length > 0) {
1162 params->service = g_malloc(spec_length);
1163 memcpy(params->service, spec, spec_length);
1165 } else if (query_length > 0 && spec_length > 0) {
1166 params->query = g_malloc(query_length);
1167 memcpy(params->query, query, query_length);
1168 params->query_length = query_length;
1170 params->response = g_malloc(spec_length);
1171 memcpy(params->response, spec, spec_length);
1172 params->response_length = spec_length;
1174 if (spec_length > 0) {
1175 params->wfd_ies = g_malloc(spec_length);
1176 memcpy(params->wfd_ies, spec, spec_length);
1178 params->wfd_ies_length = spec_length;
1184 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1189 g_free(params->service);
1190 g_free(params->query);
1191 g_free(params->response);
1192 g_free(params->wfd_ies);
1197 static int peer_register_wfd_service(const unsigned char *specification,
1198 int specification_length,
1199 peer_service_registration_cb_t callback,
1202 struct peer_service_registration *reg_data = NULL;
1203 static GSupplicantP2PServiceParams *params;
1208 if (wfd_service_registered)
1211 params = fill_in_peer_service_params(specification,
1212 specification_length, NULL, 0, 0);
1216 reg_data = g_try_malloc0(sizeof(*reg_data));
1222 reg_data->callback = callback;
1223 reg_data->user_data = user_data;
1225 ret = g_supplicant_set_widi_ies(params,
1226 register_wfd_service_cb, reg_data);
1227 if (ret < 0 && ret != -EINPROGRESS)
1230 wfd_service_registered = true;
1234 free_peer_service_params(params);
1240 static void register_peer_service_cb(int result,
1241 GSupplicantInterface *iface, void *user_data)
1243 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1244 struct peer_service_registration *reg_data = user_data;
1246 #if defined TIZEN_EXT
1254 apply_p2p_listen_on_iface(wifi, NULL);
1256 if (reg_data->callback)
1257 reg_data->callback(result, reg_data->user_data);
1262 static int peer_register_service(const unsigned char *specification,
1263 int specification_length,
1264 const unsigned char *query,
1265 int query_length, int version,
1266 peer_service_registration_cb_t callback,
1269 struct peer_service_registration *reg_data;
1270 GSupplicantP2PServiceParams *params;
1277 if (specification && !version && !query &&
1278 is_service_wfd(specification, specification_length)) {
1279 return peer_register_wfd_service(specification,
1280 specification_length, callback, user_data);
1283 reg_data = g_try_malloc0(sizeof(*reg_data));
1287 reg_data->callback = callback;
1288 reg_data->user_data = user_data;
1290 ret_f = -EOPNOTSUPP;
1292 for (list = iface_list; list; list = list->next) {
1293 struct wifi_data *wifi = list->data;
1294 GSupplicantInterface *iface = wifi->interface;
1296 if (!g_supplicant_interface_has_p2p(iface))
1299 params = fill_in_peer_service_params(specification,
1300 specification_length, query,
1301 query_length, version);
1306 ret_f = g_supplicant_interface_p2p_add_service(iface,
1307 register_peer_service_cb, params, reg_data);
1308 if (ret_f == 0 || ret_f == -EINPROGRESS)
1312 ret = g_supplicant_interface_p2p_add_service(iface,
1313 register_peer_service_cb, params, NULL);
1314 if (ret != 0 && ret != -EINPROGRESS)
1315 free_peer_service_params(params);
1318 if (ret_f != 0 && ret_f != -EINPROGRESS)
1324 static int peer_unregister_wfd_service(void)
1326 GSupplicantP2PServiceParams *params;
1329 if (!wfd_service_registered)
1332 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1336 wfd_service_registered = false;
1338 g_supplicant_set_widi_ies(params, NULL, NULL);
1340 for (list = iface_list; list; list = list->next) {
1341 struct wifi_data *wifi = list->data;
1343 if (!g_supplicant_interface_has_p2p(wifi->interface))
1347 if (!wifi->servicing || wifi->servicing < 0) {
1348 g_supplicant_interface_p2p_listen(wifi->interface,
1350 wifi->servicing = 0;
1357 static int peer_unregister_service(const unsigned char *specification,
1358 int specification_length,
1359 const unsigned char *query,
1360 int query_length, int version)
1362 GSupplicantP2PServiceParams *params;
1367 if (specification && !version && !query &&
1368 is_service_wfd(specification, specification_length)) {
1369 ret = peer_unregister_wfd_service();
1370 if (ret != 0 && ret != -EINPROGRESS)
1375 for (list = iface_list; list; list = list->next) {
1376 struct wifi_data *wifi = list->data;
1377 GSupplicantInterface *iface = wifi->interface;
1380 goto stop_listening;
1382 if (!g_supplicant_interface_has_p2p(iface))
1385 params = fill_in_peer_service_params(specification,
1386 specification_length, query,
1387 query_length, version);
1391 ret = g_supplicant_interface_p2p_del_service(iface, params);
1392 if (ret != 0 && ret != -EINPROGRESS)
1393 free_peer_service_params(params);
1396 if (!wifi->servicing || wifi->servicing < 0) {
1397 g_supplicant_interface_p2p_listen(iface, 0, 0);
1398 wifi->servicing = 0;
1405 static struct connman_peer_driver peer_driver = {
1406 .connect = peer_connect,
1407 .disconnect = peer_disconnect,
1408 .register_service = peer_register_service,
1409 .unregister_service = peer_unregister_service,
1412 static void handle_tethering(struct wifi_data *wifi)
1414 if (!wifi->tethering)
1423 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1425 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1428 wifi->bridged = true;
1431 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1433 struct connman_device *device = user_data;
1434 struct wifi_data *wifi = connman_device_get_data(device);
1439 DBG("index %d flags %d change %d", wifi->index, flags, change);
1441 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1443 DBG("interface up");
1445 DBG("interface down");
1448 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1449 if (flags & IFF_LOWER_UP)
1455 if (flags & IFF_LOWER_UP)
1456 handle_tethering(wifi);
1458 wifi->flags = flags;
1461 static int wifi_probe(struct connman_device *device)
1463 struct wifi_data *wifi;
1465 DBG("device %p", device);
1467 wifi = g_try_new0(struct wifi_data, 1);
1471 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1472 wifi->ap_supported = WIFI_AP_UNKNOWN;
1473 wifi->tethering_param = NULL;
1475 connman_device_set_data(device, wifi);
1476 wifi->device = connman_device_ref(device);
1478 wifi->index = connman_device_get_index(device);
1481 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1482 wifi_newlink, device);
1483 if (is_p2p_connecting())
1484 add_pending_wifi_device(wifi);
1486 iface_list = g_list_append(iface_list, wifi);
1491 static void remove_networks(struct connman_device *device,
1492 struct wifi_data *wifi)
1496 for (list = wifi->networks; list; list = list->next) {
1497 struct connman_network *network = list->data;
1499 connman_device_remove_network(device, network);
1500 connman_network_unref(network);
1503 g_slist_free(wifi->networks);
1504 wifi->networks = NULL;
1507 static void remove_peers(struct wifi_data *wifi)
1511 for (list = wifi->peers; list; list = list->next) {
1512 struct connman_peer *peer = list->data;
1514 connman_peer_unregister(peer);
1515 connman_peer_unref(peer);
1518 g_slist_free(wifi->peers);
1522 static void reset_autoscan(struct connman_device *device)
1524 struct wifi_data *wifi = connman_device_get_data(device);
1525 struct autoscan_params *autoscan;
1529 if (!wifi || !wifi->autoscan)
1532 autoscan = wifi->autoscan;
1534 autoscan->interval = 0;
1536 if (autoscan->timeout == 0)
1539 g_source_remove(autoscan->timeout);
1540 autoscan->timeout = 0;
1542 connman_device_unref(device);
1545 static void stop_autoscan(struct connman_device *device)
1547 const struct wifi_data *wifi = connman_device_get_data(device);
1549 if (!wifi || !wifi->autoscan)
1552 reset_autoscan(device);
1554 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1557 static void check_p2p_technology(void)
1559 bool p2p_exists = false;
1562 for (list = iface_list; list; list = list->next) {
1563 struct wifi_data *w = list->data;
1566 g_supplicant_interface_has_p2p(w->interface))
1571 connman_technology_driver_unregister(&p2p_tech_driver);
1572 connman_peer_driver_unregister(&peer_driver);
1576 struct last_connected {
1582 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1584 GTimeVal *aval = (GTimeVal *)a;
1585 GTimeVal *bval = (GTimeVal *)b;
1587 /* Note that the sort order is descending */
1588 if (aval->tv_sec < bval->tv_sec)
1591 if (aval->tv_sec > bval->tv_sec)
1597 static void free_entry(gpointer data)
1599 struct last_connected *entry = data;
1601 g_free(entry->ssid);
1605 static void wifi_remove(struct connman_device *device)
1607 struct wifi_data *wifi = connman_device_get_data(device);
1609 DBG("device %p wifi %p", device, wifi);
1614 stop_autoscan(device);
1616 if (wifi->p2p_device)
1617 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1619 iface_list = g_list_remove(iface_list, wifi);
1621 check_p2p_technology();
1622 #if defined TIZEN_EXT_WIFI_MESH
1623 check_mesh_technology();
1626 remove_pending_wifi_device(wifi);
1628 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
1629 g_source_remove(wifi->p2p_find_timeout);
1630 connman_device_unref(wifi->device);
1633 if (wifi->p2p_connection_timeout)
1634 g_source_remove(wifi->p2p_connection_timeout);
1636 #if defined TIZEN_EXT
1637 if (wifi->automaxspeed_timeout != 0) {
1638 g_source_remove(wifi->automaxspeed_timeout);
1639 wifi->automaxspeed_timeout = 0;
1643 remove_networks(device, wifi);
1646 connman_device_set_powered(device, false);
1647 connman_device_set_data(device, NULL);
1648 connman_device_unref(wifi->device);
1649 connman_rtnl_remove_watch(wifi->watch);
1651 g_supplicant_interface_set_data(wifi->interface, NULL);
1653 g_supplicant_interface_cancel(wifi->interface);
1655 if (wifi->scan_params)
1656 g_supplicant_free_scan_params(wifi->scan_params);
1657 #if defined TIZEN_EXT
1658 if (wifi->hidden_scan_params) {
1659 while (wifi->hidden_scan_params->ssids) {
1660 struct scan_ssid *ssid;
1661 ssid = wifi->hidden_scan_params->ssids->data;
1662 wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
1664 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1668 g_free(wifi->autoscan);
1669 g_free(wifi->identifier);
1673 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1677 for (iter = list; iter; iter = g_slist_next(iter)) {
1678 struct scan_ssid *scan_ssid = iter->data;
1680 if (ssid_len == scan_ssid->ssid_len &&
1681 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1688 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1689 int freq, GSupplicantScanParams *scan_data,
1690 int driver_max_scan_ssids, char *ssid_name)
1693 struct scan_ssid *scan_ssid;
1695 if ((driver_max_scan_ssids == 0 ||
1696 driver_max_scan_ssids > scan_data->num_ssids) &&
1697 (hex_ssid || raw_ssid)) {
1699 unsigned int j = 0, hex;
1702 size_t hex_ssid_len = strlen(hex_ssid);
1704 ssid = g_try_malloc0(hex_ssid_len / 2);
1708 for (i = 0; i < hex_ssid_len; i += 2) {
1709 sscanf(hex_ssid + i, "%02x", &hex);
1718 * If we have already added hidden AP to the list,
1719 * then do not do it again. This might happen if you have
1720 * used or are using multiple wifi cards, so in that case
1721 * you might have multiple service files for same AP.
1723 if (is_duplicate(scan_data->ssids, ssid, j)) {
1729 scan_ssid = g_try_new(struct scan_ssid, 1);
1736 memcpy(scan_ssid->ssid, ssid, j);
1737 scan_ssid->ssid_len = j;
1738 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1741 scan_data->num_ssids++;
1743 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1744 scan_data->num_ssids);
1751 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1753 if (!scan_data->freqs) {
1754 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1755 if (!scan_data->freqs) {
1756 g_slist_free_full(scan_data->ssids, g_free);
1760 scan_data->num_freqs = 1;
1761 scan_data->freqs[0] = freq;
1763 bool duplicate = false;
1765 /* Don't add duplicate entries */
1766 for (i = 0; i < scan_data->num_freqs; i++) {
1767 if (scan_data->freqs[i] == freq) {
1774 scan_data->num_freqs++;
1775 scan_data->freqs = g_try_realloc(scan_data->freqs,
1776 sizeof(uint16_t) * scan_data->num_freqs);
1777 if (!scan_data->freqs) {
1778 g_slist_free_full(scan_data->ssids, g_free);
1781 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1788 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1790 struct connman_config_entry **entries;
1792 #if defined TIZEN_EXT
1793 gchar **services = NULL;
1796 #endif /* defined TIZEN_EXT */
1800 int num_ssids = 0, add_param_failed = 0;
1801 #if defined TIZEN_EXT
1802 GSequenceIter *iter;
1803 GSequence *latest_list;
1804 struct last_connected *entry;
1807 latest_list = g_sequence_new(free_entry);
1811 services = connman_storage_get_services();
1812 for (i = 0; services && services[i]; i++) {
1813 if (strncmp(services[i], "wifi_", 5) != 0)
1816 keyfile = connman_storage_load_service(services[i]);
1820 value = g_key_file_get_boolean(keyfile,
1821 services[i], "Hidden", NULL);
1823 g_key_file_free(keyfile);
1827 value = g_key_file_get_boolean(keyfile,
1828 services[i], "Favorite", NULL);
1830 g_key_file_free(keyfile);
1834 #if defined TIZEN_EXT
1835 value = g_key_file_get_boolean(keyfile,
1836 services[i], "AutoConnect", NULL);
1838 g_key_file_free(keyfile);
1842 gchar *str = g_key_file_get_string(keyfile,
1843 services[i], "Modified", NULL);
1845 g_key_file_free(keyfile);
1848 g_time_val_from_iso8601(str, &modified);
1852 ssid = g_key_file_get_string(keyfile,
1853 services[i], "SSID", NULL);
1855 name = g_key_file_get_string(keyfile, services[i], "Name",
1858 #if defined TIZEN_EXT
1859 entry = g_try_new(struct last_connected, 1);
1861 g_sequence_free(latest_list);
1864 g_key_file_free(keyfile);
1868 entry->modified = modified;
1871 g_sequence_insert_sorted(latest_list, entry,
1874 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1883 g_key_file_free(keyfile);
1886 #if defined TIZEN_EXT
1887 gint length = g_sequence_get_length(latest_list);
1888 iter = g_sequence_get_begin_iter(latest_list);
1890 for (i = 0; i < length; i++) {
1891 entry = g_sequence_get(iter);
1893 ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid);
1899 iter = g_sequence_iter_next(iter);
1902 g_sequence_free(latest_list);
1906 * Check if there are any hidden AP that needs to be provisioned.
1908 entries = connman_config_get_entries("wifi");
1909 for (i = 0; entries && entries[i]; i++) {
1912 if (!entries[i]->hidden)
1915 if (!entries[i]->ssid) {
1916 ssid = entries[i]->name;
1919 ssid = entries[i]->ssid;
1920 len = entries[i]->ssid_len;
1926 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1933 connman_config_free_entries(entries);
1935 if (add_param_failed > 0)
1936 DBG("Unable to scan %d out of %d SSIDs",
1937 add_param_failed, num_ssids);
1939 g_strfreev(services);
1944 static int get_hidden_connections_params(struct wifi_data *wifi,
1945 GSupplicantScanParams *scan_params)
1947 int driver_max_ssids, i;
1948 GSupplicantScanParams *orig_params;
1951 * Scan hidden networks so that we can autoconnect to them.
1952 * We will assume 1 as a default number of ssid to scan.
1954 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1956 if (driver_max_ssids == 0)
1957 driver_max_ssids = 1;
1959 DBG("max ssids %d", driver_max_ssids);
1961 #if defined TIZEN_EXT
1962 if (!wifi->hidden_scan_params) {
1963 wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1964 if (!wifi->hidden_scan_params)
1967 if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
1968 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1969 wifi->hidden_scan_params = NULL;
1975 orig_params = wifi->hidden_scan_params;
1977 if (!wifi->scan_params) {
1978 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1979 if (!wifi->scan_params)
1982 if (get_hidden_connections(wifi->scan_params) == 0) {
1983 g_supplicant_free_scan_params(wifi->scan_params);
1984 wifi->scan_params = NULL;
1990 orig_params = wifi->scan_params;
1993 /* Let's transfer driver_max_ssids params */
1994 for (i = 0; i < driver_max_ssids; i++) {
1995 struct scan_ssid *ssid;
1997 #if defined TIZEN_EXT
1998 if (!wifi->hidden_scan_params->ssids)
2000 if (!wifi->scan_params->ssids)
2004 ssid = orig_params->ssids->data;
2005 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
2006 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
2010 scan_params->num_ssids = i;
2011 scan_params->ssids = g_slist_reverse(scan_params->ssids);
2013 if (orig_params->num_freqs <= 0)
2016 scan_params->freqs =
2017 g_malloc(sizeof(uint16_t) * orig_params->num_freqs);
2018 memcpy(scan_params->freqs, orig_params->freqs,
2019 sizeof(uint16_t) *orig_params->num_freqs);
2021 scan_params->num_freqs = orig_params->num_freqs;
2026 orig_params->num_ssids -= scan_params->num_ssids;
2028 return scan_params->num_ssids;
2031 g_slist_free_full(scan_params->ssids, g_free);
2032 #if defined TIZEN_EXT
2033 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2034 wifi->hidden_scan_params = NULL;
2036 g_supplicant_free_scan_params(wifi->scan_params);
2037 wifi->scan_params = NULL;
2043 static int throw_wifi_scan(struct connman_device *device,
2044 GSupplicantInterfaceCallback callback)
2046 struct wifi_data *wifi = connman_device_get_data(device);
2052 DBG("device %p %p", device, wifi->interface);
2054 if (wifi->tethering)
2057 #if defined TIZEN_EXT
2058 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)
2059 && !wifi->allow_full_scan)
2061 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
2065 connman_device_ref(device);
2067 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2070 connman_device_set_scanning(device,
2071 CONNMAN_SERVICE_TYPE_WIFI, true);
2073 connman_device_unref(device);
2078 static void hidden_free(struct hidden_params *hidden)
2083 if (hidden->scan_params)
2084 g_supplicant_free_scan_params(hidden->scan_params);
2085 g_free(hidden->identity);
2086 g_free(hidden->passphrase);
2087 g_free(hidden->security);
2091 #if defined TIZEN_EXT
2092 static void service_state_changed(struct connman_service *service,
2093 enum connman_service_state state);
2095 static int network_connect(struct connman_network *network);
2097 static struct connman_notifier notifier = {
2099 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
2100 .service_state_changed = service_state_changed,
2103 static void service_state_changed(struct connman_service *service,
2104 enum connman_service_state state)
2106 enum connman_service_type type;
2108 type = connman_service_get_type(service);
2109 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2112 DBG("service %p state %d", service, state);
2115 case CONNMAN_SERVICE_STATE_READY:
2116 case CONNMAN_SERVICE_STATE_ONLINE:
2117 case CONNMAN_SERVICE_STATE_FAILURE:
2118 connman_notifier_unregister(¬ifier);
2119 is_wifi_notifier_registered = FALSE;
2121 __connman_device_request_scan(type);
2129 static gboolean need_bss_transition(uint16_t freq, int snr, int strength)
2132 * Since bssid->strength is a positive value,
2133 * it need to be changed to its original value.
2135 int signal = strength - 120;
2138 * If the currently connected AP matches the following conditions,
2139 * scan for BSS transition is started.
2140 * - SNR is less than 20 or RSSI level is less than 3
2142 if (snr < 20 && snr != 0)
2144 else if (freq > 4900 && signal <= RSSI_LEVEL_2_5G)
2146 else if (freq <= 4900 && signal <= RSSI_LEVEL_2_24G)
2152 static gboolean check_bss_condition(uint16_t freq, int snr, uint16_t strength)
2155 * Since bssid->strength is a positive value,
2156 * it need to be changed to its original value.
2158 int signal = strength - 120;
2161 * If the AP that matches the following conditions exists in the SCAN result,
2162 * BSS transition is started.
2163 * - SNR is 25 or more and RSSI level is greater than 3
2165 if (snr < 25 && snr != 0)
2168 if (freq > 4900 && signal > RSSI_LEVEL_3_5G)
2170 else if (freq <= 4900 && signal > RSSI_LEVEL_3_24G)
2176 static void scan_callback_hidden(int result,
2177 GSupplicantInterface *interface, void *user_data);
2179 static int network_disconnect(struct connman_network *network);
2182 static void scan_callback(int result, GSupplicantInterface *interface,
2185 struct connman_device *device = user_data;
2186 struct wifi_data *wifi = connman_device_get_data(device);
2188 #if defined TIZEN_EXT
2189 bool roaming_needed = false;
2190 bool roaming_ap_found = false;
2191 GSList *list = NULL;
2192 GSList *bssid_list = NULL;
2193 bool favorite_exists = false;
2194 struct connman_network *network = NULL;
2195 struct connman_service *service = NULL;
2198 DBG("result %d wifi %p", result, wifi);
2201 if (wifi->hidden && !wifi->postpone_hidden) {
2202 connman_network_clear_hidden(wifi->hidden->user_data);
2203 hidden_free(wifi->hidden);
2204 wifi->hidden = NULL;
2207 if (wifi->scan_params) {
2208 g_supplicant_free_scan_params(wifi->scan_params);
2209 wifi->scan_params = NULL;
2212 #if defined TIZEN_EXT
2213 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2214 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2215 wifi->hidden_scan_params = NULL;
2221 connman_device_reset_scanning(device);
2223 /* User is connecting to a hidden AP, let's wait for finished event */
2224 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2225 GSupplicantScanParams *scan_params;
2228 wifi->postpone_hidden = false;
2229 scan_params = wifi->hidden->scan_params;
2230 wifi->hidden->scan_params = NULL;
2232 reset_autoscan(device);
2234 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2235 scan_callback, device);
2239 /* On error, let's recall scan_callback, which will cleanup */
2240 return scan_callback(ret, interface, user_data);
2243 #if defined TIZEN_EXT
2245 for (list = wifi->networks; list; list = list->next) {
2246 network = list->data;
2247 service = connman_service_lookup_from_network(network);
2249 if (service != NULL &&
2250 (connman_service_get_favorite(service) == true) &&
2251 (connman_service_get_autoconnect(service) == true)) {
2252 DBG("Favorite service exists [%s]",
2253 connman_network_get_string(network, "Name"));
2254 favorite_exists = true;
2260 if (favorite_exists == false) {
2261 if (wifi && wifi->allow_full_scan) {
2263 DBG("Trigger full channel scan");
2264 wifi->allow_full_scan = false;
2266 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2267 scan_callback_hidden, device);
2271 /* On error, let's recall scan_callback, which will cleanup */
2272 return scan_callback(ret, interface, user_data);
2275 wifi->allow_full_scan = false;
2278 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
2281 connman_device_set_scanning(device,
2282 CONNMAN_SERVICE_TYPE_WIFI, false);
2285 if (result != -ENOLINK)
2286 #if defined TIZEN_EXT
2289 start_autoscan(device);
2292 * If we are here then we were scanning; however, if we are
2293 * also mid-flight disabling the interface, then wifi_disable
2294 * has already cleared the device scanning state and
2295 * unreferenced the device, obviating the need to do it here.
2299 connman_device_unref(device);
2301 #if defined TIZEN_EXT
2305 if (wifi->scan_pending_network && result != -EIO) {
2306 network_connect(wifi->scan_pending_network);
2307 wifi->scan_pending_network = NULL;
2308 connman_network_set_connecting(wifi->network);
2309 } else if (connman_setting_get_bool("WifiRoaming") && wifi->network) {
2310 bssid_list = connman_network_get_bssid_list(wifi->network);
2312 if (g_slist_length(bssid_list) <= 1)
2315 if (!connman_network_get_connected(wifi->network))
2318 if (connman_network_get_bool(wifi->network, "WiFi.Roaming"))
2321 if (!need_bss_transition(
2322 connman_network_get_frequency(wifi->network),
2323 connman_network_get_snr(wifi->network),
2324 connman_network_get_strength(wifi->network)))
2327 for (bssid_list; bssid_list; bssid_list = bssid_list->next) {
2328 struct g_connman_bssids *bssid = bssid_list->data;
2330 if (check_bss_condition(bssid->frequency,
2331 bssid->score_snr, bssid->strength))
2332 roaming_ap_found = true;
2335 if (roaming_ap_found) {
2336 char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
2337 char *bssid_str = bssid_buff;
2338 unsigned char *bssid;
2340 bssid = connman_network_get_bssid(wifi->network);
2341 snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
2342 connman_network_set_string(wifi->network,
2343 "WiFi.RoamingCurBSSID", bssid_str);
2345 network_disconnect(wifi->network);
2346 wifi->pending_network = wifi->network;
2347 connman_network_set_bool(wifi->network, "WiFi.Roaming", true);
2352 if (is_wifi_notifier_registered != true &&
2353 wifi_first_scan == true && found_with_first_scan == true) {
2354 wifi_first_scan = false;
2355 found_with_first_scan = false;
2357 connman_notifier_register(¬ifier);
2358 is_wifi_notifier_registered = true;
2363 static void scan_callback_hidden(int result,
2364 GSupplicantInterface *interface, void *user_data)
2366 struct connman_device *device = user_data;
2367 struct wifi_data *wifi = connman_device_get_data(device);
2368 GSupplicantScanParams *scan_params;
2371 DBG("result %d wifi %p", result, wifi);
2376 /* User is trying to connect to a hidden AP */
2377 if (wifi->hidden && wifi->postpone_hidden)
2380 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2384 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2385 ret = g_supplicant_interface_scan(wifi->interface,
2387 #if defined TIZEN_EXT
2390 scan_callback_hidden,
2397 g_supplicant_free_scan_params(scan_params);
2400 scan_callback(result, interface, user_data);
2403 static gboolean autoscan_timeout(gpointer data)
2405 struct connman_device *device = data;
2406 struct wifi_data *wifi = connman_device_get_data(device);
2407 struct autoscan_params *autoscan;
2413 autoscan = wifi->autoscan;
2415 #if defined TIZEN_EXT
2420 if (autoscan->interval <= 0) {
2421 interval = autoscan->base;
2424 interval = autoscan->interval * autoscan->base;
2426 #if defined TIZEN_EXT
2427 if (autoscan->interval >= autoscan->limit)
2429 if (interval > autoscan->limit)
2431 interval = autoscan->limit;
2433 throw_wifi_scan(wifi->device, scan_callback_hidden);
2436 * In case BackgroundScanning is disabled, interval will reach the
2437 * limit exactly after the very first passive scanning. It allows
2438 * to ensure at most one passive scan is performed in such cases.
2440 if (!connman_setting_get_bool("BackgroundScanning") &&
2441 interval == autoscan->limit) {
2442 g_source_remove(autoscan->timeout);
2443 autoscan->timeout = 0;
2445 connman_device_unref(device);
2451 DBG("interval %d", interval);
2453 autoscan->interval = interval;
2455 autoscan->timeout = g_timeout_add_seconds(interval,
2456 autoscan_timeout, device);
2461 static void start_autoscan(struct connman_device *device)
2463 struct wifi_data *wifi = connman_device_get_data(device);
2464 struct autoscan_params *autoscan;
2471 if (wifi->p2p_device)
2474 if (wifi->connected)
2477 autoscan = wifi->autoscan;
2481 if (autoscan->timeout > 0 || autoscan->interval > 0)
2484 connman_device_ref(device);
2486 autoscan_timeout(device);
2489 static struct autoscan_params *parse_autoscan_params(const char *params)
2491 struct autoscan_params *autoscan;
2498 list_params = g_strsplit(params, ":", 0);
2499 if (list_params == 0)
2502 if (!g_strcmp0(list_params[0], "exponential") &&
2503 g_strv_length(list_params) == 3) {
2504 base = atoi(list_params[1]);
2505 limit = atoi(list_params[2]);
2506 } else if (!g_strcmp0(list_params[0], "single") &&
2507 g_strv_length(list_params) == 2)
2508 base = limit = atoi(list_params[1]);
2510 g_strfreev(list_params);
2514 DBG("Setup %s autoscanning", list_params[0]);
2516 g_strfreev(list_params);
2518 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2520 DBG("Could not allocate memory for autoscan");
2524 DBG("base %d - limit %d", base, limit);
2525 autoscan->base = base;
2526 autoscan->limit = limit;
2531 static void setup_autoscan(struct wifi_data *wifi)
2534 * If BackgroundScanning is enabled, setup exponential
2535 * autoscanning if it has not been previously done.
2537 if (connman_setting_get_bool("BackgroundScanning")) {
2538 wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
2541 #if defined TIZEN_EXT
2543 if (wifi->autoscan) {
2544 g_free(wifi->autoscan);
2545 wifi->autoscan = NULL;
2548 DBG("BackgroundScanning is disabled");
2555 * On the contrary, if BackgroundScanning is disabled, update autoscan
2556 * parameters based on the type of scanning that is being performed.
2558 if (wifi->autoscan) {
2559 g_free(wifi->autoscan);
2560 wifi->autoscan = NULL;
2563 switch (wifi->scanning_type) {
2564 case WIFI_SCANNING_PASSIVE:
2565 /* Do not setup autoscan. */
2567 case WIFI_SCANNING_ACTIVE:
2568 /* Setup one single passive scan after active. */
2569 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2571 case WIFI_SCANNING_UNKNOWN:
2572 /* Setup autoscan in this case but we should never fall here. */
2573 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2579 static void finalize_interface_creation(struct wifi_data *wifi)
2581 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2583 if (!wifi->device) {
2584 connman_error("WiFi device not set");
2588 connman_device_set_powered(wifi->device, true);
2590 if (wifi->p2p_device)
2593 if (!wifi->autoscan)
2594 setup_autoscan(wifi);
2596 start_autoscan(wifi->device);
2599 static void interface_create_callback(int result,
2600 GSupplicantInterface *interface,
2603 struct wifi_data *wifi = user_data;
2604 char *bgscan_range_max;
2607 DBG("result %d ifname %s, wifi %p", result,
2608 g_supplicant_interface_get_ifname(interface),
2611 if (result < 0 || !wifi)
2614 wifi->interface = interface;
2615 g_supplicant_interface_set_data(interface, wifi);
2617 if (g_supplicant_interface_get_ready(interface)) {
2618 wifi->interface_ready = true;
2619 finalize_interface_creation(wifi);
2623 * Set the BSS expiration age to match the long scanning
2624 * interval to avoid the loss of unconnected networks between
2627 bgscan_range_max = strrchr(BGSCAN_DEFAULT, ':');
2628 if (!bgscan_range_max || strlen(bgscan_range_max) < 1)
2631 value = strtol(bgscan_range_max + 1, NULL, 10);
2632 if (value <= 0 || errno == ERANGE)
2635 if (g_supplicant_interface_set_bss_expiration_age(interface,
2636 value + SCAN_MAX_DURATION) < 0) {
2637 connman_warn("Failed to set bss expiration age");
2641 static int wifi_enable(struct connman_device *device)
2643 struct wifi_data *wifi = connman_device_get_data(device);
2646 const char *driver = connman_setting_get_string("wifi");
2649 DBG("device %p %p", device, wifi);
2651 index = connman_device_get_index(device);
2652 if (!wifi || index < 0)
2655 if (is_p2p_connecting())
2656 return -EINPROGRESS;
2658 interface = connman_inet_ifname(index);
2659 ret = g_supplicant_interface_create(interface, driver, NULL,
2661 connman_device_get_mac_policy(device),
2662 connman_device_get_preassoc_mac_policy(device),
2663 connman_device_get_random_mac_lifetime(device),
2664 #endif /* TIZEN_EXT */
2665 interface_create_callback,
2672 return -EINPROGRESS;
2675 static int wifi_disable(struct connman_device *device)
2677 struct wifi_data *wifi = connman_device_get_data(device);
2680 DBG("device %p wifi %p", device, wifi);
2685 wifi->connected = false;
2686 wifi->disconnecting = false;
2688 if (wifi->pending_network)
2689 wifi->pending_network = NULL;
2691 #if !defined TIZEN_EXT
2692 stop_autoscan(device);
2695 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
2696 g_source_remove(wifi->p2p_find_timeout);
2697 wifi->p2p_find_timeout = 0;
2698 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2699 connman_device_unref(wifi->device);
2702 #if defined TIZEN_EXT
2703 if (wifi->automaxspeed_timeout != 0) {
2704 g_source_remove(wifi->automaxspeed_timeout);
2705 wifi->automaxspeed_timeout = 0;
2709 /* In case of a user scan, device is still referenced */
2710 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) {
2711 connman_device_set_scanning(device,
2712 CONNMAN_SERVICE_TYPE_WIFI, false);
2713 connman_device_unref(wifi->device);
2716 #if defined TIZEN_EXT
2717 stop_autoscan(device);
2720 remove_networks(device, wifi);
2723 #if defined TIZEN_EXT
2724 wifi->scan_pending_network = NULL;
2726 if (is_wifi_notifier_registered == true) {
2727 connman_notifier_unregister(¬ifier);
2728 is_wifi_notifier_registered = false;
2732 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2736 return -EINPROGRESS;
2739 static int get_latest_connections(int max_ssids,
2740 GSupplicantScanParams *scan_data)
2742 GSequenceIter *iter;
2743 GSequence *latest_list;
2744 struct last_connected *entry;
2753 latest_list = g_sequence_new(free_entry);
2757 services = connman_storage_get_services();
2758 for (i = 0; services && services[i]; i++) {
2759 if (strncmp(services[i], "wifi_", 5) != 0)
2762 keyfile = connman_storage_load_service(services[i]);
2766 str = g_key_file_get_string(keyfile,
2767 services[i], "Favorite", NULL);
2768 if (!str || g_strcmp0(str, "true")) {
2770 g_key_file_free(keyfile);
2775 str = g_key_file_get_string(keyfile,
2776 services[i], "AutoConnect", NULL);
2777 if (!str || g_strcmp0(str, "true")) {
2779 g_key_file_free(keyfile);
2784 str = g_key_file_get_string(keyfile,
2785 services[i], "Modified", NULL);
2787 g_key_file_free(keyfile);
2790 util_iso8601_to_timeval(str, &modified);
2793 ssid = g_key_file_get_string(keyfile,
2794 services[i], "SSID", NULL);
2796 freq = g_key_file_get_integer(keyfile, services[i],
2799 entry = g_try_new(struct last_connected, 1);
2801 g_sequence_free(latest_list);
2802 g_key_file_free(keyfile);
2804 #if defined TIZEN_EXT
2805 g_strfreev(services);
2811 entry->modified = modified;
2814 g_sequence_insert_sorted(latest_list, entry,
2820 g_key_file_free(keyfile);
2823 g_strfreev(services);
2825 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2827 iter = g_sequence_get_begin_iter(latest_list);
2829 for (i = 0; i < num_ssids; i++) {
2830 entry = g_sequence_get(iter);
2832 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2833 entry->modified.tv_sec);
2835 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2836 max_ssids, entry->ssid);
2838 iter = g_sequence_iter_next(iter);
2841 g_sequence_free(latest_list);
2845 static void wifi_update_scanner_type(struct wifi_data *wifi,
2846 enum wifi_scanning_type new_type)
2850 if (!wifi || wifi->scanning_type == new_type)
2853 wifi->scanning_type = new_type;
2855 setup_autoscan(wifi);
2858 static int wifi_scan_simple(struct connman_device *device)
2860 struct wifi_data *wifi = connman_device_get_data(device);
2862 reset_autoscan(device);
2864 /* Distinguish between devices performing passive and active scanning */
2866 wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE);
2868 return throw_wifi_scan(device, scan_callback_hidden);
2871 static gboolean p2p_find_stop(gpointer data)
2873 struct connman_device *device = data;
2874 struct wifi_data *wifi = connman_device_get_data(device);
2879 wifi->p2p_find_timeout = 0;
2881 g_supplicant_interface_p2p_stop_find(wifi->interface);
2884 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2886 connman_device_unref(device);
2887 start_autoscan(device);
2892 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2895 struct connman_device *device = user_data;
2896 struct wifi_data *wifi = connman_device_get_data(device);
2898 DBG("result %d wifi %p", result, wifi);
2903 if (wifi->p2p_find_timeout) {
2904 g_source_remove(wifi->p2p_find_timeout);
2905 wifi->p2p_find_timeout = 0;
2911 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2912 p2p_find_stop, device);
2913 if (!wifi->p2p_find_timeout)
2918 p2p_find_stop(device);
2921 static int p2p_find(struct connman_device *device)
2923 struct wifi_data *wifi;
2928 if (!p2p_technology)
2931 wifi = connman_device_get_data(device);
2933 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2936 reset_autoscan(device);
2937 connman_device_ref(device);
2939 ret = g_supplicant_interface_p2p_find(wifi->interface,
2940 p2p_find_callback, device);
2942 connman_device_unref(device);
2943 start_autoscan(device);
2945 connman_device_set_scanning(device,
2946 CONNMAN_SERVICE_TYPE_P2P, true);
2952 #if defined TIZEN_EXT
2953 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2956 struct connman_device *device = user_data;
2957 struct wifi_data *wifi = connman_device_get_data(device);
2960 DBG("result %d wifi %p", result, wifi);
2962 if (wifi && wifi->scan_params) {
2963 g_supplicant_free_scan_params(wifi->scan_params);
2964 wifi->scan_params = NULL;
2967 scanning = connman_device_get_scanning(device,
2968 CONNMAN_SERVICE_TYPE_WIFI);
2970 connman_device_set_scanning(device,
2971 CONNMAN_SERVICE_TYPE_WIFI, false);
2972 connman_device_unref(device);
2976 static int wifi_specific_scan(enum connman_service_type type,
2977 struct connman_device *device, int scan_type,
2978 GSList *specific_scan_list, void *user_data)
2980 GSList *list = NULL;
2982 struct wifi_data *wifi = connman_device_get_data(device);
2983 GSupplicantScanParams *scan_params = NULL;
2984 struct scan_ssid *scan_ssid = NULL;
2993 if (wifi->p2p_device)
2996 if (type == CONNMAN_SERVICE_TYPE_P2P)
2997 return p2p_find(device);
2999 if (wifi->tethering)
3003 connman_device_get_scanning(device,
3004 CONNMAN_SERVICE_TYPE_WIFI);
3008 DBG("scan_type: %d", scan_type);
3009 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
3010 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3012 DBG("Failed to allocate memory.");
3016 for (list = specific_scan_list; list; list = list->next) {
3017 ssid = (char *)list->data;
3018 int ssid_len = strlen(ssid);
3020 scan_ssid = g_try_new0(struct scan_ssid, 1);
3022 DBG("Failed to allocate memory.");
3023 g_supplicant_free_scan_params(scan_params);
3027 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
3028 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
3029 scan_ssid->ssid_len = ssid_len;
3030 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3033 scan_params->num_ssids = count;
3035 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
3037 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3039 DBG("Failed to allocate memory.");
3043 guint num_freqs = g_slist_length(specific_scan_list);
3044 DBG("num_freqs: %d", num_freqs);
3046 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
3047 if (!scan_params->freqs) {
3048 DBG("Failed to allocate memory.");
3049 g_free(scan_params);
3054 for (list = specific_scan_list; list; list = list->next) {
3055 freq = (int)list->data;
3057 scan_params->freqs[count] = freq;
3058 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
3061 scan_params->num_freqs = count;
3063 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
3064 int freq_count, ap_count;
3065 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3067 DBG("Failed to allocate memory.");
3071 guint size = g_slist_length(specific_scan_list);
3073 scan_params->freqs = g_try_new0(uint16_t, size/2);
3074 if (!scan_params->freqs) {
3075 DBG("Failed to allocate memory.");
3076 g_free(scan_params);
3080 ap_count = freq_count = 0;
3081 for (list = specific_scan_list; list; list = list->next) {
3082 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
3083 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
3084 int ssid_len = strlen(ssid);
3086 scan_ssid = g_try_new0(struct scan_ssid, 1);
3088 DBG("Failed to allocate memory.");
3089 g_supplicant_free_scan_params(scan_params);
3093 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
3094 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
3095 scan_ssid->ssid_len = ssid_len;
3096 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3100 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
3101 scan_params->freqs[freq_count] = freq;
3102 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
3106 scan_params->num_ssids = ap_count;
3107 scan_params->num_freqs = freq_count;
3109 DBG("Invalid scan");
3113 reset_autoscan(device);
3114 connman_device_ref(device);
3116 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3117 specific_scan_callback, device);
3120 connman_device_set_scanning(device,
3121 CONNMAN_SERVICE_TYPE_WIFI, true);
3123 g_supplicant_free_scan_params(scan_params);
3124 connman_device_unref(device);
3130 static void wifi_mac_policy_callback(int result,
3131 unsigned int policy,
3134 struct connman_device *device = user_data;
3137 connman_device_mac_policy_notify(device, result, policy);
3139 connman_device_unref(device);
3142 int wifi_set_mac_policy(struct connman_device *device, unsigned int policy)
3144 struct wifi_data *wifi = connman_device_get_data(device);
3150 connman_device_ref(device);
3152 ret = g_supplicant_interface_set_mac_policy(wifi->interface,
3153 wifi_mac_policy_callback,
3156 connman_device_unref(device);
3161 static void wifi_preassoc_mac_policy_callback(int result,
3162 unsigned int policy,
3165 struct connman_device *device = user_data;
3168 connman_device_preassoc_mac_policy_notify(device, result, policy);
3170 connman_device_unref(device);
3173 int wifi_set_preassoc_mac_policy(struct connman_device *device, unsigned int policy)
3175 struct wifi_data *wifi = connman_device_get_data(device);
3181 connman_device_ref(device);
3183 ret = g_supplicant_interface_set_preassoc_mac_policy(wifi->interface,
3184 wifi_preassoc_mac_policy_callback,
3187 connman_device_unref(device);
3192 static void wifi_random_mac_lifetime_callback(int result,
3193 unsigned int lifetime,
3196 struct connman_device *device = user_data;
3199 connman_device_random_mac_lifetime_notify(device, result, lifetime);
3201 connman_device_unref(device);
3204 int wifi_set_random_mac_lifetime(struct connman_device *device, unsigned int lifetime)
3206 struct wifi_data *wifi = connman_device_get_data(device);
3212 connman_device_ref(device);
3214 ret = g_supplicant_interface_set_random_mac_lifetime(wifi->interface,
3215 wifi_random_mac_lifetime_callback,
3218 connman_device_unref(device);
3224 #if defined TIZEN_EXT_WIFI_MESH
3225 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
3228 struct connman_device *device = user_data;
3229 struct wifi_data *wifi = connman_device_get_data(device);
3232 DBG("result %d wifi %p", result, wifi);
3234 scanning = connman_device_get_scanning(device,
3235 CONNMAN_SERVICE_TYPE_MESH);
3237 connman_device_set_scanning(device,
3238 CONNMAN_SERVICE_TYPE_MESH, false);
3241 connman_device_unref(device);
3244 static int mesh_scan(struct connman_device *device)
3246 struct wifi_data *wifi;
3247 struct wifi_mesh_info *mesh_info;
3252 wifi = connman_device_get_data(device);
3254 if (!wifi || !wifi->mesh_interface)
3257 mesh_info = wifi->mesh_info;
3258 reset_autoscan(device);
3259 connman_device_ref(device);
3261 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
3262 mesh_scan_callback, device);
3264 connman_device_unref(device);
3266 connman_device_set_scanning(device,
3267 CONNMAN_SERVICE_TYPE_MESH, true);
3272 static void abort_scan_callback(int result, GSupplicantInterface *interface,
3275 struct connman_device *device = user_data;
3276 struct wifi_data *wifi = connman_device_get_data(device);
3278 DBG("result %d wifi %p", result, wifi);
3280 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
3283 static int mesh_abort_scan(enum connman_service_type type,
3284 struct connman_device *device)
3286 struct wifi_data *wifi = connman_device_get_data(device);
3287 struct wifi_mesh_info *mesh_info;
3291 if (!wifi || !wifi->mesh_interface)
3294 if (type != CONNMAN_SERVICE_TYPE_MESH)
3297 mesh_info = wifi->mesh_info;
3299 scanning = connman_device_get_scanning(device,
3300 CONNMAN_SERVICE_TYPE_MESH);
3304 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
3305 abort_scan_callback, device);
3310 static int mesh_specific_scan(enum connman_service_type type,
3311 struct connman_device *device, const char *ssid,
3312 unsigned int freq, void *user_data)
3314 struct wifi_data *wifi = connman_device_get_data(device);
3315 GSupplicantScanParams *scan_params = NULL;
3316 struct wifi_mesh_info *mesh_info;
3317 struct scan_ssid *scan_ssid;
3321 if (!wifi || !wifi->mesh_interface)
3324 if (type != CONNMAN_SERVICE_TYPE_MESH)
3327 if (wifi->p2p_device)
3330 mesh_info = wifi->mesh_info;
3332 scanning = connman_device_get_scanning(device,
3333 CONNMAN_SERVICE_TYPE_MESH);
3337 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3341 scan_ssid = g_try_new(struct scan_ssid, 1);
3343 g_free(scan_params);
3347 scan_ssid->ssid_len = strlen(ssid);
3348 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
3349 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3350 scan_params->num_ssids = 1;
3352 scan_params->freqs = g_try_new(uint16_t, 1);
3353 if (!scan_params->freqs) {
3354 g_slist_free_full(scan_params->ssids, g_free);
3355 g_free(scan_params);
3359 scan_params->freqs[0] = freq;
3360 scan_params->num_freqs = 1;
3362 reset_autoscan(device);
3363 connman_device_ref(device);
3365 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
3366 mesh_scan_callback, device);
3369 connman_device_set_scanning(device,
3370 CONNMAN_SERVICE_TYPE_MESH, true);
3372 g_supplicant_free_scan_params(scan_params);
3373 connman_device_unref(device);
3381 * Note that the hidden scan is only used when connecting to this specific
3382 * hidden AP first time. It is not used when system autoconnects to hidden AP.
3384 static int wifi_scan(struct connman_device *device,
3385 struct connman_device_scan_params *params)
3387 struct wifi_data *wifi = connman_device_get_data(device);
3388 GSupplicantScanParams *scan_params = NULL;
3389 struct scan_ssid *scan_ssid;
3390 struct hidden_params *hidden;
3392 int driver_max_ssids = 0;
3399 if (wifi->p2p_device)
3402 if (wifi->tethering)
3405 if (params->type == CONNMAN_SERVICE_TYPE_P2P)
3406 return p2p_find(device);
3408 #if defined TIZEN_EXT_WIFI_MESH
3409 if (params->type == CONNMAN_SERVICE_TYPE_MESH)
3410 return mesh_scan(device);
3413 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface,
3416 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
3418 if (!params->ssid || params->ssid_len == 0 || params->ssid_len > 32) {
3422 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
3424 DBG("max ssids %d", driver_max_ssids);
3425 if (driver_max_ssids == 0)
3426 return wifi_scan_simple(device);
3430 if (scanning && wifi->hidden && wifi->postpone_hidden)
3436 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3441 scan_ssid = g_try_new(struct scan_ssid, 1);
3443 g_free(scan_params);
3447 memcpy(scan_ssid->ssid, params->ssid, params->ssid_len);
3448 scan_ssid->ssid_len = params->ssid_len;
3449 scan_params->ssids = g_slist_prepend(scan_params->ssids,
3451 scan_params->num_ssids = 1;
3453 hidden = g_try_new0(struct hidden_params, 1);
3455 g_supplicant_free_scan_params(scan_params);
3460 hidden_free(wifi->hidden);
3461 wifi->hidden = NULL;
3464 memcpy(hidden->ssid, params->ssid, params->ssid_len);
3465 hidden->ssid_len = params->ssid_len;
3466 hidden->identity = g_strdup(params->identity);
3467 hidden->passphrase = g_strdup(params->passphrase);
3468 hidden->security = g_strdup(params->security);
3469 hidden->user_data = params->user_data;
3470 wifi->hidden = hidden;
3473 /* Let's keep this active scan for later,
3474 * when current scan will be over. */
3475 wifi->postpone_hidden = TRUE;
3476 hidden->scan_params = scan_params;
3480 } else if (wifi->connected) {
3481 g_supplicant_free_scan_params(scan_params);
3482 return wifi_scan_simple(device);
3483 } else if (!params->force_full_scan) {
3484 ret = get_latest_connections(driver_max_ssids, scan_params);
3486 g_supplicant_free_scan_params(scan_params);
3487 return wifi_scan_simple(device);
3491 /* Distinguish between devices performing passive and active scanning */
3492 wifi_update_scanner_type(wifi, WIFI_SCANNING_ACTIVE);
3494 connman_device_ref(device);
3496 reset_autoscan(device);
3497 #if defined TIZEN_EXT
3499 * When doing a full scan, stored hidden networks also need to be scanned
3500 * so that we can autoconnect to them.
3502 if (params->force_full_scan)
3503 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3504 scan_callback_hidden, device);
3507 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3508 scan_callback, device);
3510 connman_device_set_scanning(device,
3511 CONNMAN_SERVICE_TYPE_WIFI, true);
3512 #if defined TIZEN_EXT
3514 * To allow the Full Scan after ssid based scan, set the flag here
3515 * It is required because Tizen does not use the ConnMan specific
3516 * backgroung Scan feature.Tizen has added the BG Scan feature in
3517 * net-config. To sync with up ConnMan, we need to issue the Full Scan
3518 * after SSID specific scan.
3520 if (!params->force_full_scan && !do_hidden)
3521 wifi->allow_full_scan = TRUE;
3524 g_supplicant_free_scan_params(scan_params);
3525 connman_device_unref(device);
3528 hidden_free(wifi->hidden);
3529 wifi->hidden = NULL;
3536 static void wifi_stop_scan(enum connman_service_type type,
3537 struct connman_device *device)
3539 struct wifi_data *wifi = connman_device_get_data(device);
3541 DBG("device %p wifi %p", device, wifi);
3546 if (type == CONNMAN_SERVICE_TYPE_P2P) {
3547 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
3548 g_source_remove(wifi->p2p_find_timeout);
3549 p2p_find_stop(device);
3554 static void wifi_regdom_callback(int result,
3558 struct connman_device *device = user_data;
3560 connman_device_regdom_notify(device, result, alpha2);
3562 connman_device_unref(device);
3565 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3567 struct wifi_data *wifi = connman_device_get_data(device);
3573 connman_device_ref(device);
3575 ret = g_supplicant_interface_set_country(wifi->interface,
3576 wifi_regdom_callback,
3579 connman_device_unref(device);
3584 static struct connman_device_driver wifi_ng_driver = {
3586 .type = CONNMAN_DEVICE_TYPE_WIFI,
3587 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3588 .probe = wifi_probe,
3589 .remove = wifi_remove,
3590 .enable = wifi_enable,
3591 .disable = wifi_disable,
3593 .stop_scan = wifi_stop_scan,
3594 .set_regdom = wifi_set_regdom,
3595 #if defined TIZEN_EXT
3596 .specific_scan = wifi_specific_scan,
3597 .set_mac_policy = wifi_set_mac_policy,
3598 .set_preassoc_mac_policy = wifi_set_preassoc_mac_policy,
3599 .set_random_mac_lifetime = wifi_set_random_mac_lifetime,
3601 #if defined TIZEN_EXT_WIFI_MESH
3602 .abort_scan = mesh_abort_scan,
3603 .mesh_specific_scan = mesh_specific_scan,
3607 static void system_ready(void)
3611 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3612 connman_error("Failed to register WiFi driver");
3615 static void system_killed(void)
3619 connman_device_driver_unregister(&wifi_ng_driver);
3622 static int network_probe(struct connman_network *network)
3624 #if defined TIZEN_EXT
3625 if (!simplified_log)
3627 DBG("network %p", network);
3632 static void network_remove(struct connman_network *network)
3634 struct connman_device *device = connman_network_get_device(network);
3635 struct wifi_data *wifi;
3637 DBG("network %p", network);
3639 wifi = connman_device_get_data(device);
3643 if (wifi->network != network)
3646 wifi->network = NULL;
3648 #if defined TIZEN_EXT
3649 wifi->disconnecting = false;
3651 if (wifi->pending_network == network)
3652 wifi->pending_network = NULL;
3654 if (wifi->scan_pending_network == network)
3655 wifi->scan_pending_network = NULL;
3659 static void connect_callback(int result, GSupplicantInterface *interface,
3662 #if defined TIZEN_EXT
3664 struct wifi_data *wifi;
3666 struct connman_network *network = user_data;
3668 DBG("network %p result %d", network, result);
3670 #if defined TIZEN_EXT
3671 const char *ifname = g_supplicant_interface_get_ifname(interface);
3672 set_connman_bssid(RESET_BSSID, NULL, ifname);
3674 for (list = iface_list; list; list = list->next) {
3677 if (wifi && wifi->network == network)
3681 /* wifi_data may be invalid because wifi is already disabled */
3685 if (connman_network_get_bool(network, "WiFi.Roaming")) {
3687 connman_network_set_bool(network, "WiFi.Roaming", false);
3688 connman_network_set_string(network,
3689 "WiFi.RoamingCurBSSID", NULL);
3691 char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
3692 char *bssid_str = bssid_buff;
3693 unsigned char *bssid;
3694 const char *cur_bssid;
3696 bssid = g_supplicant_interface_get_add_network_bssid(interface);
3698 connman_network_set_bool(network, "WiFi.Roaming", false);
3699 connman_network_set_string(network,
3700 "WiFi.RoamingCurBSSID", NULL);
3704 MACSTR, MAC2STR(bssid));
3706 connman_network_set_string(network,
3707 "WiFi.RoamingDstBSSID", bssid_str);
3709 cur_bssid = connman_network_get_string(network,
3710 "WiFi.RoamingCurBSSID");
3712 __connman_technology_notify_roaming_state(ifname,
3713 "started", cur_bssid, bssid_str);
3718 if (result == -ENOKEY) {
3719 connman_network_set_error(network,
3720 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3721 } else if (result < 0) {
3722 connman_network_set_error(network,
3723 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3726 connman_network_unref(network);
3729 static GSupplicantSecurity network_security(const char *security)
3731 if (g_str_equal(security, "none"))
3732 return G_SUPPLICANT_SECURITY_NONE;
3733 else if (g_str_equal(security, "wep"))
3734 return G_SUPPLICANT_SECURITY_WEP;
3735 else if (g_str_equal(security, "psk"))
3736 return G_SUPPLICANT_SECURITY_PSK;
3737 else if (g_str_equal(security, "wpa"))
3738 return G_SUPPLICANT_SECURITY_PSK;
3739 else if (g_str_equal(security, "rsn"))
3740 return G_SUPPLICANT_SECURITY_PSK;
3741 else if (g_str_equal(security, "ieee8021x"))
3742 return G_SUPPLICANT_SECURITY_IEEE8021X;
3743 #if defined TIZEN_EXT
3744 else if (g_str_equal(security, "ft_psk") == TRUE)
3745 return G_SUPPLICANT_SECURITY_FT_PSK;
3746 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3747 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3748 else if (g_str_equal(security, "sae"))
3749 return G_SUPPLICANT_SECURITY_SAE;
3750 else if (g_str_equal(security, "owe"))
3751 return G_SUPPLICANT_SECURITY_OWE;
3752 else if (g_str_equal(security, "dpp"))
3753 return G_SUPPLICANT_SECURITY_DPP;
3756 return G_SUPPLICANT_SECURITY_UNKNOWN;
3759 #if defined TIZEN_EXT
3760 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3762 if (security == NULL)
3763 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3765 if (g_str_equal(security, "FT") == TRUE)
3766 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3767 else if (g_str_equal(security, "CCKM") == TRUE)
3768 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3770 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3774 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3776 const char *security;
3777 #if defined TIZEN_EXT
3778 const void *ssid_data;
3781 memset(ssid, 0, sizeof(*ssid));
3782 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3783 #if defined TIZEN_EXT
3784 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3786 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3791 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3793 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3796 ssid->scan_ssid = 1;
3797 security = connman_network_get_string(network, "WiFi.Security");
3798 ssid->security = network_security(security);
3799 #if defined TIZEN_EXT
3800 ssid->ieee80211w = 1;
3802 ssid->passphrase = connman_network_get_string(network,
3805 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3808 * If our private key password is unset,
3809 * we use the supplied passphrase. That is needed
3810 * for PEAP where 2 passphrases (identity and client
3811 * cert may have to be provided.
3813 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3814 connman_network_set_string(network,
3815 "WiFi.PrivateKeyPassphrase",
3817 /* We must have an identity for both PEAP and TLS */
3818 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3820 /* Use agent provided identity as a fallback */
3821 if (!ssid->identity || strlen(ssid->identity) == 0)
3822 ssid->identity = connman_network_get_string(network,
3823 "WiFi.AgentIdentity");
3825 ssid->anonymous_identity = connman_network_get_string(network,
3826 "WiFi.AnonymousIdentity");
3827 ssid->ca_cert_path = connman_network_get_string(network,
3829 ssid->subject_match = connman_network_get_string(network,
3830 "WiFi.SubjectMatch");
3831 ssid->altsubject_match = connman_network_get_string(network,
3832 "WiFi.AltSubjectMatch");
3833 ssid->domain_suffix_match = connman_network_get_string(network,
3834 "WiFi.DomainSuffixMatch");
3835 ssid->domain_match = connman_network_get_string(network,
3836 "WiFi.DomainMatch");
3837 ssid->client_cert_path = connman_network_get_string(network,
3838 "WiFi.ClientCertFile");
3839 ssid->private_key_path = connman_network_get_string(network,
3840 "WiFi.PrivateKeyFile");
3841 ssid->private_key_passphrase = connman_network_get_string(network,
3842 "WiFi.PrivateKeyPassphrase");
3843 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3845 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3846 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3847 #if defined TIZEN_EXT
3848 ssid->connector = connman_network_get_string(network,
3850 ssid->c_sign_key = connman_network_get_string(network,
3852 ssid->net_access_key = connman_network_get_string(network,
3853 "WiFi.NetAccessKey");
3856 #if defined TIZEN_EXT
3857 const char *ifname = connman_device_get_string(
3858 connman_network_get_device(network), "Interface");
3859 if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) {
3860 ssid->bssid_for_connect_len = 6;
3861 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect, ifname);
3862 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3863 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3864 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3865 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3867 ssid->freq = connman_network_get_frequency(network);
3870 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3871 if (bssid_list && g_slist_length(bssid_list) > 1) {
3873 /* If there are more than one bssid,
3874 * the user-specified bssid is tried only once at the beginning.
3875 * After that, the bssids in the list are tried in order.
3877 if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) {
3878 set_connman_bssid(RESET_BSSID, NULL, ifname);
3883 char buff[MAC_ADDRESS_LENGTH];
3884 for (list = bssid_list; list; list = list->next) {
3885 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3887 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3888 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3889 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3890 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3892 gchar *curr_bssid = g_strdup((const gchar *)buff);
3894 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3895 DBG("bssid match, try next bssid");
3899 g_hash_table_add(failed_bssids, curr_bssid);
3901 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3902 ssid->bssid = buff_bssid;
3903 ssid->freq = (unsigned int)bssids->frequency;
3909 ssid->bssid = connman_network_get_bssid(network);
3910 g_hash_table_remove_all(failed_bssids);
3913 ssid->bssid = connman_network_get_bssid(network);
3916 ssid->eap_keymgmt = network_eap_keymgmt(
3917 connman_network_get_string(network, "WiFi.KeymgmtType"));
3918 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3920 if(g_strcmp0(ssid->eap, "fast") == 0)
3921 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3923 ssid->keymgmt = connman_network_get_keymgmt(network);
3926 if (connman_setting_get_bool("BackgroundScanning"))
3927 ssid->bgscan = BGSCAN_DEFAULT;
3930 static int network_connect(struct connman_network *network)
3932 struct connman_device *device = connman_network_get_device(network);
3933 struct wifi_data *wifi;
3934 GSupplicantInterface *interface;
3935 GSupplicantSSID *ssid;
3937 DBG("network %p", network);
3942 wifi = connman_device_get_data(device);
3946 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3950 interface = wifi->interface;
3952 ssid_init(ssid, network);
3954 if (wifi->disconnecting) {
3955 wifi->pending_network = network;
3956 #if defined TIZEN_EXT
3961 wifi->network = connman_network_ref(network);
3963 #if defined TIZEN_EXT
3964 wifi->scan_pending_network = NULL;
3967 return g_supplicant_interface_connect(interface, ssid,
3968 connect_callback, network);
3971 return -EINPROGRESS;
3974 static void disconnect_callback(int result, GSupplicantInterface *interface,
3977 struct disconnect_data *dd = user_data;
3978 struct connman_network *network = dd->network;
3979 #if defined TIZEN_EXT
3981 struct wifi_data *wifi;
3984 DBG("network %p result %d", network, result);
3986 for (list = iface_list; list; list = list->next) {
3989 if (wifi->network == NULL && wifi->disconnecting == true)
3990 wifi->disconnecting = false;
3992 if (wifi->network == network)
3996 /* wifi_data may be invalid because wifi is already disabled */
4001 struct wifi_data *wifi = dd->wifi;
4005 DBG("result %d supplicant interface %p wifi %p networks: current %p "
4006 "pending %p disconnected %p", result, interface, wifi,
4007 wifi->network, wifi->pending_network, network);
4009 if (result == -ECONNABORTED) {
4010 DBG("wifi interface no longer available");
4014 #if defined TIZEN_EXT
4015 if (wifi->network &&
4016 (wifi->network != wifi->pending_network ||
4017 connman_network_get_bool(wifi->network, "WiFi.Roaming")))
4019 if (g_slist_find(wifi->networks, network))
4021 connman_network_set_connected(network, false);
4023 wifi->disconnecting = false;
4025 if (network != wifi->network) {
4026 if (network == wifi->pending_network)
4027 wifi->pending_network = NULL;
4028 DBG("current wifi network has changed since disconnection");
4032 wifi->network = NULL;
4034 wifi->connected = false;
4036 if (wifi->pending_network) {
4037 network_connect(wifi->pending_network);
4038 wifi->pending_network = NULL;
4041 start_autoscan(wifi->device);
4044 static int network_disconnect(struct connman_network *network)
4046 struct connman_device *device = connman_network_get_device(network);
4047 struct disconnect_data *dd;
4048 struct wifi_data *wifi;
4050 #if defined TIZEN_EXT
4051 struct connman_service *service;
4054 DBG("network %p", network);
4056 wifi = connman_device_get_data(device);
4057 if (!wifi || !wifi->interface)
4060 #if defined TIZEN_EXT
4061 if (connman_network_get_associating(network) == true) {
4062 connman_network_clear_associating(network);
4063 connman_network_set_bool(network, "WiFi.UseWPS", false);
4065 service = connman_service_lookup_from_network(network);
4067 if (service != NULL &&
4068 (__connman_service_is_connected_state(service,
4069 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
4070 __connman_service_is_connected_state(service,
4071 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
4072 (connman_service_get_favorite(service) == false))
4073 __connman_service_set_passphrase(service, NULL);
4076 if (wifi->pending_network == network)
4077 wifi->pending_network = NULL;
4079 if (wifi->scan_pending_network == network)
4080 wifi->scan_pending_network = NULL;
4083 connman_network_set_associating(network, false);
4085 if (wifi->disconnecting)
4088 wifi->disconnecting = true;
4090 dd = g_malloc0(sizeof(*dd));
4092 dd->network = network;
4094 err = g_supplicant_interface_disconnect(wifi->interface,
4095 disconnect_callback, dd);
4097 wifi->disconnecting = false;
4104 #if defined TIZEN_EXT
4105 static void set_connection_mode(struct connman_network *network,
4108 ieee80211_modes_e phy_mode;
4109 connection_mode_e conn_mode;
4111 phy_mode = connman_network_get_phy_mode(network);
4113 case IEEE80211_MODE_B:
4114 if (linkspeed > 0 && linkspeed <= 11)
4115 conn_mode = CONNECTION_MODE_IEEE80211B;
4117 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4120 case IEEE80211_MODE_BG:
4121 if (linkspeed > 0 && linkspeed <= 11)
4122 conn_mode = CONNECTION_MODE_IEEE80211B;
4123 else if (linkspeed > 11 && linkspeed <= 54)
4124 conn_mode = CONNECTION_MODE_IEEE80211G;
4126 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4129 case IEEE80211_MODE_BGN:
4130 if (linkspeed > 0 && linkspeed <= 11)
4131 conn_mode = CONNECTION_MODE_IEEE80211B;
4132 else if (linkspeed > 11 && linkspeed <= 54)
4133 conn_mode = CONNECTION_MODE_IEEE80211G;
4134 else if (linkspeed > 54 && linkspeed <= 450)
4135 conn_mode = CONNECTION_MODE_IEEE80211N;
4137 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4140 case IEEE80211_MODE_A:
4141 if (linkspeed > 0 && linkspeed <= 54)
4142 conn_mode = CONNECTION_MODE_IEEE80211A;
4144 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4147 case IEEE80211_MODE_AN:
4148 if (linkspeed > 0 && linkspeed <= 54)
4149 conn_mode = CONNECTION_MODE_IEEE80211A;
4150 else if (linkspeed > 54 && linkspeed <= 450)
4151 conn_mode = CONNECTION_MODE_IEEE80211N;
4153 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4156 case IEEE80211_MODE_ANAC:
4157 if (linkspeed > 0 && linkspeed <= 54)
4158 conn_mode = CONNECTION_MODE_IEEE80211A;
4159 else if (linkspeed > 54 && linkspeed <= 450)
4160 conn_mode = CONNECTION_MODE_IEEE80211N;
4161 else if (linkspeed > 450 && linkspeed <= 1300)
4162 conn_mode = CONNECTION_MODE_IEEE80211AC;
4164 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4168 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
4172 DBG("connection mode(%d)", conn_mode);
4173 connman_network_set_connection_mode(network, conn_mode);
4176 static void signalpoll_callback(int result, int maxspeed, int strength,
4177 int snr, void *user_data)
4179 char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
4180 char *bssid_str = bssid_buff;
4181 unsigned char *bssid;
4182 struct timespec curr_time = {0};
4183 __time_t roam_scan_time;
4184 const char *interface = NULL;
4185 struct connman_device *device;
4186 struct connman_network *network = user_data;
4187 uint16_t freq = connman_network_get_frequency(network);
4190 DBG("Failed to get maxspeed from signalpoll !");
4191 connman_network_unref(network);
4199 DBG("freq = %u, maxspeed = %d, strength = %d, snr = %d", freq, maxspeed, strength, snr);
4201 connman_network_set_strength(network, (uint8_t)strength);
4202 connman_network_set_snr(network, snr);
4203 connman_network_set_maxspeed(network, maxspeed);
4204 set_connection_mode(network, maxspeed);
4206 clock_gettime(CLOCK_MONOTONIC, &curr_time);
4207 roam_scan_time = connman_network_get_roam_scan_time(network);
4208 if (curr_time.tv_sec <= roam_scan_time + ROAM_SCAN_INTERVAL)
4211 if (need_bss_transition(freq, snr, strength)) {
4212 device = connman_network_get_device(network);
4216 interface = connman_device_get_string(device, "Interface");
4217 bssid = connman_network_get_bssid(network);
4218 snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
4219 __connman_technology_notify_roaming_state(interface, "required", bssid_str, NULL);
4221 if (connman_setting_get_bool("WifiRoamingScan") == false)
4224 throw_wifi_scan(device, scan_callback);
4225 connman_network_set_roam_scan_time(network, curr_time.tv_sec);
4229 connman_network_unref(network);
4232 static int network_signalpoll(struct wifi_data *wifi)
4234 GSupplicantInterface *interface;
4235 struct connman_network *network;
4237 if (!wifi || !wifi->network)
4240 wifi->network = connman_network_ref(wifi->network);
4242 interface = wifi->interface;
4243 network = wifi->network;
4245 DBG("network %p", network);
4247 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
4250 static gboolean autosignalpoll_timeout(gpointer data)
4252 struct wifi_data *wifi = data;
4254 if (!wifi || !wifi->automaxspeed_timeout) {
4255 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
4259 int ret = network_signalpoll(wifi);
4261 DBG("Fail to get max speed !!");
4262 wifi->automaxspeed_timeout = 0;
4265 connman_network_unref(wifi->network);
4274 static struct connman_network_driver network_driver = {
4276 .type = CONNMAN_NETWORK_TYPE_WIFI,
4277 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
4278 .probe = network_probe,
4279 .remove = network_remove,
4280 .connect = network_connect,
4281 .disconnect = network_disconnect,
4284 static void interface_added(GSupplicantInterface *interface)
4286 const char *ifname = g_supplicant_interface_get_ifname(interface);
4287 const char *driver = g_supplicant_interface_get_driver(interface);
4288 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4290 * Note: If supplicant interface's driver is wired then skip it,
4291 * because it meanti only for ethernet not Wi-Fi.
4293 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
4295 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4297 #if defined TIZEN_EXT
4298 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
4301 struct wifi_data *wifi;
4303 wifi = g_supplicant_interface_get_data(interface);
4305 wifi = get_pending_wifi_data(ifname);
4309 wifi->interface = interface;
4310 g_supplicant_interface_set_data(interface, wifi);
4311 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
4312 wifi->p2p_device = true;
4315 DBG("ifname %s driver %s wifi %p tethering %d",
4316 ifname, driver, wifi, wifi->tethering);
4318 if (!wifi->device) {
4319 connman_error("WiFi device not set");
4323 connman_device_set_powered(wifi->device, true);
4324 #if defined TIZEN_EXT
4325 connman_device_set_wifi_5ghz_supported(wifi->device, is_5_0_ghz_supported);
4326 /* Max number of SSIDs supported by wlan chipset that can be scanned */
4327 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
4328 connman_device_set_max_scan_ssids(wifi->device, max_scan_ssids);
4332 static bool is_idle(struct wifi_data *wifi)
4334 DBG("state %d", wifi->state);
4336 switch (wifi->state) {
4337 case G_SUPPLICANT_STATE_UNKNOWN:
4338 case G_SUPPLICANT_STATE_DISABLED:
4339 case G_SUPPLICANT_STATE_DISCONNECTED:
4340 case G_SUPPLICANT_STATE_INACTIVE:
4341 case G_SUPPLICANT_STATE_SCANNING:
4344 case G_SUPPLICANT_STATE_AUTHENTICATING:
4345 case G_SUPPLICANT_STATE_ASSOCIATING:
4346 case G_SUPPLICANT_STATE_ASSOCIATED:
4347 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4348 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4349 case G_SUPPLICANT_STATE_COMPLETED:
4356 static bool is_idle_wps(GSupplicantInterface *interface,
4357 struct wifi_data *wifi)
4359 /* First, let's check if WPS processing did not went wrong */
4360 if (g_supplicant_interface_get_wps_state(interface) ==
4361 G_SUPPLICANT_WPS_STATE_FAIL)
4364 /* Unlike normal connection, being associated while processing wps
4365 * actually means that we are idling. */
4366 switch (wifi->state) {
4367 case G_SUPPLICANT_STATE_UNKNOWN:
4368 case G_SUPPLICANT_STATE_DISABLED:
4369 case G_SUPPLICANT_STATE_DISCONNECTED:
4370 case G_SUPPLICANT_STATE_INACTIVE:
4371 case G_SUPPLICANT_STATE_SCANNING:
4372 case G_SUPPLICANT_STATE_ASSOCIATED:
4374 case G_SUPPLICANT_STATE_AUTHENTICATING:
4375 case G_SUPPLICANT_STATE_ASSOCIATING:
4376 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4377 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4378 case G_SUPPLICANT_STATE_COMPLETED:
4385 static bool handle_wps_completion(GSupplicantInterface *interface,
4386 struct connman_network *network,
4387 struct connman_device *device,
4388 struct wifi_data *wifi)
4392 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4394 const unsigned char *ssid, *wps_ssid;
4395 unsigned int ssid_len, wps_ssid_len;
4396 struct disconnect_data *dd;
4397 const char *wps_key;
4399 /* Checking if we got associated with requested
4401 ssid = connman_network_get_blob(network, "WiFi.SSID",
4404 wps_ssid = g_supplicant_interface_get_wps_ssid(
4405 interface, &wps_ssid_len);
4407 if (!wps_ssid || wps_ssid_len != ssid_len ||
4408 memcmp(ssid, wps_ssid, ssid_len) != 0) {
4409 dd = g_malloc0(sizeof(*dd));
4411 dd->network = network;
4413 connman_network_set_associating(network, false);
4414 g_supplicant_interface_disconnect(wifi->interface,
4415 disconnect_callback, dd);
4416 #if defined TIZEN_EXT
4417 connman_network_set_bool(network, "WiFi.UseWPS", false);
4418 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4423 wps_key = g_supplicant_interface_get_wps_key(interface);
4424 #if defined TIZEN_EXT
4425 /* Check the passphrase and encrypt it
4428 gchar *passphrase = g_strdup(wps_key);
4430 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4432 if (check_passphrase_ext(network, passphrase) < 0) {
4433 DBG("[WPS] Invalid passphrase");
4438 ret = send_encryption_request(passphrase, network);
4443 DBG("[WPS] Encryption request succeeded");
4445 DBG("[WPS] Encryption request failed %d", ret);
4448 connman_network_set_string(network, "WiFi.Passphrase",
4451 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4458 static bool handle_assoc_status_code(GSupplicantInterface *interface,
4459 struct wifi_data *wifi)
4461 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
4462 #if defined TIZEN_EXT
4463 wifi->assoc_code > 0 &&
4465 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
4467 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
4468 wifi->load_shaping_retries ++;
4471 wifi->load_shaping_retries = 0;
4475 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
4476 struct connman_network *network,
4477 struct wifi_data *wifi)
4479 struct connman_service *service;
4481 #if defined TIZEN_EXT
4482 const char *security;
4483 if (wifi->connected)
4486 security = connman_network_get_string(network, "WiFi.Security");
4488 if (security && g_str_equal(security, "ieee8021x") == true &&
4489 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4491 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4496 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4499 if ((wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) &&
4500 !((wifi->state == G_SUPPLICANT_STATE_ASSOCIATING) &&
4501 (wifi->assoc_code == ASSOC_STATUS_AUTH_TIMEOUT)))
4504 if (wifi->connected)
4508 service = connman_service_lookup_from_network(network);
4514 if (connman_service_get_favorite(service)) {
4515 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
4520 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4525 #if defined TIZEN_EXT
4526 static bool handle_wifi_assoc_retry(struct connman_network *network,
4527 struct wifi_data *wifi)
4529 const char *security;
4531 if (!wifi->network || wifi->connected || wifi->disconnecting ||
4532 connman_network_get_connecting(network) != true) {
4533 wifi->assoc_retry_count = 0;
4537 if (wifi->state != G_SUPPLICANT_STATE_AUTHENTICATING &&
4538 wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
4539 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
4540 wifi->assoc_retry_count = 0;
4544 security = connman_network_get_string(network, "WiFi.Security");
4545 if (security && g_str_equal(security, "ieee8021x") == true &&
4546 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4547 wifi->assoc_retry_count = 0;
4551 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
4552 wifi->assoc_retry_count = 0;
4554 /* Honestly it's not an invalid-key error,
4555 * however QA team recommends that the invalid-key error
4556 * might be better to display for user experience.
4558 switch (wifi->state) {
4559 case G_SUPPLICANT_STATE_AUTHENTICATING:
4560 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL);
4562 case G_SUPPLICANT_STATE_ASSOCIATED:
4563 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4566 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
4577 static void interface_state(GSupplicantInterface *interface)
4579 struct connman_network *network;
4580 struct connman_device *device;
4581 struct wifi_data *wifi;
4582 GSupplicantState state = g_supplicant_interface_get_state(interface);
4583 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4585 * Note: If supplicant interface's driver is wired then skip it,
4586 * because it meanti only for ethernet not Wi-Fi.
4588 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
4590 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4595 wifi = g_supplicant_interface_get_data(interface);
4597 DBG("wifi %p interface state %d", wifi, state);
4602 device = wifi->device;
4606 if (state == G_SUPPLICANT_STATE_COMPLETED) {
4607 if (wifi->tethering_param) {
4608 g_free(wifi->tethering_param->ssid);
4609 g_free(wifi->tethering_param);
4610 wifi->tethering_param = NULL;
4613 if (wifi->tethering)
4614 stop_autoscan(device);
4617 if (g_supplicant_interface_get_ready(interface) &&
4618 !wifi->interface_ready) {
4619 wifi->interface_ready = true;
4620 finalize_interface_creation(wifi);
4623 network = wifi->network;
4628 case G_SUPPLICANT_STATE_SCANNING:
4629 #if defined TIZEN_EXT
4630 if (wifi->automaxspeed_timeout != 0) {
4631 g_source_remove(wifi->automaxspeed_timeout);
4632 wifi->automaxspeed_timeout = 0;
4633 DBG("Remove signalpoll timer!!");
4636 if (wifi->connected)
4637 connman_network_set_connected(network, false);
4641 case G_SUPPLICANT_STATE_AUTHENTICATING:
4642 case G_SUPPLICANT_STATE_ASSOCIATING:
4643 #if defined TIZEN_EXT
4644 reset_autoscan(device);
4646 stop_autoscan(device);
4649 if (!wifi->connected)
4650 connman_network_set_associating(network, true);
4654 case G_SUPPLICANT_STATE_COMPLETED:
4655 #if defined TIZEN_EXT
4656 /* though it should be already reset: */
4657 reset_autoscan(device);
4659 wifi->assoc_retry_count = 0;
4661 wifi->scan_pending_network = NULL;
4663 /* should be cleared scanning flag */
4664 bool scanning = connman_device_get_scanning(device,
4665 CONNMAN_SERVICE_TYPE_WIFI);
4667 connman_device_set_scanning(device,
4668 CONNMAN_SERVICE_TYPE_WIFI, false);
4669 connman_device_unref(device);
4672 if (!wifi->automaxspeed_timeout) {
4673 DBG("Going to start signalpoll timer!!");
4674 int ret = network_signalpoll(wifi);
4676 DBG("Fail to get max speed !!");
4678 wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
4681 g_hash_table_remove_all(failed_bssids);
4683 /* though it should be already stopped: */
4684 stop_autoscan(device);
4687 if (!handle_wps_completion(interface, network, device, wifi))
4690 connman_network_set_connected(network, true);
4692 wifi->disconnect_code = 0;
4693 wifi->assoc_code = 0;
4694 wifi->load_shaping_retries = 0;
4697 case G_SUPPLICANT_STATE_DISCONNECTED:
4698 #if defined TIZEN_EXT
4699 connman_network_set_strength(network, 0);
4700 connman_network_set_maxspeed(network, 0);
4702 if (wifi->automaxspeed_timeout != 0) {
4703 g_source_remove(wifi->automaxspeed_timeout);
4704 wifi->automaxspeed_timeout = 0;
4705 DBG("Remove signalpoll timer!!");
4709 * If we're in one of the idle modes, we have
4710 * not started association yet and thus setting
4711 * those ones to FALSE could cancel an association
4714 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4716 if (is_idle_wps(interface, wifi))
4722 #if defined TIZEN_EXT
4723 if (handle_assoc_status_code(interface, wifi)) {
4724 const char *group = connman_network_get_group(network);
4725 GSupplicantNetwork *supplicant_network;
4726 GSList *bssid_list = NULL;
4727 guint bssid_length = 0;
4730 supplicant_network = g_supplicant_interface_get_network(interface, group);
4732 connman_network_set_assoc_reject_table(network,
4733 g_supplicant_network_get_assoc_reject_table(supplicant_network));
4735 g_supplicant_network_update_assoc_reject(interface, supplicant_network);
4738 bssid_list = (GSList *)connman_network_get_bssid_list(network);
4740 bssid_length = g_slist_length(bssid_list);
4742 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4743 network_connect(network);
4747 wifi->load_shaping_retries = 0;
4750 g_hash_table_remove_all(failed_bssids);
4752 if (handle_assoc_status_code(interface, wifi))
4756 /* If previous state was 4way-handshake, then
4757 * it's either: psk was incorrect and thus we retry
4758 * or if we reach the maximum retries we declare the
4760 if (handle_4way_handshake_failure(interface,
4764 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4765 switch (wifi->disconnect_code) {
4766 #if defined TIZEN_EXT
4767 case 1: /* Unspecified reason */
4768 /* Let's assume it's because we got blocked */
4770 case 6: /* Class 2 frame received from nonauthenticated STA */
4771 connman_network_set_error(network,
4772 CONNMAN_NETWORK_ERROR_BLOCKED);
4779 #if defined TIZEN_EXT
4780 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4781 * Retry association until its retry count is expired */
4782 if (handle_wifi_assoc_retry(network, wifi) == true) {
4783 throw_wifi_scan(wifi->device, scan_callback);
4784 wifi->scan_pending_network = wifi->network;
4788 if(wifi->disconnect_code > 0){
4789 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4790 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4794 if (network != wifi->pending_network) {
4795 connman_network_set_connected(network, false);
4796 connman_network_set_associating(network, false);
4798 wifi->disconnecting = false;
4800 start_autoscan(device);
4804 case G_SUPPLICANT_STATE_INACTIVE:
4805 #if defined TIZEN_EXT
4806 if (handle_wps_completion(interface, network, device, wifi) == false)
4809 connman_network_set_associating(network, false);
4810 start_autoscan(device);
4814 case G_SUPPLICANT_STATE_UNKNOWN:
4815 case G_SUPPLICANT_STATE_DISABLED:
4816 case G_SUPPLICANT_STATE_ASSOCIATED:
4817 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4818 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4822 old_connected = wifi->connected;
4823 wifi->state = state;
4825 /* Saving wpa_s state policy:
4826 * If connected and if the state changes are roaming related:
4827 * --> We stay connected
4829 * --> We are connected
4831 * --> We are not connected
4834 case G_SUPPLICANT_STATE_AUTHENTICATING:
4835 case G_SUPPLICANT_STATE_ASSOCIATING:
4836 case G_SUPPLICANT_STATE_ASSOCIATED:
4837 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4838 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4839 if (wifi->connected)
4840 connman_warn("Probably roaming right now!"
4841 " Staying connected...");
4843 case G_SUPPLICANT_STATE_SCANNING:
4844 wifi->connected = false;
4847 start_autoscan(device);
4849 case G_SUPPLICANT_STATE_COMPLETED:
4850 wifi->connected = true;
4853 wifi->connected = false;
4860 static void interface_removed(GSupplicantInterface *interface)
4862 const char *ifname = g_supplicant_interface_get_ifname(interface);
4863 struct wifi_data *wifi;
4864 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4866 * Note: If supplicant interface's driver is wired then skip it,
4867 * because it meanti only for ethernet not Wi-Fi.
4869 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
4871 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4874 DBG("ifname %s", ifname);
4876 wifi = g_supplicant_interface_get_data(interface);
4878 #if defined TIZEN_EXT_WIFI_MESH
4879 if (wifi && wifi->mesh_interface) {
4880 DBG("Notify mesh interface remove");
4881 connman_mesh_notify_interface_remove(true);
4882 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4883 g_free(mesh_info->parent_ifname);
4884 g_free(mesh_info->ifname);
4885 g_free(mesh_info->identifier);
4887 wifi->mesh_interface = false;
4888 wifi->mesh_info = NULL;
4894 wifi->interface = NULL;
4896 if (wifi && wifi->tethering)
4899 if (!wifi || !wifi->device) {
4900 DBG("wifi interface already removed");
4904 connman_device_set_powered(wifi->device, false);
4906 check_p2p_technology();
4907 #if defined TIZEN_EXT_WIFI_MESH
4908 check_mesh_technology();
4912 static void set_device_type(const char *type, char dev_type[17])
4914 const char *oui = "0050F204";
4915 const char *category = "0001";
4916 const char *sub_category = "0000";
4918 if (!g_strcmp0(type, "handset")) {
4920 sub_category = "0005";
4921 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4922 sub_category = "0001";
4923 else if (!g_strcmp0(type, "server"))
4924 sub_category = "0002";
4925 else if (!g_strcmp0(type, "laptop"))
4926 sub_category = "0005";
4927 else if (!g_strcmp0(type, "desktop"))
4928 sub_category = "0006";
4929 else if (!g_strcmp0(type, "tablet"))
4930 sub_category = "0009";
4931 else if (!g_strcmp0(type, "watch"))
4934 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4937 static void p2p_support(GSupplicantInterface *interface)
4939 char dev_type[17] = {};
4940 const char *hostname;
4941 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4943 * Note: If supplicant interface's driver is wired then skip it,
4944 * because it meanti only for ethernet not Wi-Fi.
4946 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
4948 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4956 if (!g_supplicant_interface_has_p2p(interface))
4959 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4960 DBG("Could not register P2P technology driver");
4964 hostname = connman_utsname_get_hostname();
4966 hostname = "ConnMan";
4968 set_device_type(connman_machine_get_type(), dev_type);
4969 g_supplicant_interface_set_p2p_device_config(interface,
4970 hostname, dev_type);
4971 connman_peer_driver_register(&peer_driver);
4974 static void scan_started(GSupplicantInterface *interface)
4976 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4978 * Note: If supplicant interface's driver is wired then skip it,
4979 * because it meanti only for ethernet not Wi-Fi.
4981 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
4983 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4988 static void scan_finished(GSupplicantInterface *interface)
4990 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4992 * Note: If supplicant interface's driver is wired then skip it,
4993 * because it meanti only for ethernet not Wi-Fi.
4995 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
4997 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4999 #if defined TIZEN_EXT
5000 struct wifi_data *wifi;
5001 bool is_associating = false;
5002 static bool is_scanning = true;
5007 #if defined TIZEN_EXT
5008 wifi = g_supplicant_interface_get_data(interface);
5009 if (wifi && wifi->scan_pending_network) {
5010 network_connect(wifi->scan_pending_network);
5011 wifi->scan_pending_network = NULL;
5014 //service state - associating
5015 if(!wifi || !wifi->network)
5018 is_associating = connman_network_get_associating(wifi->network);
5019 if(is_associating && is_scanning){
5020 is_scanning = false;
5021 DBG("send scan for connecting");
5022 throw_wifi_scan(wifi->device, scan_callback);
5033 static void ap_create_fail(GSupplicantInterface *interface)
5035 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5037 * Note: If supplicant interface's driver is wired then skip it,
5038 * because it meanti only for ethernet not Wi-Fi.
5040 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5042 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5044 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5047 if ((wifi->tethering) && (wifi->tethering_param)) {
5048 DBG("%s create AP fail \n",
5049 g_supplicant_interface_get_ifname(wifi->interface));
5051 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
5052 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5053 wifi->tethering = false;
5055 ret = tech_set_tethering(wifi->tethering_param->technology,
5056 wifi->tethering_param->ssid->ssid,
5057 wifi->tethering_param->ssid->passphrase,
5058 wifi->bridge, true);
5060 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
5061 connman_technology_tethering_notify(wifi_technology,false);
5064 g_free(wifi->tethering_param->ssid);
5065 g_free(wifi->tethering_param);
5066 wifi->tethering_param = NULL;
5070 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
5072 unsigned char strength;
5074 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
5075 #if !defined TIZEN_EXT
5083 #if defined TIZEN_EXT_WIFI_MESH
5084 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
5086 GSupplicantInterface *interface;
5087 struct wifi_data *wifi;
5088 const char *name, *security;
5089 struct connman_mesh *connman_mesh;
5090 struct wifi_mesh_info *mesh_info;
5091 const unsigned char *bssid;
5092 const char *identifier;
5097 interface = g_supplicant_network_get_interface(supplicant_network);
5098 wifi = g_supplicant_interface_get_data(interface);
5099 if (!wifi || !wifi->mesh_interface) {
5100 DBG("Virtual Mesh interface not created");
5104 bssid = g_supplicant_network_get_bssid(supplicant_network);
5105 address = g_malloc0(19);
5106 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
5107 bssid[2], bssid[3], bssid[4], bssid[5]);
5109 identifier = g_supplicant_network_get_identifier(supplicant_network);
5110 name = g_supplicant_network_get_name(supplicant_network);
5111 security = g_supplicant_network_get_security(supplicant_network);
5112 frequency = g_supplicant_network_get_frequency(supplicant_network);
5114 mesh_info = wifi->mesh_info;
5115 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
5119 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
5121 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
5122 connman_mesh_set_name(connman_mesh, name);
5123 connman_mesh_set_security(connman_mesh, security);
5124 connman_mesh_set_frequency(connman_mesh, frequency);
5125 connman_mesh_set_address(connman_mesh, address);
5126 connman_mesh_set_index(connman_mesh, mesh_info->index);
5127 connman_mesh_set_strength(connman_mesh,
5128 calculate_strength(supplicant_network));
5129 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
5131 ret = connman_mesh_register(connman_mesh);
5132 if (ret == -EALREADY)
5133 DBG("Mesh Peer is already registered");
5139 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
5141 GSupplicantInterface *interface;
5142 struct wifi_data *wifi;
5143 struct connman_mesh *connman_mesh;
5144 struct wifi_mesh_info *mesh_info;
5145 const char *identifier;
5147 interface = g_supplicant_network_get_interface(supplicant_network);
5148 wifi = g_supplicant_interface_get_data(interface);
5149 if (!wifi || !wifi->mesh_interface) {
5150 DBG("Virtual Mesh interface not created");
5154 identifier = g_supplicant_network_get_identifier(supplicant_network);
5156 DBG("Failed to get Mesh Peer identifier");
5160 mesh_info = wifi->mesh_info;
5161 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
5163 /* Do not unregister connected mesh peer */
5164 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
5165 DBG("Mesh Peer %s is connected", identifier);
5168 DBG("Mesh Peer identifier %s removed", identifier);
5169 connman_mesh_unregister(connman_mesh);
5175 #if defined TIZEN_EXT
5176 static GSList *get_supported_security_list(unsigned int keymgmt,
5177 bool owe_transition_mode,
5178 GSupplicantNetwork *supplicant_network)
5180 GSList *sec_list = NULL;
5181 dbus_bool_t privacy = g_supplicant_network_get_privacy(supplicant_network);
5182 const char *enc_mode = g_supplicant_network_get_enc_mode(supplicant_network);
5185 (G_SUPPLICANT_KEYMGMT_WPA_EAP |
5186 G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
5187 sec_list = g_slist_prepend (sec_list, "ieee8021x");
5188 else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
5189 sec_list = g_slist_prepend (sec_list, "ft_ieee8021x");
5195 (G_SUPPLICANT_KEYMGMT_WPA_PSK |
5196 G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) {
5197 if (!g_strcmp0(enc_mode, "aes"))
5198 sec_list = g_slist_prepend (sec_list, "rsn");
5199 else if (!g_strcmp0(enc_mode, "tkip"))
5200 sec_list = g_slist_prepend (sec_list, "psk");
5201 else if (!g_strcmp0(enc_mode, "mixed")) {
5202 sec_list = g_slist_prepend (sec_list, "psk");
5203 sec_list = g_slist_prepend (sec_list, "rsn");
5205 } else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
5206 sec_list = g_slist_prepend (sec_list, "ft_psk");
5208 if (keymgmt & G_SUPPLICANT_KEYMGMT_SAE)
5209 sec_list = g_slist_prepend (sec_list, "sae");
5210 if (keymgmt & G_SUPPLICANT_KEYMGMT_OWE || owe_transition_mode)
5211 sec_list = g_slist_prepend (sec_list, "owe");
5212 if (keymgmt & G_SUPPLICANT_KEYMGMT_DPP)
5213 sec_list = g_slist_prepend (sec_list, "dpp");
5219 sec_list = g_slist_prepend (sec_list, "wep");
5221 sec_list = g_slist_prepend (sec_list, "none");
5227 static void network_added(GSupplicantNetwork *supplicant_network)
5229 struct connman_network *network;
5230 GSupplicantInterface *interface;
5231 struct wifi_data *wifi;
5232 const char *name, *identifier, *security, *group, *mode;
5233 const unsigned char *ssid;
5234 unsigned int ssid_len;
5238 bool wps_advertizing;
5240 #if defined TIZEN_EXT
5241 bool owe_transition_mode;
5242 const unsigned char *transition_mode_ssid;
5243 const unsigned char *transition_mode_bssid;
5244 unsigned int transition_mode_ssid_len;
5245 unsigned int keymgmt;
5246 GSList *vsie_list = NULL;
5247 GSList *sec_list = NULL;
5248 const unsigned char *country_code;
5249 ieee80211_modes_e phy_mode;
5252 mode = g_supplicant_network_get_mode(supplicant_network);
5253 identifier = g_supplicant_network_get_identifier(supplicant_network);
5254 #if defined TIZEN_EXT
5255 if (!simplified_log)
5257 DBG("%s", identifier);
5259 if (!g_strcmp0(mode, "adhoc"))
5262 #if defined TIZEN_EXT_WIFI_MESH
5263 if (!g_strcmp0(mode, "mesh")) {
5264 mesh_peer_added(supplicant_network);
5269 interface = g_supplicant_network_get_interface(supplicant_network);
5270 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5272 * Note: If supplicant interface's driver is wired then skip it,
5273 * because it meanti only for ethernet not Wi-Fi.
5275 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5277 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5279 wifi = g_supplicant_interface_get_data(interface);
5280 name = g_supplicant_network_get_name(supplicant_network);
5281 security = g_supplicant_network_get_security(supplicant_network);
5282 group = g_supplicant_network_get_identifier(supplicant_network);
5283 wps = g_supplicant_network_get_wps(supplicant_network);
5284 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
5285 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
5286 wps_advertizing = g_supplicant_network_is_wps_advertizing(
5287 supplicant_network);
5292 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
5294 network = connman_device_get_network(wifi->device, identifier);
5297 network = connman_network_create(identifier,
5298 CONNMAN_NETWORK_TYPE_WIFI);
5302 connman_network_set_index(network, wifi->index);
5304 if (connman_device_add_network(wifi->device, network) < 0) {
5305 connman_network_unref(network);
5309 wifi->networks = g_slist_prepend(wifi->networks, network);
5312 if (name && name[0] != '\0')
5313 connman_network_set_name(network, name);
5315 connman_network_set_blob(network, "WiFi.SSID",
5317 #if defined TIZEN_EXT
5318 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
5320 connman_network_set_vsie_list(network, vsie_list);
5322 DBG("vsie_list is NULL");
5323 country_code = g_supplicant_network_get_countrycode(supplicant_network);
5324 connman_network_set_countrycode(network, country_code);
5325 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
5326 connman_network_set_phy_mode(network, phy_mode);
5328 connman_network_set_string(network, "WiFi.Security", security);
5329 connman_network_set_strength(network,
5330 calculate_strength(supplicant_network));
5331 connman_network_set_bool(network, "WiFi.WPS", wps);
5332 connman_network_set_bool(network, "WiFi.WPSAdvertising",
5336 /* Is AP advertizing for WPS association?
5337 * If so, we decide to use WPS by default */
5338 if (wps_ready && wps_pbc &&
5340 #if !defined TIZEN_EXT
5341 connman_network_set_bool(network, "WiFi.UseWPS", true);
5343 DBG("wps is activating by ap but ignore it.");
5347 connman_network_set_frequency(network,
5348 g_supplicant_network_get_frequency(supplicant_network));
5350 #if defined TIZEN_EXT
5351 keymgmt = g_supplicant_network_get_keymgmt(supplicant_network);
5352 connman_network_set_bssid(network,
5353 g_supplicant_network_get_bssid(supplicant_network));
5354 owe_transition_mode = (bool)g_supplicant_network_get_transition_mode(supplicant_network);
5355 connman_network_set_bool(network, "WiFi.TRANSITION_MODE", owe_transition_mode);
5356 if (owe_transition_mode) {
5357 transition_mode_ssid = (unsigned char *)g_supplicant_network_get_transition_mode_ssid(supplicant_network, &transition_mode_ssid_len);
5358 connman_network_set_blob(network, "WiFi.TRANSITION_MODE_SSID",
5359 transition_mode_ssid, transition_mode_ssid_len);
5360 transition_mode_bssid = g_supplicant_network_get_transition_mode_bssid(supplicant_network);
5361 connman_network_set_transition_mode_bssid(network, transition_mode_bssid);
5364 sec_list = get_supported_security_list(keymgmt,
5365 owe_transition_mode, supplicant_network);
5367 connman_network_set_sec_list(network, sec_list);
5368 connman_network_set_maxrate(network,
5369 g_supplicant_network_get_maxrate(supplicant_network));
5370 connman_network_set_enc_mode(network,
5371 g_supplicant_network_get_enc_mode(supplicant_network));
5372 connman_network_set_rsn_mode(network,
5373 g_supplicant_network_get_rsn_mode(supplicant_network));
5374 connman_network_set_bool(network, "WiFi.PMFRequired",
5375 (bool)g_supplicant_network_is_pmf_required(supplicant_network));
5376 connman_network_set_keymgmt(network, keymgmt);
5377 connman_network_set_bool(network, "WiFi.HS20AP",
5378 g_supplicant_network_is_hs20AP(supplicant_network));
5379 connman_network_set_bssid_list(network,
5380 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
5381 connman_network_set_last_connected_bssid(network,
5382 g_supplicant_network_get_last_connected_bssid(supplicant_network));
5383 connman_network_set_assoc_reject_table(network,
5384 g_supplicant_network_get_assoc_reject_table(supplicant_network));
5386 connman_network_set_available(network, true);
5387 connman_network_set_string(network, "WiFi.Mode", mode);
5389 #if defined TIZEN_EXT
5394 connman_network_set_group(network, group);
5396 #if defined TIZEN_EXT
5397 g_supplicant_network_set_last_connected_bssid(supplicant_network,
5398 connman_network_get_last_connected_bssid(network));
5401 #if defined TIZEN_EXT
5402 if (wifi_first_scan == true)
5403 found_with_first_scan = true;
5406 if (wifi->hidden && ssid) {
5407 #if defined TIZEN_EXT
5408 if (network_security(wifi->hidden->security) ==
5409 network_security(security) &&
5411 if (!g_strcmp0(wifi->hidden->security, security) &&
5413 wifi->hidden->ssid_len == ssid_len &&
5414 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
5415 connman_network_connect_hidden(network,
5416 wifi->hidden->identity,
5417 wifi->hidden->passphrase,
5418 wifi->hidden->user_data);
5419 wifi->hidden->user_data = NULL;
5420 hidden_free(wifi->hidden);
5421 wifi->hidden = NULL;
5426 static void network_removed(GSupplicantNetwork *network)
5428 GSupplicantInterface *interface;
5429 struct wifi_data *wifi;
5430 const char *name, *identifier;
5431 struct connman_network *connman_network;
5433 #if defined TIZEN_EXT_WIFI_MESH
5435 mode = g_supplicant_network_get_mode(network);
5436 if (!g_strcmp0(mode, "mesh")) {
5437 mesh_peer_removed(network);
5442 interface = g_supplicant_network_get_interface(network);
5443 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5445 * Note: If supplicant interface's driver is wired then skip it,
5446 * because it meanti only for ethernet not Wi-Fi.
5448 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5450 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5452 wifi = g_supplicant_interface_get_data(interface);
5453 identifier = g_supplicant_network_get_identifier(network);
5454 name = g_supplicant_network_get_name(network);
5456 DBG("name %s", name);
5461 connman_network = connman_device_get_network(wifi->device, identifier);
5462 if (!connman_network)
5465 #if defined TIZEN_EXT
5466 if (connman_network == wifi->scan_pending_network)
5467 wifi->scan_pending_network = NULL;
5469 if (connman_network == wifi->pending_network)
5470 wifi->pending_network = NULL;
5472 if(connman_network_get_connecting(connman_network) == true){
5473 connman_network_set_connected(connman_network, false);
5477 wifi->networks = g_slist_remove(wifi->networks, connman_network);
5479 connman_device_remove_network(wifi->device, connman_network);
5480 connman_network_unref(connman_network);
5483 static void network_changed(GSupplicantNetwork *network, const char *property)
5485 GSupplicantInterface *interface;
5486 struct wifi_data *wifi;
5487 const char *name, *identifier;
5488 struct connman_network *connman_network;
5491 #if defined TIZEN_EXT
5492 const unsigned char *bssid;
5493 unsigned int maxrate;
5496 const unsigned char *country_code;
5497 ieee80211_modes_e phy_mode;
5501 interface = g_supplicant_network_get_interface(network);
5502 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5504 * Note: If supplicant interface's driver is wired then skip it,
5505 * because it meanti only for ethernet not Wi-Fi.
5507 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5509 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5511 wifi = g_supplicant_interface_get_data(interface);
5512 identifier = g_supplicant_network_get_identifier(network);
5513 name = g_supplicant_network_get_name(network);
5515 #if defined TIZEN_EXT
5516 if (!simplified_log)
5517 DBG("name %s property %s", name, property);
5519 DBG("name %s", name);
5525 connman_network = connman_device_get_network(wifi->device, identifier);
5526 if (!connman_network)
5529 if (g_str_equal(property, "WPSCapabilities")) {
5533 bool wps_advertizing;
5535 wps = g_supplicant_network_get_wps(network);
5536 wps_pbc = g_supplicant_network_is_wps_pbc(network);
5537 wps_ready = g_supplicant_network_is_wps_active(network);
5539 g_supplicant_network_is_wps_advertizing(network);
5541 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
5542 connman_network_set_bool(connman_network,
5543 "WiFi.WPSAdvertising", wps_advertizing);
5547 * Is AP advertizing for WPS association?
5548 * If so, we decide to use WPS by default
5550 if (wps_ready && wps_pbc && wps_advertizing)
5551 connman_network_set_bool(connman_network,
5552 "WiFi.UseWPS", true);
5555 update_needed = true;
5556 } else if (g_str_equal(property, "Signal")) {
5557 connman_network_set_strength(connman_network,
5558 calculate_strength(network));
5559 update_needed = true;
5561 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
5562 else if (g_str_equal(property, "LastConnectedBSSID")) {
5563 const char *ident, *group;
5564 char *service_ident;
5567 ident = connman_device_get_ident(wifi->device);
5568 group = connman_network_get_group(connman_network);
5569 if (ident && group) {
5570 service_ident = g_strdup_printf("%s_%s_%s",
5571 __connman_network_get_type(connman_network), ident, group);
5573 need_save = connman_device_set_last_connected_ident(wifi->device, service_ident);
5575 connman_device_save_last_connected(wifi->device);
5577 g_free(service_ident);
5580 connman_network_set_last_connected_bssid(connman_network,
5581 g_supplicant_network_get_last_connected_bssid(network));
5583 update_needed = true;
5585 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
5586 #if defined TIZEN_EXT
5587 else if (g_str_equal(property, "UpdateAssocReject")) {
5588 connman_network_set_assoc_reject_table(connman_network,
5589 g_supplicant_network_get_assoc_reject_table(network));
5590 update_needed = true;
5594 update_needed = false;
5597 connman_network_update(connman_network);
5599 #if defined TIZEN_EXT
5600 bssid = g_supplicant_network_get_bssid(network);
5601 maxrate = g_supplicant_network_get_maxrate(network);
5602 frequency = g_supplicant_network_get_frequency(network);
5603 wps = g_supplicant_network_get_wps(network);
5604 phy_mode = g_supplicant_network_get_phy_mode(network);
5606 connman_network_set_bssid(connman_network, bssid);
5607 connman_network_set_maxrate(connman_network, maxrate);
5608 connman_network_set_frequency(connman_network, frequency);
5609 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
5610 country_code = g_supplicant_network_get_countrycode(network);
5611 connman_network_set_countrycode(connman_network, country_code);
5612 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
5613 connman_network_set_bssid_list(connman_network, bssid_list);
5614 connman_network_set_phy_mode(connman_network, phy_mode);
5616 if (g_str_equal(property, "CheckMultiBssidConnect") &&
5617 connman_network_get_associating(connman_network))
5618 network_connect(connman_network);
5622 static void network_associated(GSupplicantNetwork *network)
5624 GSupplicantInterface *interface;
5625 struct wifi_data *wifi;
5626 struct connman_network *connman_network;
5627 const char *identifier;
5631 interface = g_supplicant_network_get_interface(network);
5634 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5636 * Note: If supplicant interface's driver is wired then skip it,
5637 * because it meanti only for ethernet not Wi-Fi.
5639 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5641 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5644 wifi = g_supplicant_interface_get_data(interface);
5648 /* P2P networks must not be treated as WiFi networks */
5649 if (wifi->p2p_connecting || wifi->p2p_device)
5652 identifier = g_supplicant_network_get_identifier(network);
5654 connman_network = connman_device_get_network(wifi->device, identifier);
5655 if (!connman_network)
5658 if (wifi->network) {
5659 if (wifi->network == connman_network)
5662 unsigned int ssid_len;
5663 DBG("network1 ssid[%s] , OWE[%d],ssid[%s]",
5664 (char *)connman_network_get_blob(wifi->network,"WiFi.SSID", &ssid_len),
5665 connman_network_get_bool(wifi->network,"WiFi.TRANSITION_MODE"),
5666 (char *)connman_network_get_blob(wifi->network,"WiFi.TRANSITION_MODE_SSID", &ssid_len));
5668 DBG("network1 ssid[%s], OWE[%d], ssid[%s]",
5669 (char *)connman_network_get_blob(connman_network,"WiFi.SSID",&ssid_len),
5670 connman_network_get_bool(connman_network,"WiFi.TRANSITION_MODE"),
5671 (char *)connman_network_get_blob(connman_network,"WiFi.TRANSITION_MODE_SSID", &ssid_len));
5672 if (connman_network_check_transition_mode(wifi->network, connman_network)) {//OWE trasition mode check
5673 DBG("OWE transition mode is TRUE");
5678 * This should never happen, we got associated with
5679 * a network different than the one we were expecting.
5681 DBG("Associated to %p while expecting %p",
5682 connman_network, wifi->network);
5684 connman_network_set_associating(wifi->network, false);
5687 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
5689 wifi->network = connman_network_ref(connman_network);
5693 * Interface state changes callback (interface_state) is always
5694 * called before network_associated callback thus we need to call
5695 * interface_state again in order to process the new state now that
5696 * we have the network properly set.
5698 interface_state(interface);
5701 static void sta_authorized(GSupplicantInterface *interface,
5704 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5706 * Note: If supplicant interface's driver is wired then skip it,
5707 * because it meanti only for ethernet not Wi-Fi.
5709 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5711 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5713 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5715 DBG("wifi %p station %s authorized", wifi, addr);
5717 if (!wifi || !wifi->tethering)
5720 __connman_tethering_client_register(addr);
5723 static void sta_deauthorized(GSupplicantInterface *interface,
5726 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5728 * Note: If supplicant interface's driver is wired then skip it,
5729 * because it meanti only for ethernet not Wi-Fi.
5731 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5733 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5735 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5737 DBG("wifi %p station %s deauthorized", wifi, addr);
5739 if (!wifi || !wifi->tethering)
5742 __connman_tethering_client_unregister(addr);
5745 static void apply_peer_services(GSupplicantPeer *peer,
5746 struct connman_peer *connman_peer)
5748 const unsigned char *data;
5753 connman_peer_reset_services(connman_peer);
5755 data = g_supplicant_peer_get_widi_ies(peer, &length);
5757 connman_peer_add_service(connman_peer,
5758 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
5762 static void peer_found(GSupplicantPeer *peer)
5764 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5765 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5766 struct connman_peer *connman_peer;
5767 const char *identifier, *name;
5770 #if defined TIZEN_EXT
5774 identifier = g_supplicant_peer_get_identifier(peer);
5775 name = g_supplicant_peer_get_name(peer);
5777 DBG("ident: %s", identifier);
5779 connman_peer = connman_peer_get(wifi->device, identifier);
5783 connman_peer = connman_peer_create(identifier);
5784 connman_peer_set_name(connman_peer, name);
5785 connman_peer_set_device(connman_peer, wifi->device);
5786 apply_peer_services(peer, connman_peer);
5788 ret = connman_peer_register(connman_peer);
5789 if (ret < 0 && ret != -EALREADY)
5790 connman_peer_unref(connman_peer);
5792 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
5795 static void peer_lost(GSupplicantPeer *peer)
5797 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5798 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5799 struct connman_peer *connman_peer;
5800 const char *identifier;
5805 identifier = g_supplicant_peer_get_identifier(peer);
5807 DBG("ident: %s", identifier);
5809 connman_peer = connman_peer_get(wifi->device, identifier);
5811 if (wifi->p2p_connecting &&
5812 wifi->pending_peer == connman_peer) {
5813 peer_connect_timeout(wifi);
5815 connman_peer_unregister(connman_peer);
5816 connman_peer_unref(connman_peer);
5819 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
5822 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
5824 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5825 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5826 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
5827 struct connman_peer *connman_peer;
5828 const char *identifier;
5830 identifier = g_supplicant_peer_get_identifier(peer);
5832 DBG("ident: %s", identifier);
5837 connman_peer = connman_peer_get(wifi->device, identifier);
5842 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
5843 apply_peer_services(peer, connman_peer);
5844 connman_peer_services_changed(connman_peer);
5846 case G_SUPPLICANT_PEER_GROUP_CHANGED:
5847 if (!g_supplicant_peer_is_in_a_group(peer))
5848 p_state = CONNMAN_PEER_STATE_IDLE;
5850 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
5852 case G_SUPPLICANT_PEER_GROUP_STARTED:
5854 case G_SUPPLICANT_PEER_GROUP_FINISHED:
5855 p_state = CONNMAN_PEER_STATE_IDLE;
5857 case G_SUPPLICANT_PEER_GROUP_JOINED:
5858 connman_peer_set_iface_address(connman_peer,
5859 g_supplicant_peer_get_iface_address(peer));
5861 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
5862 p_state = CONNMAN_PEER_STATE_IDLE;
5864 case G_SUPPLICANT_PEER_GROUP_FAILED:
5865 if (g_supplicant_peer_has_requested_connection(peer))
5866 p_state = CONNMAN_PEER_STATE_IDLE;
5868 p_state = CONNMAN_PEER_STATE_FAILURE;
5872 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
5873 p_state == CONNMAN_PEER_STATE_FAILURE) {
5874 if (wifi->p2p_connecting
5875 && connman_peer == wifi->pending_peer)
5876 peer_cancel_timeout(wifi);
5878 p_state = CONNMAN_PEER_STATE_UNKNOWN;
5881 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
5884 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
5885 GSupplicantInterface *g_iface;
5886 struct wifi_data *g_wifi;
5888 g_iface = g_supplicant_peer_get_group_interface(peer);
5892 g_wifi = g_supplicant_interface_get_data(g_iface);
5896 connman_peer_set_as_master(connman_peer,
5897 !g_supplicant_peer_is_client(peer));
5898 connman_peer_set_sub_device(connman_peer, g_wifi->device);
5901 * If wpa_supplicant didn't create a dedicated p2p-group
5902 * interface then mark this interface as p2p_device to avoid
5903 * scan and auto-scan are launched on it while P2P is connected.
5905 if (!g_list_find(p2p_iface_list, g_wifi))
5906 wifi->p2p_device = true;
5909 connman_peer_set_state(connman_peer, p_state);
5912 static void peer_request(GSupplicantPeer *peer)
5914 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5915 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5916 struct connman_peer *connman_peer;
5917 const char *identifier;
5919 #if defined TIZEN_EXT
5924 identifier = g_supplicant_peer_get_identifier(peer);
5926 DBG("ident: %s", identifier);
5928 connman_peer = connman_peer_get(wifi->device, identifier);
5932 connman_peer_request_connection(connman_peer);
5935 #if defined TIZEN_EXT
5936 static void system_power_off(void)
5939 struct wifi_data *wifi;
5940 struct connman_service *service;
5941 struct connman_ipconfig *ipconfig_ipv4;
5943 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
5944 for (list = iface_list; list; list = list->next) {
5947 if (wifi->network != NULL) {
5948 service = connman_service_lookup_from_network(wifi->network);
5949 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5950 __connman_dhcp_stop(ipconfig_ipv4);
5956 static void network_merged(GSupplicantNetwork *network)
5958 GSupplicantInterface *interface;
5959 GSupplicantState state;
5960 struct wifi_data *wifi;
5961 const char *identifier;
5962 struct connman_network *connman_network;
5966 interface = g_supplicant_network_get_interface(network);
5970 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5972 * Note: If supplicant interface's driver is wired then skip it,
5973 * because it meanti only for ethernet not Wi-Fi.
5975 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
5977 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5979 state = g_supplicant_interface_get_state(interface);
5980 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5983 wifi = g_supplicant_interface_get_data(interface);
5987 identifier = g_supplicant_network_get_identifier(network);
5989 connman_network = connman_device_get_network(wifi->device, identifier);
5990 if (!connman_network)
5993 DBG("merged identifier %s", identifier);
5995 if (wifi->connected == FALSE) {
5997 case G_SUPPLICANT_STATE_AUTHENTICATING:
5998 case G_SUPPLICANT_STATE_ASSOCIATING:
5999 case G_SUPPLICANT_STATE_ASSOCIATED:
6000 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
6001 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
6002 connman_network_set_associating(connman_network, TRUE);
6004 case G_SUPPLICANT_STATE_COMPLETED:
6005 connman_network_set_connected(connman_network, TRUE);
6008 DBG("Not handled the state : %d", state);
6013 ishs20AP = g_supplicant_network_is_hs20AP(network);
6016 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
6017 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
6018 connman_network_set_string(connman_network, "WiFi.EAP",
6020 connman_network_set_string(connman_network, "WiFi.Identity",
6021 g_supplicant_network_get_identity(network));
6022 connman_network_set_string(connman_network, "WiFi.Phase2",
6023 g_supplicant_network_get_phase2(network));
6028 wifi->network = connman_network;
6031 static void assoc_failed(void *user_data)
6033 struct connman_network *network = user_data;
6034 connman_network_set_associating(network, false);
6037 static void scan_done(GSupplicantInterface *interface)
6039 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6041 * Note: If supplicant interface's driver is wired then skip it,
6042 * because it meanti only for ethernet not Wi-Fi.
6044 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
6046 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6049 int scan_type = CONNMAN_SCAN_TYPE_WPA_SUPPLICANT;
6050 struct wifi_data *wifi;
6053 for (list = iface_list; list; list = list->next) {
6056 if (interface == wifi->interface) {
6057 scanning = connman_device_get_scanning(wifi->device,
6058 CONNMAN_SERVICE_TYPE_WIFI);
6060 __connman_technology_notify_scan_done(
6061 connman_device_get_string(wifi->device, "Interface"), scan_type);
6068 static void debug(const char *str)
6070 #if defined TIZEN_EXT
6071 if (connman_setting_get_bool("ConnmanSupplicantDebug"))
6073 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
6075 connman_debug("%s", str);
6078 static void disconnect_reasoncode(GSupplicantInterface *interface,
6081 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6083 * Note: If supplicant interface's driver is wired then skip it,
6084 * because it meanti only for ethernet not Wi-Fi.
6086 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
6088 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6090 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
6093 wifi->disconnect_code = reasoncode;
6097 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
6099 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6101 * Note: If supplicant interface's driver is wired then skip it,
6102 * because it meanti only for ethernet not Wi-Fi.
6104 if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
6106 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6108 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
6111 wifi->assoc_code = status_code;
6115 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
6116 static GSupplicantCallbacks callbacks = {
6117 #else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6118 static const GSupplicantCallbacks callbacks = {
6119 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
6120 .system_ready = system_ready,
6121 .system_killed = system_killed,
6122 .interface_added = interface_added,
6123 .interface_state = interface_state,
6124 .interface_removed = interface_removed,
6125 .p2p_support = p2p_support,
6126 .scan_started = scan_started,
6127 .scan_finished = scan_finished,
6128 .ap_create_fail = ap_create_fail,
6129 .network_added = network_added,
6130 .network_removed = network_removed,
6131 .network_changed = network_changed,
6132 .network_associated = network_associated,
6133 .sta_authorized = sta_authorized,
6134 .sta_deauthorized = sta_deauthorized,
6135 .peer_found = peer_found,
6136 .peer_lost = peer_lost,
6137 .peer_changed = peer_changed,
6138 .peer_request = peer_request,
6139 #if defined TIZEN_EXT
6140 .system_power_off = system_power_off,
6141 .network_merged = network_merged,
6142 .assoc_failed = assoc_failed,
6143 .scan_done = scan_done,
6146 .disconnect_reasoncode = disconnect_reasoncode,
6147 .assoc_status_code = assoc_status_code,
6148 #if defined TIZEN_EXT_WIFI_MESH
6149 .mesh_support = mesh_support,
6150 .mesh_group_started = mesh_group_started,
6151 .mesh_group_removed = mesh_group_removed,
6152 .mesh_peer_connected = mesh_peer_connected,
6153 .mesh_peer_disconnected = mesh_peer_disconnected,
6158 static int tech_probe(struct connman_technology *technology)
6160 wifi_technology = technology;
6165 static void tech_remove(struct connman_technology *technology)
6167 wifi_technology = NULL;
6170 static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
6172 GSupplicantSSID *ap;
6174 ap = g_try_malloc0(sizeof(GSupplicantSSID));
6178 ap->mode = G_SUPPLICANT_MODE_MASTER;
6179 #if defined TIZEN_EXT
6180 ap->ssid = (void *) ssid;
6184 ap->ssid_len = strlen(ssid);
6188 if (!passphrase || strlen(passphrase) == 0) {
6189 ap->security = G_SUPPLICANT_SECURITY_NONE;
6190 ap->passphrase = NULL;
6192 ap->security = G_SUPPLICANT_SECURITY_PSK;
6193 ap->protocol = G_SUPPLICANT_PROTO_RSN;
6194 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
6195 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
6196 ap->passphrase = passphrase;
6202 static void ap_start_callback(int result, GSupplicantInterface *interface,
6205 struct wifi_tethering_info *info = user_data;
6207 DBG("result %d index %d bridge %s",
6208 result, info->wifi->index, info->wifi->bridge);
6210 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
6211 connman_inet_remove_from_bridge(info->wifi->index,
6212 info->wifi->bridge);
6214 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
6215 connman_technology_tethering_notify(info->technology, false);
6216 g_free(info->wifi->tethering_param->ssid);
6217 g_free(info->wifi->tethering_param);
6218 info->wifi->tethering_param = NULL;
6222 g_free(info->ifname);
6226 static void ap_create_callback(int result,
6227 GSupplicantInterface *interface,
6230 struct wifi_tethering_info *info = user_data;
6232 DBG("result %d ifname %s", result,
6233 g_supplicant_interface_get_ifname(interface));
6235 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
6236 connman_inet_remove_from_bridge(info->wifi->index,
6237 info->wifi->bridge);
6239 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
6240 connman_technology_tethering_notify(info->technology, false);
6241 g_free(info->wifi->tethering_param->ssid);
6242 g_free(info->wifi->tethering_param);
6243 info->wifi->tethering_param = NULL;
6247 g_free(info->ifname);
6253 info->wifi->interface = interface;
6254 g_supplicant_interface_set_data(interface, info->wifi);
6256 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
6257 connman_error("Failed to set interface ap_scan property");
6259 g_supplicant_interface_connect(interface, info->ssid,
6260 ap_start_callback, info);
6263 static void sta_remove_callback(int result,
6264 GSupplicantInterface *interface,
6267 struct wifi_tethering_info *info = user_data;
6268 const char *driver = connman_setting_get_string("wifi");
6270 DBG("ifname %s result %d ", info->ifname, result);
6272 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
6273 info->wifi->tethering = false;
6274 connman_technology_tethering_notify(info->technology, false);
6276 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
6277 g_free(info->wifi->tethering_param->ssid);
6278 g_free(info->wifi->tethering_param);
6279 info->wifi->tethering_param = NULL;
6282 g_free(info->ifname);
6288 info->wifi->interface = NULL;
6290 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
6293 #endif /* TIZEN_EXT */
6298 static int enable_wifi_tethering(struct connman_technology *technology,
6299 const char *bridge, const char *identifier,
6300 const char *passphrase, bool available)
6303 GSupplicantInterface *interface;
6304 struct wifi_data *wifi;
6305 struct wifi_tethering_info *info;
6310 for (list = iface_list; list; list = list->next) {
6313 DBG("wifi %p network %p pending_network %p", wifi,
6314 wifi->network, wifi->pending_network);
6316 interface = wifi->interface;
6321 ifname = g_supplicant_interface_get_ifname(wifi->interface);
6325 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
6326 DBG("%s does not support AP mode (detected)", ifname);
6330 mode = g_supplicant_interface_get_mode(interface);
6331 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
6332 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
6333 DBG("%s does not support AP mode (capability)", ifname);
6337 if (wifi->network && available)
6340 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
6344 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
6345 if (!wifi->tethering_param) {
6351 info->technology = technology;
6352 info->wifi->bridge = bridge;
6353 info->ssid = ssid_ap_init(identifier, passphrase);
6357 info->ifname = g_strdup(ifname);
6359 wifi->tethering_param->technology = technology;
6360 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
6361 if (!wifi->tethering_param->ssid)
6364 info->wifi->tethering = true;
6365 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
6367 berr = connman_technology_tethering_notify(technology, true);
6371 err = g_supplicant_interface_remove(interface,
6372 sta_remove_callback,
6375 DBG("tethering wifi %p ifname %s", wifi, ifname);
6380 g_free(info->ifname);
6383 g_free(wifi->tethering_param);
6384 wifi->tethering_param = NULL;
6387 * Remove bridge if it was correctly created but remove
6388 * operation failed. Instead, if bridge creation failed then
6389 * break out and do not try again on another interface,
6390 * bridge set-up does not depend on it.
6393 connman_technology_tethering_notify(technology, false);
6401 static int tech_set_tethering(struct connman_technology *technology,
6402 const char *identifier, const char *passphrase,
6403 const char *bridge, bool enabled)
6406 struct wifi_data *wifi;
6412 for (list = iface_list; list; list = list->next) {
6415 if (wifi->tethering) {
6416 wifi->tethering = false;
6418 connman_inet_remove_from_bridge(wifi->index,
6420 wifi->bridged = false;
6424 connman_technology_tethering_notify(technology, false);
6429 DBG("trying tethering for available devices");
6430 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
6434 DBG("trying tethering for any device");
6435 err = enable_wifi_tethering(technology, bridge, identifier,
6442 static void regdom_callback(int result, const char *alpha2, void *user_data)
6446 if (!wifi_technology)
6452 connman_technology_regdom_notify(wifi_technology, alpha2);
6455 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
6457 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
6460 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
6461 static void supp_ins_init(void)
6464 GSupplicantINSPreferredFreq preferred_freq;
6466 string = connman_setting_get_string("INSPreferredFreqBSSID");
6467 if (g_strcmp0(string, "5GHz") == 0)
6468 preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ;
6469 else if (g_strcmp0(string, "2.4GHz") == 0)
6470 preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ;
6472 preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_UNKNOWN;
6474 g_supplicant_set_ins_settings(preferred_freq,
6475 connman_setting_get_bool("INSLastConnectedBSSID"),
6476 connman_setting_get_bool("INSAssocReject"),
6477 connman_setting_get_bool("INSSignalBSSID"),
6478 connman_setting_get_uint("INSPreferredFreqBSSIDScore"),
6479 connman_setting_get_uint("INSLastConnectedBSSIDScore"),
6480 connman_setting_get_uint("INSAssocRejectScore"),
6481 connman_setting_get_int("INSSignalLevel3_5GHz"),
6482 connman_setting_get_int("INSSignalLevel3_24GHz")
6485 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
6487 static struct connman_technology_driver tech_driver = {
6489 .type = CONNMAN_SERVICE_TYPE_WIFI,
6490 .probe = tech_probe,
6491 .remove = tech_remove,
6492 .set_tethering = tech_set_tethering,
6493 .set_regdom = tech_set_regdom,
6496 static int wifi_init(void)
6500 err = connman_network_driver_register(&network_driver);
6504 err = g_supplicant_register(&callbacks);
6506 connman_network_driver_unregister(&network_driver);
6510 err = connman_technology_driver_register(&tech_driver);
6512 g_supplicant_unregister(&callbacks);
6513 connman_network_driver_unregister(&network_driver);
6517 #if defined TIZEN_EXT
6518 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
6521 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
6523 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
6527 static void wifi_exit(void)
6531 connman_technology_driver_unregister(&tech_driver);
6533 g_supplicant_unregister(&callbacks);
6535 connman_network_driver_unregister(&network_driver);
6537 #if defined TIZEN_EXT
6538 g_hash_table_unref(failed_bssids);
6542 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
6543 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)