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 <linux/if_arp.h>
34 #include <linux/wireless.h>
35 #include <net/ethernet.h>
38 #define IFF_LOWER_UP 0x10000
41 #include <dbus/dbus.h>
44 #define CONNMAN_API_SUBJECT_TO_CHANGE
45 #include <connman/plugin.h>
46 #include <connman/inet.h>
47 #include <connman/device.h>
48 #include <connman/rtnl.h>
49 #include <connman/technology.h>
50 #include <connman/service.h>
51 #include <connman/peer.h>
52 #include <connman/log.h>
53 #include <connman/option.h>
54 #include <connman/storage.h>
55 #include <include/setting.h>
56 #include <connman/provision.h>
57 #include <connman/utsname.h>
58 #include <connman/machine.h>
60 #include <gsupplicant/gsupplicant.h>
62 #define CLEANUP_TIMEOUT 8 /* in seconds */
63 #define INACTIVE_TIMEOUT 12 /* in seconds */
64 #define FAVORITE_MAXIMUM_RETRIES 2
66 #define BGSCAN_DEFAULT "simple:30:-45:300"
67 #define AUTOSCAN_DEFAULT "exponential:3:300"
69 #define P2P_FIND_TIMEOUT 30
70 #define P2P_CONNECTION_TIMEOUT 100
71 #define P2P_LISTEN_PERIOD 500
72 #define P2P_LISTEN_INTERVAL 2000
74 #define ASSOC_STATUS_NO_CLIENT 17
76 #define LOAD_SHAPING_MAX_RETRIES 7
78 #define LOAD_SHAPING_MAX_RETRIES 3
82 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
85 static struct connman_technology *wifi_technology = NULL;
86 static struct connman_technology *p2p_technology = NULL;
88 enum wifi_ap_capability{
90 WIFI_AP_SUPPORTED = 1,
91 WIFI_AP_NOT_SUPPORTED = 2,
94 struct hidden_params {
96 unsigned int ssid_len;
98 char *anonymous_identity;
100 char *altsubject_match;
101 char *domain_suffix_match;
105 GSupplicantScanParams *scan_params;
110 * Used for autoscan "emulation".
111 * Should be removed when wpa_s autoscan support will be by default.
113 struct autoscan_params {
117 unsigned int timeout;
120 struct wifi_tethering_info {
121 struct wifi_data *wifi;
122 struct connman_technology *technology;
124 GSupplicantSSID *ssid;
129 struct connman_device *device;
130 struct connman_network *network;
131 struct connman_network *pending_network;
133 GSupplicantInterface *interface;
134 GSupplicantState state;
138 enum wifi_ap_capability ap_supported;
140 bool interface_ready;
146 int load_shaping_retries;
147 struct hidden_params *hidden;
148 bool postpone_hidden;
149 struct wifi_tethering_info *tethering_param;
151 * autoscan "emulation".
153 struct autoscan_params *autoscan;
155 GSupplicantScanParams *scan_params;
156 unsigned int p2p_find_timeout;
157 unsigned int p2p_connection_timeout;
158 struct connman_peer *pending_peer;
163 #if defined TIZEN_EXT
164 int assoc_retry_count;
165 struct connman_network *scan_pending_network;
166 bool allow_full_scan;
167 unsigned int automaxspeed_timeout;
171 #if defined TIZEN_EXT_WIFI_MESH
173 struct wifi_mesh_info *mesh_info;
177 #if defined TIZEN_EXT
181 #define TIZEN_ASSOC_RETRY_COUNT 4
183 static gboolean wifi_first_scan = false;
184 static gboolean found_with_first_scan = false;
185 static gboolean is_wifi_notifier_registered = false;
186 static GHashTable *failed_bssids = NULL;
187 static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
191 static GList *iface_list = NULL;
193 static GList *pending_wifi_device = NULL;
194 static GList *p2p_iface_list = NULL;
195 bool wfd_service_registered = false;
197 static void start_autoscan(struct connman_device *device);
199 static int tech_set_tethering(struct connman_technology *technology,
200 const char *identifier, const char *passphrase,
201 const char *bridge, bool enabled);
203 #if defined TIZEN_EXT
204 #define NETCONFIG_SERVICE "net.netconfig"
205 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
206 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
208 struct enc_method_call_data {
209 DBusConnection *connection;
210 struct connman_network *network;
213 static struct enc_method_call_data encrypt_request_data;
215 static void encryption_request_reply(DBusPendingCall *call,
220 DBusMessageIter args;
222 struct connman_service *service;
223 gchar* encrypted_value = NULL;
224 struct connman_network *network = encrypt_request_data.network;
228 reply = dbus_pending_call_steal_reply(call);
230 dbus_error_init(&error);
231 if (dbus_set_error_from_message(&error, reply)) {
232 DBG("send_encryption_request() %s %s", error.name, error.message);
233 dbus_error_free(&error);
237 if (dbus_message_iter_init(reply, &args) == FALSE)
240 dbus_message_iter_get_basic(&args, &out_data);
242 encrypted_value = g_strdup((const gchar *)out_data);
243 service = connman_service_lookup_from_network(network);
246 DBG("encryption result: no service");
250 if (connman_service_get_favorite(service)) {
251 __connman_service_set_passphrase(service, encrypted_value);
252 __connman_service_save(service);
254 connman_network_set_string(network, "WiFi.Passphrase",
257 DBG("encryption result: succeeded");
260 dbus_message_unref(reply);
261 dbus_pending_call_unref(call);
262 dbus_connection_unref(encrypt_request_data.connection);
263 g_free(encrypted_value);
265 encrypt_request_data.connection = NULL;
266 encrypt_request_data.network = NULL;
269 static int send_encryption_request(const char *passphrase,
270 struct connman_network *network)
272 DBusConnection *connection = NULL;
273 DBusMessage *msg = NULL;
274 DBusPendingCall *call;
277 DBG("Invalid parameter");
281 connection = connman_dbus_get_connection();
283 DBG("dbus connection does not exist");
287 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
288 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
290 dbus_connection_unref(connection);
294 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
297 if (!dbus_connection_send_with_reply(connection, msg,
298 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
299 dbus_message_unref(msg);
300 dbus_connection_unref(connection);
305 dbus_message_unref(msg);
306 dbus_connection_unref(connection);
310 encrypt_request_data.connection = connection;
311 encrypt_request_data.network = network;
313 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
314 dbus_message_unref(msg);
320 static int p2p_tech_probe(struct connman_technology *technology)
322 p2p_technology = technology;
327 static void p2p_tech_remove(struct connman_technology *technology)
329 p2p_technology = NULL;
332 static struct connman_technology_driver p2p_tech_driver = {
334 .type = CONNMAN_SERVICE_TYPE_P2P,
335 .probe = p2p_tech_probe,
336 .remove = p2p_tech_remove,
339 static bool is_p2p_connecting(void)
343 for (list = iface_list; list; list = list->next) {
344 struct wifi_data *wifi = list->data;
346 if (wifi->p2p_connecting)
353 static void add_pending_wifi_device(struct wifi_data *wifi)
355 if (g_list_find(pending_wifi_device, wifi))
358 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
361 #if defined TIZEN_EXT_WIFI_MESH
362 struct wifi_mesh_info {
363 struct wifi_data *wifi;
364 GSupplicantInterface *interface;
365 struct connman_mesh *mesh;
372 struct mesh_change_peer_status_info {
374 enum connman_mesh_peer_status peer_status;
375 mesh_change_peer_status_cb_t callback;
379 static struct connman_technology_driver mesh_tech_driver = {
381 .type = CONNMAN_SERVICE_TYPE_MESH,
384 static void mesh_interface_create_callback(int result,
385 GSupplicantInterface *interface,
388 struct wifi_mesh_info *mesh_info = user_data;
389 struct wifi_data *wifi;
390 bool success = false;
392 DBG("result %d ifname %s, mesh_info %p", result,
393 g_supplicant_interface_get_ifname(interface),
396 if (result < 0 || !mesh_info)
399 wifi = mesh_info->wifi;
401 mesh_info->interface = interface;
402 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
403 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
404 DBG("Mesh Interface identifier %s", mesh_info->identifier);
405 wifi->mesh_interface = true;
406 wifi->mesh_info = mesh_info;
407 g_supplicant_interface_set_data(interface, wifi);
411 connman_mesh_notify_interface_create(success);
414 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
417 struct wifi_data *wifi;
418 struct wifi_mesh_info *mesh_info;
419 const char *wifi_ifname;
420 bool parent_found = false;
421 const char *driver = "nl80211";
423 for (list = iface_list; list; list = list->next) {
426 if (!g_supplicant_interface_has_mesh(wifi->interface))
429 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
433 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
440 DBG("Parent interface %s doesn't exist", parent_ifname);
444 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
448 mesh_info->wifi = wifi;
449 mesh_info->ifname = g_strdup(ifname);
450 mesh_info->parent_ifname = g_strdup(parent_ifname);
452 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
453 mesh_interface_create_callback, mesh_info);
457 static void mesh_interface_remove_callback(int result,
458 GSupplicantInterface *interface,
461 struct wifi_data *wifi = user_data;
462 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
463 bool success = false;
465 DBG("result %d mesh_info %p", result, mesh_info);
467 if (result < 0 || !mesh_info)
470 mesh_info->interface = NULL;
471 g_free(mesh_info->parent_ifname);
472 g_free(mesh_info->ifname);
473 g_free(mesh_info->identifier);
475 wifi->mesh_interface = false;
476 wifi->mesh_info = NULL;
480 connman_mesh_notify_interface_remove(success);
483 static int remove_mesh_interface(const char *ifname)
486 struct wifi_data *wifi;
487 struct wifi_mesh_info *mesh_info;
488 bool mesh_if_found = false;
491 for (list = iface_list; list; list = list->next) {
494 if (wifi->mesh_interface) {
495 mesh_if_found = true;
500 if (!mesh_if_found) {
501 DBG("Mesh interface %s doesn't exist", ifname);
505 mesh_info = wifi->mesh_info;
506 ret = g_supplicant_interface_remove(mesh_info->interface,
507 mesh_interface_remove_callback, wifi);
514 static void mesh_disconnect_callback(int result,
515 GSupplicantInterface *interface, void *user_data)
517 struct connman_mesh *mesh = user_data;
519 DBG("result %d interface %p mesh %p", result, interface, mesh);
522 static int mesh_peer_disconnect(struct connman_mesh *mesh)
525 struct wifi_data *wifi;
526 struct wifi_mesh_info *mesh_info;
527 bool mesh_if_found = false;
528 GSupplicantInterface *interface;
530 for (list = iface_list; list; list = list->next) {
533 if (wifi->mesh_interface) {
534 mesh_if_found = true;
539 if (!mesh_if_found) {
540 DBG("Mesh interface is not created");
544 mesh_info = wifi->mesh_info;
546 interface = mesh_info->interface;
547 return g_supplicant_interface_disconnect(interface,
548 mesh_disconnect_callback, mesh);
551 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
554 struct connman_mesh *mesh = user_data;
555 DBG("mesh %p result %d", mesh, result);
558 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
560 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
563 static GSupplicantSecurity mesh_network_security(const char *security)
565 if (g_str_equal(security, "none"))
566 return G_SUPPLICANT_SECURITY_NONE;
567 else if (g_str_equal(security, "sae"))
568 return G_SUPPLICANT_SECURITY_SAE;
570 return G_SUPPLICANT_SECURITY_UNKNOWN;
573 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
576 const char *security;
581 memset(ssid, 0, sizeof(*ssid));
582 ssid->mode = G_SUPPLICANT_MODE_MESH;
584 security = connman_mesh_get_security(mesh);
585 ssid->security = mesh_network_security(security);
587 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
588 ssid->passphrase = connman_mesh_get_passphrase(mesh);
590 ssid->freq = connman_mesh_get_frequency(mesh);
591 name = connman_mesh_get_name(mesh);
593 ssid->ssid_len = strlen(name);
594 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
595 memcpy(ssid->ssid, name, ssid->ssid_len);
600 static int mesh_peer_connect(struct connman_mesh *mesh)
603 struct wifi_data *wifi;
604 struct wifi_mesh_info *mesh_info;
605 bool mesh_if_found = false;
606 GSupplicantInterface *interface;
607 GSupplicantSSID *ssid;
609 for (list = iface_list; list; list = list->next) {
612 if (wifi->mesh_interface) {
613 mesh_if_found = true;
618 if (!mesh_if_found) {
619 DBG("Mesh interface is not created");
623 mesh_info = wifi->mesh_info;
625 interface = mesh_info->interface;
627 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
631 mesh_info->mesh = mesh;
633 mesh_ssid_init(ssid, mesh);
634 return g_supplicant_interface_connect(interface, ssid,
635 mesh_connect_callback, mesh);
638 static void mesh_peer_change_status_callback(int result,
639 GSupplicantInterface *interface,
642 struct mesh_change_peer_status_info *data = user_data;
644 DBG("result %d Peer Status %d", result, data->peer_status);
646 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
647 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
648 connman_mesh_remove_connected_peer(data->peer_address, 52);
652 data->callback(result, data->user_data);
654 g_free(data->peer_address);
659 static int mesh_change_peer_status(const char *peer_address,
660 enum connman_mesh_peer_status status,
661 mesh_change_peer_status_cb_t callback, void *user_data)
664 struct wifi_data *wifi;
665 struct wifi_mesh_info *mesh_info;
666 bool mesh_if_found = false;
667 GSupplicantInterface *interface;
668 struct mesh_change_peer_status_info *data;
671 for (list = iface_list; list; list = list->next) {
674 if (wifi->mesh_interface) {
675 mesh_if_found = true;
680 if (!mesh_if_found) {
681 DBG("Mesh interface is not created");
685 mesh_info = wifi->mesh_info;
687 interface = mesh_info->interface;
690 case CONNMAN_MESH_PEER_ADD:
691 method = "MeshPeerAdd";
693 case CONNMAN_MESH_PEER_REMOVE:
694 method = "MeshPeerRemove";
697 DBG("Invalid method");
701 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
703 DBG("Memory allocation failed");
707 data->peer_address = g_strdup(peer_address);
708 data->peer_status = status;
709 data->callback = callback;
710 data->user_data = user_data;
712 return g_supplicant_interface_mesh_peer_change_status(interface,
713 mesh_peer_change_status_callback, peer_address, method,
717 static struct connman_mesh_driver mesh_driver = {
718 .add_interface = add_mesh_interface,
719 .remove_interface = remove_mesh_interface,
720 .connect = mesh_peer_connect,
721 .disconnect = mesh_peer_disconnect,
722 .change_peer_status = mesh_change_peer_status,
725 static void mesh_support(GSupplicantInterface *interface)
729 if (!g_supplicant_interface_has_mesh(interface))
732 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
733 DBG("Could not register Mesh technology driver");
737 connman_mesh_driver_register(&mesh_driver);
740 static void check_mesh_technology(void)
742 bool mesh_exists = false;
745 for (list = iface_list; list; list = list->next) {
746 struct wifi_data *w = list->data;
749 g_supplicant_interface_has_mesh(w->interface))
754 connman_technology_driver_unregister(&mesh_tech_driver);
755 connman_mesh_driver_unregister(&mesh_driver);
759 static void mesh_group_started(GSupplicantInterface *interface)
761 struct wifi_data *wifi;
762 struct wifi_mesh_info *mesh_info;
763 struct connman_mesh *mesh;
764 const unsigned char *ssid;
765 unsigned int ssid_len;
768 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
769 memcpy(name, ssid, ssid_len);
770 name[ssid_len] = '\0';
771 DBG("name %s", name);
772 wifi = g_supplicant_interface_get_data(interface);
773 DBG("wifi %p", wifi);
778 mesh_info = wifi->mesh_info;
782 mesh = mesh_info->mesh;
786 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
789 static void mesh_group_removed(GSupplicantInterface *interface)
791 struct wifi_data *wifi;
792 struct wifi_mesh_info *mesh_info;
793 struct connman_mesh *mesh;
794 const unsigned char *ssid;
795 unsigned int ssid_len;
796 int disconnect_reason;
799 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
800 memcpy(name, ssid, ssid_len);
801 name[ssid_len] = '\0';
802 DBG("name %s", name);
804 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
805 DBG("Disconnect Reason %d", disconnect_reason);
807 wifi = g_supplicant_interface_get_data(interface);
808 DBG("wifi %p", wifi);
813 mesh_info = wifi->mesh_info;
817 mesh = connman_get_connected_mesh_from_name(name);
819 DBG("%s is not connected", name);
820 mesh = connman_get_connecting_mesh_from_name(name);
822 DBG("%s is not connecting", name);
827 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
828 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
831 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
833 const char *peer_address;
835 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
840 DBG("Peer %s connected", peer_address);
841 connman_mesh_add_connected_peer(peer_address);
844 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
846 const char *peer_address;
849 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
854 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
856 DBG("Peer %s disconnected with reason %d", peer_address, reason);
857 connman_mesh_remove_connected_peer(peer_address, reason);
861 static struct wifi_data *get_pending_wifi_data(const char *ifname)
865 for (list = pending_wifi_device; list; list = list->next) {
866 struct wifi_data *wifi;
867 const char *dev_name;
870 if (!wifi || !wifi->device)
873 dev_name = connman_device_get_string(wifi->device, "Interface");
874 if (!g_strcmp0(ifname, dev_name)) {
875 pending_wifi_device = g_list_delete_link(
876 pending_wifi_device, list);
884 static void remove_pending_wifi_device(struct wifi_data *wifi)
888 link = g_list_find(pending_wifi_device, wifi);
893 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
896 static void peer_cancel_timeout(struct wifi_data *wifi)
898 if (wifi->p2p_connection_timeout > 0)
899 g_source_remove(wifi->p2p_connection_timeout);
901 wifi->p2p_connection_timeout = 0;
902 wifi->p2p_connecting = false;
904 if (wifi->pending_peer) {
905 connman_peer_unref(wifi->pending_peer);
906 wifi->pending_peer = NULL;
910 static gboolean peer_connect_timeout(gpointer data)
912 struct wifi_data *wifi = data;
916 if (wifi->p2p_connecting) {
917 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
918 GSupplicantPeer *gs_peer =
919 g_supplicant_interface_peer_lookup(wifi->interface,
920 connman_peer_get_identifier(wifi->pending_peer));
922 if (g_supplicant_peer_has_requested_connection(gs_peer))
923 state = CONNMAN_PEER_STATE_IDLE;
925 connman_peer_set_state(wifi->pending_peer, state);
928 peer_cancel_timeout(wifi);
933 static void peer_connect_callback(int result, GSupplicantInterface *interface,
936 struct wifi_data *wifi = user_data;
937 struct connman_peer *peer = wifi->pending_peer;
939 DBG("peer %p - %d", peer, result);
945 peer_connect_timeout(wifi);
949 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
951 wifi->p2p_connection_timeout = g_timeout_add_seconds(
952 P2P_CONNECTION_TIMEOUT,
953 peer_connect_timeout, wifi);
956 static int peer_connect(struct connman_peer *peer,
957 enum connman_peer_wps_method wps_method,
960 struct connman_device *device = connman_peer_get_device(peer);
961 GSupplicantPeerParams *peer_params;
962 GSupplicantPeer *gs_peer;
963 struct wifi_data *wifi;
967 DBG("peer %p", peer);
972 wifi = connman_device_get_data(device);
973 if (!wifi || !wifi->interface)
976 if (wifi->p2p_connecting)
979 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
980 connman_peer_get_identifier(peer));
984 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
985 pin = g_supplicant_peer_is_wps_pin(gs_peer);
987 switch (wps_method) {
988 case CONNMAN_PEER_WPS_UNKNOWN:
989 if ((pbc && pin) || pin)
992 case CONNMAN_PEER_WPS_PBC:
997 case CONNMAN_PEER_WPS_PIN:
998 if (!pin || !wps_pin)
1003 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1007 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1009 peer_params->wps_pin = g_strdup(wps_pin);
1011 peer_params->master = connman_peer_service_is_master();
1013 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1014 peer_connect_callback, wifi);
1015 if (ret == -EINPROGRESS) {
1016 wifi->pending_peer = connman_peer_ref(peer);
1017 wifi->p2p_connecting = true;
1018 } else if (ret < 0) {
1019 g_free(peer_params->path);
1020 g_free(peer_params->wps_pin);
1021 g_free(peer_params);
1027 static int peer_disconnect(struct connman_peer *peer)
1029 struct connman_device *device = connman_peer_get_device(peer);
1030 GSupplicantPeerParams peer_params = {};
1031 GSupplicantPeer *gs_peer;
1032 struct wifi_data *wifi;
1035 DBG("peer %p", peer);
1040 wifi = connman_device_get_data(device);
1044 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1045 connman_peer_get_identifier(peer));
1049 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1051 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1053 g_free(peer_params.path);
1055 if (ret == -EINPROGRESS) {
1056 peer_cancel_timeout(wifi);
1057 wifi->p2p_device = false;
1063 struct peer_service_registration {
1064 peer_service_registration_cb_t callback;
1068 static bool is_service_wfd(const unsigned char *specs, int length)
1070 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1076 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1078 struct wifi_data *wifi = data;
1080 if (!wifi->interface ||
1081 !g_supplicant_interface_has_p2p(wifi->interface))
1084 if (!wifi->servicing) {
1085 g_supplicant_interface_p2p_listen(wifi->interface,
1086 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1092 static void register_wfd_service_cb(int result,
1093 GSupplicantInterface *iface, void *user_data)
1095 struct peer_service_registration *reg_data = user_data;
1100 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1102 if (reg_data && reg_data->callback) {
1103 reg_data->callback(result, reg_data->user_data);
1108 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1109 const unsigned char *spec,
1110 int spec_length, const unsigned char *query,
1111 int query_length, int version)
1113 GSupplicantP2PServiceParams *params;
1115 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1120 params->version = version;
1121 params->service = g_memdup(spec, spec_length);
1122 } else if (query_length > 0 && spec_length > 0) {
1123 params->query = g_memdup(query, query_length);
1124 params->query_length = query_length;
1126 params->response = g_memdup(spec, spec_length);
1127 params->response_length = spec_length;
1129 params->wfd_ies = g_memdup(spec, spec_length);
1130 params->wfd_ies_length = spec_length;
1136 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1141 g_free(params->service);
1142 g_free(params->query);
1143 g_free(params->response);
1144 g_free(params->wfd_ies);
1149 static int peer_register_wfd_service(const unsigned char *specification,
1150 int specification_length,
1151 peer_service_registration_cb_t callback,
1154 struct peer_service_registration *reg_data = NULL;
1155 static GSupplicantP2PServiceParams *params;
1160 if (wfd_service_registered)
1163 params = fill_in_peer_service_params(specification,
1164 specification_length, NULL, 0, 0);
1168 reg_data = g_try_malloc0(sizeof(*reg_data));
1174 reg_data->callback = callback;
1175 reg_data->user_data = user_data;
1177 ret = g_supplicant_set_widi_ies(params,
1178 register_wfd_service_cb, reg_data);
1179 if (ret < 0 && ret != -EINPROGRESS)
1182 wfd_service_registered = true;
1186 free_peer_service_params(params);
1192 static void register_peer_service_cb(int result,
1193 GSupplicantInterface *iface, void *user_data)
1195 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1196 struct peer_service_registration *reg_data = user_data;
1198 #if defined TIZEN_EXT
1206 apply_p2p_listen_on_iface(wifi, NULL);
1208 if (reg_data->callback)
1209 reg_data->callback(result, reg_data->user_data);
1214 static int peer_register_service(const unsigned char *specification,
1215 int specification_length,
1216 const unsigned char *query,
1217 int query_length, int version,
1218 peer_service_registration_cb_t callback,
1221 struct peer_service_registration *reg_data;
1222 GSupplicantP2PServiceParams *params;
1229 if (specification && !version && !query &&
1230 is_service_wfd(specification, specification_length)) {
1231 return peer_register_wfd_service(specification,
1232 specification_length, callback, user_data);
1235 reg_data = g_try_malloc0(sizeof(*reg_data));
1239 reg_data->callback = callback;
1240 reg_data->user_data = user_data;
1242 ret_f = -EOPNOTSUPP;
1244 for (list = iface_list; list; list = list->next) {
1245 struct wifi_data *wifi = list->data;
1246 GSupplicantInterface *iface = wifi->interface;
1248 if (!g_supplicant_interface_has_p2p(iface))
1251 params = fill_in_peer_service_params(specification,
1252 specification_length, query,
1253 query_length, version);
1260 ret_f = g_supplicant_interface_p2p_add_service(iface,
1261 register_peer_service_cb, params, reg_data);
1262 if (ret_f == 0 || ret_f == -EINPROGRESS)
1266 ret = g_supplicant_interface_p2p_add_service(iface,
1267 register_peer_service_cb, params, NULL);
1268 if (ret != 0 && ret != -EINPROGRESS)
1269 free_peer_service_params(params);
1272 if (ret_f != 0 && ret_f != -EINPROGRESS)
1278 static int peer_unregister_wfd_service(void)
1280 GSupplicantP2PServiceParams *params;
1283 if (!wfd_service_registered)
1286 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1290 wfd_service_registered = false;
1292 g_supplicant_set_widi_ies(params, NULL, NULL);
1294 for (list = iface_list; list; list = list->next) {
1295 struct wifi_data *wifi = list->data;
1297 if (!g_supplicant_interface_has_p2p(wifi->interface))
1301 if (!wifi->servicing || wifi->servicing < 0) {
1302 g_supplicant_interface_p2p_listen(wifi->interface,
1304 wifi->servicing = 0;
1311 static int peer_unregister_service(const unsigned char *specification,
1312 int specification_length,
1313 const unsigned char *query,
1314 int query_length, int version)
1316 GSupplicantP2PServiceParams *params;
1321 if (specification && !version && !query &&
1322 is_service_wfd(specification, specification_length)) {
1323 ret = peer_unregister_wfd_service();
1324 if (ret != 0 && ret != -EINPROGRESS)
1329 for (list = iface_list; list; list = list->next) {
1330 struct wifi_data *wifi = list->data;
1331 GSupplicantInterface *iface = wifi->interface;
1334 goto stop_listening;
1336 if (!g_supplicant_interface_has_p2p(iface))
1339 params = fill_in_peer_service_params(specification,
1340 specification_length, query,
1341 query_length, version);
1347 ret = g_supplicant_interface_p2p_del_service(iface, params);
1348 if (ret != 0 && ret != -EINPROGRESS)
1349 free_peer_service_params(params);
1352 if (!wifi->servicing || wifi->servicing < 0) {
1353 g_supplicant_interface_p2p_listen(iface, 0, 0);
1354 wifi->servicing = 0;
1361 static struct connman_peer_driver peer_driver = {
1362 .connect = peer_connect,
1363 .disconnect = peer_disconnect,
1364 .register_service = peer_register_service,
1365 .unregister_service = peer_unregister_service,
1368 static void handle_tethering(struct wifi_data *wifi)
1370 if (!wifi->tethering)
1379 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1381 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1384 wifi->bridged = true;
1387 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1389 struct connman_device *device = user_data;
1390 struct wifi_data *wifi = connman_device_get_data(device);
1395 DBG("index %d flags %d change %d", wifi->index, flags, change);
1397 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1399 DBG("interface up");
1401 DBG("interface down");
1404 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1405 if (flags & IFF_LOWER_UP) {
1408 handle_tethering(wifi);
1413 wifi->flags = flags;
1416 static int wifi_probe(struct connman_device *device)
1418 struct wifi_data *wifi;
1420 DBG("device %p", device);
1422 wifi = g_try_new0(struct wifi_data, 1);
1426 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1427 wifi->ap_supported = WIFI_AP_UNKNOWN;
1428 wifi->tethering_param = NULL;
1430 connman_device_set_data(device, wifi);
1431 wifi->device = connman_device_ref(device);
1433 wifi->index = connman_device_get_index(device);
1436 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1437 wifi_newlink, device);
1438 if (is_p2p_connecting())
1439 add_pending_wifi_device(wifi);
1441 iface_list = g_list_append(iface_list, wifi);
1446 static void remove_networks(struct connman_device *device,
1447 struct wifi_data *wifi)
1451 for (list = wifi->networks; list; list = list->next) {
1452 struct connman_network *network = list->data;
1454 connman_device_remove_network(device, network);
1455 connman_network_unref(network);
1458 g_slist_free(wifi->networks);
1459 wifi->networks = NULL;
1462 static void remove_peers(struct wifi_data *wifi)
1466 for (list = wifi->peers; list; list = list->next) {
1467 struct connman_peer *peer = list->data;
1469 connman_peer_unregister(peer);
1470 connman_peer_unref(peer);
1473 g_slist_free(wifi->peers);
1477 static void reset_autoscan(struct connman_device *device)
1479 struct wifi_data *wifi = connman_device_get_data(device);
1480 struct autoscan_params *autoscan;
1484 if (!wifi || !wifi->autoscan)
1487 autoscan = wifi->autoscan;
1489 if (autoscan->timeout == 0 && autoscan->interval == 0)
1492 g_source_remove(autoscan->timeout);
1494 autoscan->timeout = 0;
1495 autoscan->interval = 0;
1497 connman_device_unref(device);
1500 static void stop_autoscan(struct connman_device *device)
1502 const struct wifi_data *wifi = connman_device_get_data(device);
1504 if (!wifi || !wifi->autoscan)
1507 reset_autoscan(device);
1509 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1512 static void check_p2p_technology(void)
1514 bool p2p_exists = false;
1517 for (list = iface_list; list; list = list->next) {
1518 struct wifi_data *w = list->data;
1521 g_supplicant_interface_has_p2p(w->interface))
1526 connman_technology_driver_unregister(&p2p_tech_driver);
1527 connman_peer_driver_unregister(&peer_driver);
1531 static void wifi_remove(struct connman_device *device)
1533 struct wifi_data *wifi = connman_device_get_data(device);
1535 DBG("device %p wifi %p", device, wifi);
1540 stop_autoscan(device);
1542 if (wifi->p2p_device)
1543 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1545 iface_list = g_list_remove(iface_list, wifi);
1547 check_p2p_technology();
1548 #if defined TIZEN_EXT_WIFI_MESH
1549 check_mesh_technology();
1552 remove_pending_wifi_device(wifi);
1554 if (wifi->p2p_find_timeout) {
1555 g_source_remove(wifi->p2p_find_timeout);
1556 connman_device_unref(wifi->device);
1559 if (wifi->p2p_connection_timeout)
1560 g_source_remove(wifi->p2p_connection_timeout);
1562 #if defined TIZEN_EXT
1563 if (wifi->automaxspeed_timeout != 0) {
1564 g_source_remove(wifi->automaxspeed_timeout);
1565 wifi->automaxspeed_timeout = 0;
1569 remove_networks(device, wifi);
1572 connman_device_set_powered(device, false);
1573 connman_device_set_data(device, NULL);
1574 connman_device_unref(wifi->device);
1575 connman_rtnl_remove_watch(wifi->watch);
1577 g_supplicant_interface_set_data(wifi->interface, NULL);
1579 g_supplicant_interface_cancel(wifi->interface);
1581 if (wifi->scan_params)
1582 g_supplicant_free_scan_params(wifi->scan_params);
1584 g_free(wifi->autoscan);
1585 g_free(wifi->identifier);
1589 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1593 for (iter = list; iter; iter = g_slist_next(iter)) {
1594 struct scan_ssid *scan_ssid = iter->data;
1596 if (ssid_len == scan_ssid->ssid_len &&
1597 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1604 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1605 int freq, GSupplicantScanParams *scan_data,
1606 int driver_max_scan_ssids, char *ssid_name)
1609 struct scan_ssid *scan_ssid;
1611 if ((driver_max_scan_ssids == 0 ||
1612 driver_max_scan_ssids > scan_data->num_ssids) &&
1613 (hex_ssid || raw_ssid)) {
1615 unsigned int j = 0, hex;
1618 size_t hex_ssid_len = strlen(hex_ssid);
1620 ssid = g_try_malloc0(hex_ssid_len / 2);
1624 for (i = 0; i < hex_ssid_len; i += 2) {
1625 sscanf(hex_ssid + i, "%02x", &hex);
1634 * If we have already added hidden AP to the list,
1635 * then do not do it again. This might happen if you have
1636 * used or are using multiple wifi cards, so in that case
1637 * you might have multiple service files for same AP.
1639 if (is_duplicate(scan_data->ssids, ssid, j)) {
1645 scan_ssid = g_try_new(struct scan_ssid, 1);
1652 memcpy(scan_ssid->ssid, ssid, j);
1653 scan_ssid->ssid_len = j;
1654 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1657 scan_data->num_ssids++;
1659 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1660 scan_data->num_ssids);
1667 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1669 if (!scan_data->freqs) {
1670 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1671 if (!scan_data->freqs) {
1672 g_slist_free_full(scan_data->ssids, g_free);
1676 scan_data->num_freqs = 1;
1677 scan_data->freqs[0] = freq;
1679 bool duplicate = false;
1681 /* Don't add duplicate entries */
1682 for (i = 0; i < scan_data->num_freqs; i++) {
1683 if (scan_data->freqs[i] == freq) {
1690 scan_data->num_freqs++;
1691 scan_data->freqs = g_try_realloc(scan_data->freqs,
1692 sizeof(uint16_t) * scan_data->num_freqs);
1693 if (!scan_data->freqs) {
1694 g_slist_free_full(scan_data->ssids, g_free);
1697 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1704 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1706 struct connman_config_entry **entries;
1712 int num_ssids = 0, add_param_failed = 0;
1714 services = connman_storage_get_services();
1715 for (i = 0; services && services[i]; i++) {
1716 if (strncmp(services[i], "wifi_", 5) != 0)
1719 keyfile = connman_storage_load_service(services[i]);
1723 value = g_key_file_get_boolean(keyfile,
1724 services[i], "Hidden", NULL);
1726 g_key_file_free(keyfile);
1730 value = g_key_file_get_boolean(keyfile,
1731 services[i], "Favorite", NULL);
1733 g_key_file_free(keyfile);
1737 #if defined TIZEN_EXT
1738 value = g_key_file_get_boolean(keyfile,
1739 services[i], "AutoConnect", NULL);
1741 g_key_file_free(keyfile);
1746 ssid = g_key_file_get_string(keyfile,
1747 services[i], "SSID", NULL);
1749 name = g_key_file_get_string(keyfile, services[i], "Name",
1752 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1760 g_key_file_free(keyfile);
1764 * Check if there are any hidden AP that needs to be provisioned.
1766 entries = connman_config_get_entries("wifi");
1767 for (i = 0; entries && entries[i]; i++) {
1770 if (!entries[i]->hidden)
1773 if (!entries[i]->ssid) {
1774 ssid = entries[i]->name;
1777 ssid = entries[i]->ssid;
1778 len = entries[i]->ssid_len;
1784 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1791 connman_config_free_entries(entries);
1793 if (add_param_failed > 0)
1794 DBG("Unable to scan %d out of %d SSIDs",
1795 add_param_failed, num_ssids);
1797 g_strfreev(services);
1802 static int get_hidden_connections_params(struct wifi_data *wifi,
1803 GSupplicantScanParams *scan_params)
1805 int driver_max_ssids, i;
1806 GSupplicantScanParams *orig_params;
1809 * Scan hidden networks so that we can autoconnect to them.
1810 * We will assume 1 as a default number of ssid to scan.
1812 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1814 if (driver_max_ssids == 0)
1815 driver_max_ssids = 1;
1817 DBG("max ssids %d", driver_max_ssids);
1819 if (!wifi->scan_params) {
1820 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1821 if (!wifi->scan_params)
1824 if (get_hidden_connections(wifi->scan_params) == 0) {
1825 g_supplicant_free_scan_params(wifi->scan_params);
1826 wifi->scan_params = NULL;
1832 orig_params = wifi->scan_params;
1834 /* Let's transfer driver_max_ssids params */
1835 for (i = 0; i < driver_max_ssids; i++) {
1836 struct scan_ssid *ssid;
1838 if (!wifi->scan_params->ssids)
1841 ssid = orig_params->ssids->data;
1842 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1843 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1847 scan_params->num_ssids = i;
1848 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1850 scan_params->freqs = g_memdup(orig_params->freqs,
1851 sizeof(uint16_t) * orig_params->num_freqs);
1852 if (!scan_params->freqs)
1855 scan_params->num_freqs = orig_params->num_freqs;
1860 orig_params->num_ssids -= scan_params->num_ssids;
1862 return scan_params->num_ssids;
1865 g_slist_free_full(scan_params->ssids, g_free);
1866 g_supplicant_free_scan_params(wifi->scan_params);
1867 wifi->scan_params = NULL;
1872 static int throw_wifi_scan(struct connman_device *device,
1873 GSupplicantInterfaceCallback callback)
1875 struct wifi_data *wifi = connman_device_get_data(device);
1881 DBG("device %p %p", device, wifi->interface);
1883 if (wifi->tethering)
1885 #if defined TIZEN_EXT
1886 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1888 if (connman_device_get_scanning(device))
1892 connman_device_ref(device);
1894 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1897 connman_device_set_scanning(device,
1898 CONNMAN_SERVICE_TYPE_WIFI, true);
1900 connman_device_unref(device);
1905 static void hidden_free(struct hidden_params *hidden)
1910 if (hidden->scan_params)
1911 g_supplicant_free_scan_params(hidden->scan_params);
1912 g_free(hidden->identity);
1913 g_free(hidden->passphrase);
1914 g_free(hidden->security);
1918 #if defined TIZEN_EXT
1919 static void service_state_changed(struct connman_service *service,
1920 enum connman_service_state state);
1922 static int network_connect(struct connman_network *network);
1924 static struct connman_notifier notifier = {
1926 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1927 .service_state_changed = service_state_changed,
1930 static void service_state_changed(struct connman_service *service,
1931 enum connman_service_state state)
1933 enum connman_service_type type;
1935 type = connman_service_get_type(service);
1936 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1939 DBG("service %p state %d", service, state);
1942 case CONNMAN_SERVICE_STATE_READY:
1943 case CONNMAN_SERVICE_STATE_ONLINE:
1944 case CONNMAN_SERVICE_STATE_FAILURE:
1945 connman_notifier_unregister(¬ifier);
1946 is_wifi_notifier_registered = FALSE;
1948 __connman_device_request_scan(type);
1957 static void scan_callback(int result, GSupplicantInterface *interface,
1960 struct connman_device *device = user_data;
1961 struct wifi_data *wifi = connman_device_get_data(device);
1964 DBG("result %d wifi %p", result, wifi);
1967 if (wifi->hidden && !wifi->postpone_hidden) {
1968 connman_network_clear_hidden(wifi->hidden->user_data);
1969 hidden_free(wifi->hidden);
1970 wifi->hidden = NULL;
1973 if (wifi->scan_params) {
1974 g_supplicant_free_scan_params(wifi->scan_params);
1975 wifi->scan_params = NULL;
1980 connman_device_reset_scanning(device);
1982 /* User is connecting to a hidden AP, let's wait for finished event */
1983 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1984 GSupplicantScanParams *scan_params;
1987 wifi->postpone_hidden = false;
1988 scan_params = wifi->hidden->scan_params;
1989 wifi->hidden->scan_params = NULL;
1991 reset_autoscan(device);
1993 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1994 scan_callback, device);
1998 /* On error, let's recall scan_callback, which will cleanup */
1999 return scan_callback(ret, interface, user_data);
2002 #if defined TIZEN_EXT
2003 if (wifi && wifi->allow_full_scan) {
2005 DBG("Trigger Full Channel Scan");
2006 wifi->allow_full_scan = FALSE;
2008 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2009 scan_callback, device);
2013 /* On error, let's recall scan_callback, which will cleanup */
2014 return scan_callback(ret, interface, user_data);
2018 scanning = connman_device_get_scanning(device);
2020 connman_device_set_scanning(device,
2021 CONNMAN_SERVICE_TYPE_WIFI, false);
2023 if (result != -ENOLINK)
2024 #if defined TIZEN_EXT
2027 start_autoscan(device);
2030 * If we are here then we were scanning; however, if we are
2031 * also mid-flight disabling the interface, then wifi_disable
2032 * has already cleared the device scanning state and
2033 * unreferenced the device, obviating the need to do it here.
2037 connman_device_unref(device);
2039 #if defined TIZEN_EXT
2040 if (wifi && wifi->scan_pending_network && result != -EIO) {
2041 network_connect(wifi->scan_pending_network);
2042 wifi->scan_pending_network = NULL;
2043 connman_network_set_connecting(wifi->network);
2046 if (is_wifi_notifier_registered != true &&
2047 wifi_first_scan == true && found_with_first_scan == true) {
2048 wifi_first_scan = false;
2049 found_with_first_scan = false;
2051 connman_notifier_register(¬ifier);
2052 is_wifi_notifier_registered = true;
2057 static void scan_callback_hidden(int result,
2058 GSupplicantInterface *interface, void *user_data)
2060 struct connman_device *device = user_data;
2061 struct wifi_data *wifi = connman_device_get_data(device);
2062 GSupplicantScanParams *scan_params;
2065 DBG("result %d wifi %p", result, wifi);
2070 /* User is trying to connect to a hidden AP */
2071 if (wifi->hidden && wifi->postpone_hidden)
2074 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2078 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2079 ret = g_supplicant_interface_scan(wifi->interface,
2081 scan_callback_hidden,
2087 g_supplicant_free_scan_params(scan_params);
2090 scan_callback(result, interface, user_data);
2093 static gboolean autoscan_timeout(gpointer data)
2095 struct connman_device *device = data;
2096 struct wifi_data *wifi = connman_device_get_data(device);
2097 struct autoscan_params *autoscan;
2103 autoscan = wifi->autoscan;
2105 if (autoscan->interval <= 0) {
2106 interval = autoscan->base;
2109 interval = autoscan->interval * autoscan->base;
2111 #if defined TIZEN_EXT
2112 if (autoscan->interval >= autoscan->limit)
2114 if (interval > autoscan->limit)
2116 interval = autoscan->limit;
2118 throw_wifi_scan(wifi->device, scan_callback_hidden);
2121 DBG("interval %d", interval);
2123 autoscan->interval = interval;
2125 autoscan->timeout = g_timeout_add_seconds(interval,
2126 autoscan_timeout, device);
2131 static void start_autoscan(struct connman_device *device)
2133 struct wifi_data *wifi = connman_device_get_data(device);
2134 struct autoscan_params *autoscan;
2141 if (wifi->p2p_device)
2144 if (wifi->connected)
2147 autoscan = wifi->autoscan;
2151 if (autoscan->timeout > 0 || autoscan->interval > 0)
2154 connman_device_ref(device);
2156 autoscan_timeout(device);
2159 static struct autoscan_params *parse_autoscan_params(const char *params)
2161 struct autoscan_params *autoscan;
2166 DBG("Emulating autoscan");
2168 list_params = g_strsplit(params, ":", 0);
2169 if (list_params == 0)
2172 if (g_strv_length(list_params) < 3) {
2173 g_strfreev(list_params);
2177 base = atoi(list_params[1]);
2178 limit = atoi(list_params[2]);
2180 g_strfreev(list_params);
2182 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2184 DBG("Could not allocate memory for autoscan");
2188 DBG("base %d - limit %d", base, limit);
2189 autoscan->base = base;
2190 autoscan->limit = limit;
2195 static void setup_autoscan(struct wifi_data *wifi)
2197 if (!wifi->autoscan)
2198 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2200 start_autoscan(wifi->device);
2203 static void finalize_interface_creation(struct wifi_data *wifi)
2205 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2207 if (!wifi->device) {
2208 connman_error("WiFi device not set");
2212 connman_device_set_powered(wifi->device, true);
2214 if (!connman_setting_get_bool("BackgroundScanning"))
2217 if (wifi->p2p_device)
2220 setup_autoscan(wifi);
2223 static void interface_create_callback(int result,
2224 GSupplicantInterface *interface,
2227 struct wifi_data *wifi = user_data;
2229 DBG("result %d ifname %s, wifi %p", result,
2230 g_supplicant_interface_get_ifname(interface),
2233 if (result < 0 || !wifi)
2236 wifi->interface = interface;
2237 g_supplicant_interface_set_data(interface, wifi);
2239 if (g_supplicant_interface_get_ready(interface)) {
2240 wifi->interface_ready = true;
2241 finalize_interface_creation(wifi);
2245 static int wifi_enable(struct connman_device *device)
2247 struct wifi_data *wifi = connman_device_get_data(device);
2250 const char *driver = connman_option_get_string("wifi");
2253 DBG("device %p %p", device, wifi);
2255 index = connman_device_get_index(device);
2256 if (!wifi || index < 0)
2259 if (is_p2p_connecting())
2260 return -EINPROGRESS;
2262 interface = connman_inet_ifname(index);
2263 ret = g_supplicant_interface_create(interface, driver, NULL,
2264 interface_create_callback,
2271 return -EINPROGRESS;
2274 static int wifi_disable(struct connman_device *device)
2276 struct wifi_data *wifi = connman_device_get_data(device);
2279 DBG("device %p wifi %p", device, wifi);
2284 wifi->connected = false;
2285 wifi->disconnecting = false;
2287 if (wifi->pending_network)
2288 wifi->pending_network = NULL;
2290 stop_autoscan(device);
2292 if (wifi->p2p_find_timeout) {
2293 g_source_remove(wifi->p2p_find_timeout);
2294 wifi->p2p_find_timeout = 0;
2295 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2296 connman_device_unref(wifi->device);
2299 #if defined TIZEN_EXT
2300 if (wifi->automaxspeed_timeout != 0) {
2301 g_source_remove(wifi->automaxspeed_timeout);
2302 wifi->automaxspeed_timeout = 0;
2306 /* In case of a user scan, device is still referenced */
2307 if (connman_device_get_scanning(device)) {
2308 connman_device_set_scanning(device,
2309 CONNMAN_SERVICE_TYPE_WIFI, false);
2310 connman_device_unref(wifi->device);
2313 remove_networks(device, wifi);
2316 #if defined TIZEN_EXT
2317 wifi->scan_pending_network = NULL;
2319 if (is_wifi_notifier_registered == true) {
2320 connman_notifier_unregister(¬ifier);
2321 is_wifi_notifier_registered = false;
2325 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2329 return -EINPROGRESS;
2332 struct last_connected {
2338 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
2340 GTimeVal *aval = (GTimeVal *)a;
2341 GTimeVal *bval = (GTimeVal *)b;
2343 /* Note that the sort order is descending */
2344 if (aval->tv_sec < bval->tv_sec)
2347 if (aval->tv_sec > bval->tv_sec)
2353 static void free_entry(gpointer data)
2355 struct last_connected *entry = data;
2357 g_free(entry->ssid);
2361 static int get_latest_connections(int max_ssids,
2362 GSupplicantScanParams *scan_data)
2364 GSequenceIter *iter;
2365 GSequence *latest_list;
2366 struct last_connected *entry;
2375 latest_list = g_sequence_new(free_entry);
2379 services = connman_storage_get_services();
2380 for (i = 0; services && services[i]; i++) {
2381 if (strncmp(services[i], "wifi_", 5) != 0)
2384 keyfile = connman_storage_load_service(services[i]);
2388 str = g_key_file_get_string(keyfile,
2389 services[i], "Favorite", NULL);
2390 if (!str || g_strcmp0(str, "true")) {
2392 g_key_file_free(keyfile);
2397 str = g_key_file_get_string(keyfile,
2398 services[i], "AutoConnect", NULL);
2399 if (!str || g_strcmp0(str, "true")) {
2401 g_key_file_free(keyfile);
2406 str = g_key_file_get_string(keyfile,
2407 services[i], "Modified", NULL);
2409 g_key_file_free(keyfile);
2412 g_time_val_from_iso8601(str, &modified);
2415 ssid = g_key_file_get_string(keyfile,
2416 services[i], "SSID", NULL);
2418 freq = g_key_file_get_integer(keyfile, services[i],
2421 entry = g_try_new(struct last_connected, 1);
2423 g_sequence_free(latest_list);
2424 g_key_file_free(keyfile);
2430 entry->modified = modified;
2433 g_sequence_insert_sorted(latest_list, entry,
2439 g_key_file_free(keyfile);
2442 g_strfreev(services);
2444 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2446 iter = g_sequence_get_begin_iter(latest_list);
2448 for (i = 0; i < num_ssids; i++) {
2449 entry = g_sequence_get(iter);
2451 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2452 entry->modified.tv_sec);
2454 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2455 max_ssids, entry->ssid);
2457 iter = g_sequence_iter_next(iter);
2460 g_sequence_free(latest_list);
2464 static int wifi_scan_simple(struct connman_device *device)
2466 reset_autoscan(device);
2468 return throw_wifi_scan(device, scan_callback_hidden);
2471 static gboolean p2p_find_stop(gpointer data)
2473 struct connman_device *device = data;
2474 struct wifi_data *wifi = connman_device_get_data(device);
2479 wifi->p2p_find_timeout = 0;
2481 g_supplicant_interface_p2p_stop_find(wifi->interface);
2484 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2486 connman_device_unref(device);
2487 reset_autoscan(device);
2492 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2495 struct connman_device *device = user_data;
2496 struct wifi_data *wifi = connman_device_get_data(device);
2498 DBG("result %d wifi %p", result, wifi);
2503 if (wifi->p2p_find_timeout) {
2504 g_source_remove(wifi->p2p_find_timeout);
2505 wifi->p2p_find_timeout = 0;
2511 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2512 p2p_find_stop, device);
2513 if (!wifi->p2p_find_timeout)
2518 p2p_find_stop(device);
2521 static int p2p_find(struct connman_device *device)
2523 struct wifi_data *wifi;
2528 if (!p2p_technology)
2531 wifi = connman_device_get_data(device);
2533 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2536 reset_autoscan(device);
2537 connman_device_ref(device);
2539 ret = g_supplicant_interface_p2p_find(wifi->interface,
2540 p2p_find_callback, device);
2542 connman_device_unref(device);
2543 start_autoscan(device);
2545 connman_device_set_scanning(device,
2546 CONNMAN_SERVICE_TYPE_P2P, true);
2552 #if defined TIZEN_EXT
2553 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2556 struct connman_device *device = user_data;
2557 struct wifi_data *wifi = connman_device_get_data(device);
2560 DBG("result %d wifi %p", result, wifi);
2562 if (wifi && wifi->scan_params) {
2563 g_supplicant_free_scan_params(wifi->scan_params);
2564 wifi->scan_params = NULL;
2567 scanning = connman_device_get_scanning(device);
2569 connman_device_set_scanning(device,
2570 CONNMAN_SERVICE_TYPE_WIFI, false);
2571 connman_device_unref(device);
2575 static int wifi_specific_scan(enum connman_service_type type,
2576 struct connman_device *device, int scan_type,
2577 GSList *specific_scan_list, void *user_data)
2579 GSList *list = NULL;
2581 struct wifi_data *wifi = connman_device_get_data(device);
2582 GSupplicantScanParams *scan_params = NULL;
2583 struct scan_ssid *scan_ssid = NULL;
2592 if (wifi->p2p_device)
2595 if (type == CONNMAN_SERVICE_TYPE_P2P)
2596 return p2p_find(device);
2598 if (wifi->tethering)
2601 scanning = connman_device_get_scanning(device);
2605 DBG("scan_type: %d", scan_type);
2606 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2607 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2609 DBG("Failed to allocate memory.");
2613 for (list = specific_scan_list; list; list = list->next) {
2614 ssid = (char *)list->data;
2615 int ssid_len = strlen(ssid);
2617 scan_ssid = g_try_new0(struct scan_ssid, 1);
2619 DBG("Failed to allocate memory.");
2620 g_supplicant_free_scan_params(scan_params);
2624 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2625 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2626 scan_ssid->ssid_len = ssid_len;
2627 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2630 scan_params->num_ssids = count;
2632 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2634 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2636 DBG("Failed to allocate memory.");
2640 guint num_freqs = g_slist_length(specific_scan_list);
2641 DBG("num_freqs: %d", num_freqs);
2643 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2644 if (!scan_params->freqs) {
2645 DBG("Failed to allocate memory.");
2646 g_free(scan_params);
2651 for (list = specific_scan_list; list; list = list->next) {
2652 freq = (int)list->data;
2654 scan_params->freqs[count] = freq;
2655 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2658 scan_params->num_freqs = count;
2660 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2661 int freq_count, ap_count;
2662 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2664 DBG("Failed to allocate memory.");
2668 guint size = g_slist_length(specific_scan_list);
2670 scan_params->freqs = g_try_new0(uint16_t, size/2);
2671 if (!scan_params->freqs) {
2672 DBG("Failed to allocate memory.");
2673 g_free(scan_params);
2677 ap_count = freq_count = 0;
2678 for (list = specific_scan_list; list; list = list->next) {
2679 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2680 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2681 int ssid_len = strlen(ssid);
2683 scan_ssid = g_try_new0(struct scan_ssid, 1);
2685 DBG("Failed to allocate memory.");
2686 g_supplicant_free_scan_params(scan_params);
2690 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2691 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2692 scan_ssid->ssid_len = ssid_len;
2693 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2697 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2698 scan_params->freqs[freq_count] = freq;
2699 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2703 scan_params->num_ssids = ap_count;
2704 scan_params->num_freqs = freq_count;
2706 DBG("Invalid scan");
2710 reset_autoscan(device);
2711 connman_device_ref(device);
2713 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2714 specific_scan_callback, device);
2717 connman_device_set_scanning(device,
2718 CONNMAN_SERVICE_TYPE_WIFI, true);
2720 g_supplicant_free_scan_params(scan_params);
2721 connman_device_unref(device);
2728 #if defined TIZEN_EXT_WIFI_MESH
2729 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2732 struct connman_device *device = user_data;
2733 struct wifi_data *wifi = connman_device_get_data(device);
2736 DBG("result %d wifi %p", result, wifi);
2738 scanning = connman_device_get_scanning(device);
2740 connman_device_set_scanning(device,
2741 CONNMAN_SERVICE_TYPE_MESH, false);
2744 connman_device_unref(device);
2747 static int mesh_scan(struct connman_device *device)
2749 struct wifi_data *wifi;
2750 struct wifi_mesh_info *mesh_info;
2755 wifi = connman_device_get_data(device);
2757 if (!wifi->mesh_interface)
2760 mesh_info = wifi->mesh_info;
2761 reset_autoscan(device);
2762 connman_device_ref(device);
2764 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2765 mesh_scan_callback, device);
2767 connman_device_unref(device);
2769 connman_device_set_scanning(device,
2770 CONNMAN_SERVICE_TYPE_MESH, true);
2775 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2778 struct connman_device *device = user_data;
2779 struct wifi_data *wifi = connman_device_get_data(device);
2781 DBG("result %d wifi %p", result, wifi);
2783 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2786 static int mesh_abort_scan(enum connman_service_type type,
2787 struct connman_device *device)
2789 struct wifi_data *wifi = connman_device_get_data(device);
2790 struct wifi_mesh_info *mesh_info;
2794 if (!wifi || !wifi->mesh_interface)
2797 if (type != CONNMAN_SERVICE_TYPE_MESH)
2800 mesh_info = wifi->mesh_info;
2802 scanning = connman_device_get_scanning(device);
2806 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2807 abort_scan_callback, device);
2812 static int mesh_specific_scan(enum connman_service_type type,
2813 struct connman_device *device, const char *ssid,
2814 unsigned int freq, void *user_data)
2816 struct wifi_data *wifi = connman_device_get_data(device);
2817 GSupplicantScanParams *scan_params = NULL;
2818 struct wifi_mesh_info *mesh_info;
2819 struct scan_ssid *scan_ssid;
2823 if (!wifi || !wifi->mesh_interface)
2826 if (type != CONNMAN_SERVICE_TYPE_MESH)
2829 if (wifi->p2p_device)
2832 mesh_info = wifi->mesh_info;
2834 scanning = connman_device_get_scanning(device);
2838 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2842 scan_ssid = g_try_new(struct scan_ssid, 1);
2844 g_free(scan_params);
2848 scan_ssid->ssid_len = strlen(ssid);
2849 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2850 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2851 scan_params->num_ssids = 1;
2853 scan_params->freqs = g_try_new(uint16_t, 1);
2854 if (!scan_params->freqs) {
2855 g_slist_free_full(scan_params->ssids, g_free);
2856 g_free(scan_params);
2860 scan_params->freqs[0] = freq;
2861 scan_params->num_freqs = 1;
2863 reset_autoscan(device);
2864 connman_device_ref(device);
2866 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2867 mesh_scan_callback, device);
2870 connman_device_set_scanning(device,
2871 CONNMAN_SERVICE_TYPE_MESH, true);
2873 g_supplicant_free_scan_params(scan_params);
2874 connman_device_unref(device);
2882 * Note that the hidden scan is only used when connecting to this specific
2883 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2885 static int wifi_scan(enum connman_service_type type,
2886 struct connman_device *device,
2887 const char *ssid, unsigned int ssid_len,
2888 const char *identity, const char* passphrase,
2889 const char *security, void *user_data)
2891 struct wifi_data *wifi = connman_device_get_data(device);
2892 GSupplicantScanParams *scan_params = NULL;
2893 struct scan_ssid *scan_ssid;
2894 struct hidden_params *hidden;
2896 int driver_max_ssids = 0;
2903 if (wifi->p2p_device)
2906 if (wifi->tethering)
2909 if (type == CONNMAN_SERVICE_TYPE_P2P)
2910 return p2p_find(device);
2912 #if defined TIZEN_EXT_WIFI_MESH
2913 if (type == CONNMAN_SERVICE_TYPE_MESH)
2914 return mesh_scan(device);
2917 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2919 scanning = connman_device_get_scanning(device);
2921 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2925 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2927 DBG("max ssids %d", driver_max_ssids);
2928 if (driver_max_ssids == 0)
2929 return wifi_scan_simple(device);
2933 if (scanning && wifi->hidden && wifi->postpone_hidden)
2939 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2944 scan_ssid = g_try_new(struct scan_ssid, 1);
2946 g_free(scan_params);
2950 memcpy(scan_ssid->ssid, ssid, ssid_len);
2951 scan_ssid->ssid_len = ssid_len;
2952 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2954 scan_params->num_ssids = 1;
2956 hidden = g_try_new0(struct hidden_params, 1);
2958 g_supplicant_free_scan_params(scan_params);
2963 hidden_free(wifi->hidden);
2964 wifi->hidden = NULL;
2967 memcpy(hidden->ssid, ssid, ssid_len);
2968 hidden->ssid_len = ssid_len;
2969 hidden->identity = g_strdup(identity);
2970 hidden->passphrase = g_strdup(passphrase);
2971 hidden->security = g_strdup(security);
2972 hidden->user_data = user_data;
2973 wifi->hidden = hidden;
2976 /* Let's keep this active scan for later,
2977 * when current scan will be over. */
2978 wifi->postpone_hidden = TRUE;
2979 hidden->scan_params = scan_params;
2983 } else if (wifi->connected) {
2984 g_supplicant_free_scan_params(scan_params);
2985 return wifi_scan_simple(device);
2987 ret = get_latest_connections(driver_max_ssids, scan_params);
2989 g_supplicant_free_scan_params(scan_params);
2990 return wifi_scan_simple(device);
2994 connman_device_ref(device);
2996 reset_autoscan(device);
2998 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2999 scan_callback, device);
3002 connman_device_set_scanning(device,
3003 CONNMAN_SERVICE_TYPE_WIFI, true);
3004 #if defined TIZEN_EXT
3005 /*To allow the Full Scan after ssid based scan, set the flag here
3006 It is required because Tizen does not use the ConnMan specific
3007 backgroung Scan feature.Tizen has added the BG Scan feature in
3008 net-config. To sync with up ConnMan, we need to issue the Full Scan
3009 after SSID specific scan.*/
3010 wifi->allow_full_scan = TRUE;
3013 g_supplicant_free_scan_params(scan_params);
3014 connman_device_unref(device);
3017 hidden_free(wifi->hidden);
3018 wifi->hidden = NULL;
3025 static void wifi_regdom_callback(int result,
3029 struct connman_device *device = user_data;
3031 connman_device_regdom_notify(device, result, alpha2);
3033 connman_device_unref(device);
3036 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3038 struct wifi_data *wifi = connman_device_get_data(device);
3044 connman_device_ref(device);
3046 ret = g_supplicant_interface_set_country(wifi->interface,
3047 wifi_regdom_callback,
3050 connman_device_unref(device);
3055 static struct connman_device_driver wifi_ng_driver = {
3057 .type = CONNMAN_DEVICE_TYPE_WIFI,
3058 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3059 .probe = wifi_probe,
3060 .remove = wifi_remove,
3061 .enable = wifi_enable,
3062 .disable = wifi_disable,
3064 .set_regdom = wifi_set_regdom,
3065 #if defined TIZEN_EXT
3066 .specific_scan = wifi_specific_scan,
3068 #if defined TIZEN_EXT_WIFI_MESH
3069 .abort_scan = mesh_abort_scan,
3070 .mesh_specific_scan = mesh_specific_scan,
3074 static void system_ready(void)
3078 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3079 connman_error("Failed to register WiFi driver");
3082 static void system_killed(void)
3086 connman_device_driver_unregister(&wifi_ng_driver);
3089 static int network_probe(struct connman_network *network)
3091 DBG("network %p", network);
3096 static void network_remove(struct connman_network *network)
3098 struct connman_device *device = connman_network_get_device(network);
3099 struct wifi_data *wifi;
3101 DBG("network %p", network);
3103 wifi = connman_device_get_data(device);
3107 if (wifi->network != network)
3110 wifi->network = NULL;
3112 #if defined TIZEN_EXT
3113 wifi->disconnecting = false;
3115 if (wifi->pending_network == network)
3116 wifi->pending_network = NULL;
3118 if (wifi->scan_pending_network == network)
3119 wifi->scan_pending_network = NULL;
3123 static void connect_callback(int result, GSupplicantInterface *interface,
3126 #if defined TIZEN_EXT
3128 struct wifi_data *wifi;
3130 struct connman_network *network = user_data;
3132 DBG("network %p result %d", network, result);
3134 #if defined TIZEN_EXT
3135 set_connman_bssid(RESET_BSSID, NULL);
3137 for (list = iface_list; list; list = list->next) {
3140 if (wifi && wifi->network == network)
3144 /* wifi_data may be invalid because wifi is already disabled */
3149 if (result == -ENOKEY) {
3150 connman_network_set_error(network,
3151 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3152 } else if (result < 0) {
3153 connman_network_set_error(network,
3154 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3157 connman_network_unref(network);
3160 static GSupplicantSecurity network_security(const char *security)
3162 if (g_str_equal(security, "none"))
3163 return G_SUPPLICANT_SECURITY_NONE;
3164 else if (g_str_equal(security, "wep"))
3165 return G_SUPPLICANT_SECURITY_WEP;
3166 else if (g_str_equal(security, "psk"))
3167 return G_SUPPLICANT_SECURITY_PSK;
3168 else if (g_str_equal(security, "wpa"))
3169 return G_SUPPLICANT_SECURITY_PSK;
3170 else if (g_str_equal(security, "rsn"))
3171 return G_SUPPLICANT_SECURITY_PSK;
3172 else if (g_str_equal(security, "ieee8021x"))
3173 return G_SUPPLICANT_SECURITY_IEEE8021X;
3174 #if defined TIZEN_EXT
3175 else if (g_str_equal(security, "ft_psk") == TRUE)
3176 return G_SUPPLICANT_SECURITY_FT_PSK;
3177 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3178 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3181 return G_SUPPLICANT_SECURITY_UNKNOWN;
3184 #if defined TIZEN_EXT
3185 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3187 if (security == NULL)
3188 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3190 if (g_str_equal(security, "FT") == TRUE)
3191 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3192 else if (g_str_equal(security, "CCKM") == TRUE)
3193 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3195 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3199 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3201 const char *security;
3202 #if defined TIZEN_EXT
3203 const void *ssid_data;
3206 memset(ssid, 0, sizeof(*ssid));
3207 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3208 #if defined TIZEN_EXT
3209 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3211 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3216 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3218 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3221 ssid->scan_ssid = 1;
3222 security = connman_network_get_string(network, "WiFi.Security");
3223 ssid->security = network_security(security);
3224 ssid->passphrase = connman_network_get_string(network,
3226 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3229 * If our private key password is unset,
3230 * we use the supplied passphrase. That is needed
3231 * for PEAP where 2 passphrases (identity and client
3232 * cert may have to be provided.
3234 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3235 connman_network_set_string(network,
3236 "WiFi.PrivateKeyPassphrase",
3238 /* We must have an identity for both PEAP and TLS */
3239 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3241 /* Use agent provided identity as a fallback */
3242 if (!ssid->identity || strlen(ssid->identity) == 0)
3243 ssid->identity = connman_network_get_string(network,
3244 "WiFi.AgentIdentity");
3246 ssid->anonymous_identity = connman_network_get_string(network,
3247 "WiFi.AnonymousIdentity");
3248 ssid->ca_cert_path = connman_network_get_string(network,
3250 ssid->subject_match = connman_network_get_string(network,
3251 "WiFi.SubjectMatch");
3252 ssid->altsubject_match = connman_network_get_string(network,
3253 "WiFi.AltSubjectMatch");
3254 ssid->domain_suffix_match = connman_network_get_string(network,
3255 "WiFi.DomainSuffixMatch");
3256 ssid->domain_match = connman_network_get_string(network,
3257 "WiFi.DomainMatch");
3258 ssid->client_cert_path = connman_network_get_string(network,
3259 "WiFi.ClientCertFile");
3260 ssid->private_key_path = connman_network_get_string(network,
3261 "WiFi.PrivateKeyFile");
3262 ssid->private_key_passphrase = connman_network_get_string(network,
3263 "WiFi.PrivateKeyPassphrase");
3264 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3266 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3267 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3269 #if defined TIZEN_EXT
3270 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3271 ssid->bssid_for_connect_len = 6;
3272 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3273 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3274 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3275 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3276 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3278 ssid->freq = connman_network_get_frequency(network);
3281 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3282 if (bssid_list && g_slist_length(bssid_list) > 1) {
3284 /* If there are more than one bssid,
3285 * the user-specified bssid is tried only once at the beginning.
3286 * After that, the bssids in the list are tried in order.
3288 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3289 set_connman_bssid(RESET_BSSID, NULL);
3294 char buff[MAC_ADDRESS_LENGTH];
3295 for (list = bssid_list; list; list = list->next) {
3296 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3298 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3299 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3300 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3301 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3303 gchar *curr_bssid = g_strdup((const gchar *)buff);
3305 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3306 DBG("bssid match, try next bssid");
3310 g_hash_table_add(failed_bssids, curr_bssid);
3312 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3313 ssid->bssid = buff_bssid;
3314 ssid->freq = (unsigned int)bssids->frequency;
3320 ssid->bssid = connman_network_get_bssid(network);
3321 g_hash_table_remove_all(failed_bssids);
3324 ssid->bssid = connman_network_get_bssid(network);
3327 ssid->eap_keymgmt = network_eap_keymgmt(
3328 connman_network_get_string(network, "WiFi.KeymgmtType"));
3329 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3331 if(g_strcmp0(ssid->eap, "fast") == 0)
3332 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3335 if (connman_setting_get_bool("BackgroundScanning"))
3336 ssid->bgscan = BGSCAN_DEFAULT;
3339 static int network_connect(struct connman_network *network)
3341 struct connman_device *device = connman_network_get_device(network);
3342 struct wifi_data *wifi;
3343 GSupplicantInterface *interface;
3344 GSupplicantSSID *ssid;
3346 DBG("network %p", network);
3351 wifi = connman_device_get_data(device);
3355 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3359 interface = wifi->interface;
3361 ssid_init(ssid, network);
3363 if (wifi->disconnecting) {
3364 wifi->pending_network = network;
3365 #if defined TIZEN_EXT
3370 wifi->network = connman_network_ref(network);
3372 #if defined TIZEN_EXT
3373 wifi->scan_pending_network = NULL;
3376 return g_supplicant_interface_connect(interface, ssid,
3377 connect_callback, network);
3380 return -EINPROGRESS;
3383 static void disconnect_callback(int result, GSupplicantInterface *interface,
3386 #if defined TIZEN_EXT
3388 struct wifi_data *wifi;
3389 struct connman_network *network = user_data;
3391 DBG("network %p result %d", network, result);
3393 for (list = iface_list; list; list = list->next) {
3396 if (wifi->network == NULL && wifi->disconnecting == true)
3397 wifi->disconnecting = false;
3399 if (wifi->network == network)
3403 /* wifi_data may be invalid because wifi is already disabled */
3408 struct wifi_data *wifi = user_data;
3411 DBG("result %d supplicant interface %p wifi %p",
3412 result, interface, wifi);
3414 if (result == -ECONNABORTED) {
3415 DBG("wifi interface no longer available");
3419 if (wifi->network) {
3420 connman_network_set_connected(wifi->network, false);
3421 wifi->network = NULL;
3424 wifi->disconnecting = false;
3425 wifi->connected = false;
3427 if (wifi->pending_network) {
3428 network_connect(wifi->pending_network);
3429 wifi->pending_network = NULL;
3432 start_autoscan(wifi->device);
3435 static int network_disconnect(struct connman_network *network)
3437 struct connman_device *device = connman_network_get_device(network);
3438 struct wifi_data *wifi;
3440 #if defined TIZEN_EXT
3441 struct connman_service *service;
3444 DBG("network %p", network);
3446 wifi = connman_device_get_data(device);
3447 if (!wifi || !wifi->interface)
3450 #if defined TIZEN_EXT
3451 if (connman_network_get_associating(network) == true) {
3452 connman_network_clear_associating(network);
3453 connman_network_set_bool(network, "WiFi.UseWPS", false);
3455 service = connman_service_lookup_from_network(network);
3457 if (service != NULL &&
3458 (__connman_service_is_connected_state(service,
3459 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3460 __connman_service_is_connected_state(service,
3461 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3462 (connman_service_get_favorite(service) == false))
3463 __connman_service_set_passphrase(service, NULL);
3466 if (wifi->pending_network == network)
3467 wifi->pending_network = NULL;
3469 if (wifi->scan_pending_network == network)
3470 wifi->scan_pending_network = NULL;
3473 connman_network_set_associating(network, false);
3475 if (wifi->disconnecting)
3478 wifi->disconnecting = true;
3480 #if defined TIZEN_EXT
3481 err = g_supplicant_interface_disconnect(wifi->interface,
3482 disconnect_callback, network);
3484 err = g_supplicant_interface_disconnect(wifi->interface,
3485 disconnect_callback, wifi);
3489 wifi->disconnecting = false;
3494 #if defined TIZEN_EXT
3495 static void set_connection_mode(struct connman_network *network,
3498 ieee80211_modes_e phy_mode;
3499 connection_mode_e conn_mode;
3501 phy_mode = connman_network_get_phy_mode(network);
3503 case IEEE80211_MODE_B:
3504 if (linkspeed > 0 && linkspeed <= 11)
3505 conn_mode = CONNECTION_MODE_IEEE80211B;
3507 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3510 case IEEE80211_MODE_BG:
3511 if (linkspeed > 0 && linkspeed <= 11)
3512 conn_mode = CONNECTION_MODE_IEEE80211B;
3513 else if (linkspeed > 11 && linkspeed <= 54)
3514 conn_mode = CONNECTION_MODE_IEEE80211G;
3516 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3519 case IEEE80211_MODE_BGN:
3520 if (linkspeed > 0 && linkspeed <= 11)
3521 conn_mode = CONNECTION_MODE_IEEE80211B;
3522 else if (linkspeed > 11 && linkspeed <= 54)
3523 conn_mode = CONNECTION_MODE_IEEE80211G;
3524 else if (linkspeed > 54 && linkspeed <= 450)
3525 conn_mode = CONNECTION_MODE_IEEE80211N;
3527 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3530 case IEEE80211_MODE_A:
3531 if (linkspeed > 0 && linkspeed <= 54)
3532 conn_mode = CONNECTION_MODE_IEEE80211A;
3534 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3537 case IEEE80211_MODE_AN:
3538 if (linkspeed > 0 && linkspeed <= 54)
3539 conn_mode = CONNECTION_MODE_IEEE80211A;
3540 else if (linkspeed > 54 && linkspeed <= 450)
3541 conn_mode = CONNECTION_MODE_IEEE80211N;
3543 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3546 case IEEE80211_MODE_ANAC:
3547 if (linkspeed > 0 && linkspeed <= 54)
3548 conn_mode = CONNECTION_MODE_IEEE80211A;
3549 else if (linkspeed > 54 && linkspeed <= 450)
3550 conn_mode = CONNECTION_MODE_IEEE80211N;
3551 else if (linkspeed > 450 && linkspeed <= 1300)
3552 conn_mode = CONNECTION_MODE_IEEE80211AC;
3554 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3558 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3562 DBG("connection mode(%d)", conn_mode);
3563 connman_network_set_connection_mode(network, conn_mode);
3566 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3568 struct connman_network *network = user_data;
3571 DBG("Failed to get maxspeed from signalpoll !");
3575 DBG("maxspeed = %d", maxspeed);
3577 connman_network_set_maxspeed(network, maxspeed);
3578 set_connection_mode(network, maxspeed);
3582 static int network_signalpoll(struct wifi_data *wifi)
3584 GSupplicantInterface *interface;
3585 struct connman_network *network;
3587 if (!wifi || !wifi->network)
3590 interface = wifi->interface;
3591 network = wifi->network;
3593 DBG("network %p", network);
3595 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3598 static gboolean autosignalpoll_timeout(gpointer data)
3600 struct wifi_data *wifi = data;
3602 if (!wifi || !wifi->automaxspeed_timeout) {
3603 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3607 int ret = network_signalpoll(wifi);
3609 DBG("Fail to get max speed !!");
3610 wifi->automaxspeed_timeout = 0;
3618 static struct connman_network_driver network_driver = {
3620 .type = CONNMAN_NETWORK_TYPE_WIFI,
3621 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3622 .probe = network_probe,
3623 .remove = network_remove,
3624 .connect = network_connect,
3625 .disconnect = network_disconnect,
3628 static void interface_added(GSupplicantInterface *interface)
3630 const char *ifname = g_supplicant_interface_get_ifname(interface);
3631 const char *driver = g_supplicant_interface_get_driver(interface);
3632 #if defined TIZEN_EXT
3633 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3636 struct wifi_data *wifi;
3638 wifi = g_supplicant_interface_get_data(interface);
3640 wifi = get_pending_wifi_data(ifname);
3644 wifi->interface = interface;
3645 g_supplicant_interface_set_data(interface, wifi);
3646 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3647 wifi->p2p_device = true;
3650 DBG("ifname %s driver %s wifi %p tethering %d",
3651 ifname, driver, wifi, wifi->tethering);
3653 if (!wifi->device) {
3654 connman_error("WiFi device not set");
3658 connman_device_set_powered(wifi->device, true);
3659 #if defined TIZEN_EXT
3660 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3661 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3662 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3663 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3667 static bool is_idle(struct wifi_data *wifi)
3669 DBG("state %d", wifi->state);
3671 switch (wifi->state) {
3672 case G_SUPPLICANT_STATE_UNKNOWN:
3673 case G_SUPPLICANT_STATE_DISABLED:
3674 case G_SUPPLICANT_STATE_DISCONNECTED:
3675 case G_SUPPLICANT_STATE_INACTIVE:
3676 case G_SUPPLICANT_STATE_SCANNING:
3679 case G_SUPPLICANT_STATE_AUTHENTICATING:
3680 case G_SUPPLICANT_STATE_ASSOCIATING:
3681 case G_SUPPLICANT_STATE_ASSOCIATED:
3682 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3683 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3684 case G_SUPPLICANT_STATE_COMPLETED:
3691 static bool is_idle_wps(GSupplicantInterface *interface,
3692 struct wifi_data *wifi)
3694 /* First, let's check if WPS processing did not went wrong */
3695 if (g_supplicant_interface_get_wps_state(interface) ==
3696 G_SUPPLICANT_WPS_STATE_FAIL)
3699 /* Unlike normal connection, being associated while processing wps
3700 * actually means that we are idling. */
3701 switch (wifi->state) {
3702 case G_SUPPLICANT_STATE_UNKNOWN:
3703 case G_SUPPLICANT_STATE_DISABLED:
3704 case G_SUPPLICANT_STATE_DISCONNECTED:
3705 case G_SUPPLICANT_STATE_INACTIVE:
3706 case G_SUPPLICANT_STATE_SCANNING:
3707 case G_SUPPLICANT_STATE_ASSOCIATED:
3709 case G_SUPPLICANT_STATE_AUTHENTICATING:
3710 case G_SUPPLICANT_STATE_ASSOCIATING:
3711 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3712 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3713 case G_SUPPLICANT_STATE_COMPLETED:
3720 static bool handle_wps_completion(GSupplicantInterface *interface,
3721 struct connman_network *network,
3722 struct connman_device *device,
3723 struct wifi_data *wifi)
3727 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3729 const unsigned char *ssid, *wps_ssid;
3730 unsigned int ssid_len, wps_ssid_len;
3731 const char *wps_key;
3733 /* Checking if we got associated with requested
3735 ssid = connman_network_get_blob(network, "WiFi.SSID",
3738 wps_ssid = g_supplicant_interface_get_wps_ssid(
3739 interface, &wps_ssid_len);
3741 if (!wps_ssid || wps_ssid_len != ssid_len ||
3742 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3743 connman_network_set_associating(network, false);
3744 #if defined TIZEN_EXT
3745 g_supplicant_interface_disconnect(wifi->interface,
3746 disconnect_callback, wifi->network);
3748 connman_network_set_bool(network, "WiFi.UseWPS", false);
3749 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3751 g_supplicant_interface_disconnect(wifi->interface,
3752 disconnect_callback, wifi);
3757 wps_key = g_supplicant_interface_get_wps_key(interface);
3758 #if defined TIZEN_EXT
3759 /* Check the passphrase and encrypt it
3762 gchar *passphrase = g_strdup(wps_key);
3764 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3766 if (check_passphrase_ext(network, passphrase) < 0) {
3767 DBG("[WPS] Invalid passphrase");
3772 ret = send_encryption_request(passphrase, network);
3777 DBG("[WPS] Encryption request succeeded");
3779 DBG("[WPS] Encryption request failed %d", ret);
3782 connman_network_set_string(network, "WiFi.Passphrase",
3785 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3792 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3793 struct wifi_data *wifi)
3795 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3796 #if defined TIZEN_EXT
3797 wifi->assoc_code > 0 &&
3799 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3801 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3802 wifi->load_shaping_retries ++;
3805 wifi->load_shaping_retries = 0;
3809 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3810 struct connman_network *network,
3811 struct wifi_data *wifi)
3813 #if defined TIZEN_EXT
3814 const char *security;
3815 struct connman_service *service;
3817 if (wifi->connected)
3820 security = connman_network_get_string(network, "WiFi.Security");
3822 if (security && g_str_equal(security, "ieee8021x") == true &&
3823 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3825 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3830 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3833 struct connman_service *service;
3835 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3838 if (wifi->connected)
3842 service = connman_service_lookup_from_network(network);
3848 if (connman_service_get_favorite(service)) {
3849 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3854 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3859 #if defined TIZEN_EXT
3860 static bool handle_wifi_assoc_retry(struct connman_network *network,
3861 struct wifi_data *wifi)
3863 const char *security;
3865 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3866 connman_network_get_connecting(network) != true) {
3867 wifi->assoc_retry_count = 0;
3871 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3872 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3873 wifi->assoc_retry_count = 0;
3877 security = connman_network_get_string(network, "WiFi.Security");
3878 if (security && g_str_equal(security, "ieee8021x") == true &&
3879 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3880 wifi->assoc_retry_count = 0;
3884 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3885 wifi->assoc_retry_count = 0;
3887 /* Honestly it's not an invalid-key error,
3888 * however QA team recommends that the invalid-key error
3889 * might be better to display for user experience.
3891 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3900 static void interface_state(GSupplicantInterface *interface)
3902 struct connman_network *network;
3903 struct connman_device *device;
3904 struct wifi_data *wifi;
3905 GSupplicantState state = g_supplicant_interface_get_state(interface);
3909 wifi = g_supplicant_interface_get_data(interface);
3911 DBG("wifi %p interface state %d", wifi, state);
3916 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3917 if (wifi->tethering_param) {
3918 g_free(wifi->tethering_param->ssid);
3919 g_free(wifi->tethering_param);
3920 wifi->tethering_param = NULL;
3924 device = wifi->device;
3928 if (g_supplicant_interface_get_ready(interface) &&
3929 !wifi->interface_ready) {
3930 wifi->interface_ready = true;
3931 finalize_interface_creation(wifi);
3934 network = wifi->network;
3939 case G_SUPPLICANT_STATE_SCANNING:
3940 if (wifi->connected)
3941 connman_network_set_connected(network, false);
3945 case G_SUPPLICANT_STATE_AUTHENTICATING:
3946 case G_SUPPLICANT_STATE_ASSOCIATING:
3947 #if defined TIZEN_EXT
3948 reset_autoscan(device);
3950 stop_autoscan(device);
3953 if (!wifi->connected)
3954 connman_network_set_associating(network, true);
3958 case G_SUPPLICANT_STATE_COMPLETED:
3959 #if defined TIZEN_EXT
3960 /* though it should be already reset: */
3961 reset_autoscan(device);
3963 wifi->assoc_retry_count = 0;
3965 wifi->scan_pending_network = NULL;
3967 /* should be cleared scanning flag */
3968 bool scanning = connman_device_get_scanning(device);
3970 connman_device_set_scanning(device,
3971 CONNMAN_SERVICE_TYPE_WIFI, false);
3972 connman_device_unref(device);
3975 if (!wifi->automaxspeed_timeout) {
3976 DBG("Going to start signalpoll timer!!");
3977 int ret = network_signalpoll(wifi);
3979 DBG("Fail to get max speed !!");
3981 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
3984 g_hash_table_remove_all(failed_bssids);
3986 /* though it should be already stopped: */
3987 stop_autoscan(device);
3990 if (!handle_wps_completion(interface, network, device, wifi))
3993 connman_network_set_connected(network, true);
3995 wifi->disconnect_code = 0;
3996 wifi->assoc_code = 0;
3997 wifi->load_shaping_retries = 0;
4000 case G_SUPPLICANT_STATE_DISCONNECTED:
4001 #if defined TIZEN_EXT
4002 connman_network_set_maxspeed(network, 0);
4004 if (wifi->automaxspeed_timeout != 0) {
4005 g_source_remove(wifi->automaxspeed_timeout);
4006 wifi->automaxspeed_timeout = 0;
4007 DBG("Remove signalpoll timer!!");
4011 * If we're in one of the idle modes, we have
4012 * not started association yet and thus setting
4013 * those ones to FALSE could cancel an association
4016 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4018 if (is_idle_wps(interface, wifi))
4024 #if defined TIZEN_EXT
4025 if (handle_assoc_status_code(interface, wifi)) {
4026 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4027 guint bssid_length = 0;
4030 bssid_length = g_slist_length(bssid_list);
4032 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4033 network_connect(network);
4037 wifi->load_shaping_retries = 0;
4040 g_hash_table_remove_all(failed_bssids);
4042 if (handle_assoc_status_code(interface, wifi))
4046 /* If previous state was 4way-handshake, then
4047 * it's either: psk was incorrect and thus we retry
4048 * or if we reach the maximum retries we declare the
4050 if (handle_4way_handshake_failure(interface,
4054 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4055 switch (wifi->disconnect_code) {
4056 case 1: /* Unspecified reason */
4057 /* Let's assume it's because we got blocked */
4059 case 6: /* Class 2 frame received from nonauthenticated STA */
4060 connman_network_set_error(network,
4061 CONNMAN_NETWORK_ERROR_BLOCKED);
4068 #if defined TIZEN_EXT
4069 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4070 * Retry association until its retry count is expired */
4071 if (handle_wifi_assoc_retry(network, wifi) == true) {
4072 throw_wifi_scan(wifi->device, scan_callback);
4073 wifi->scan_pending_network = wifi->network;
4077 if(wifi->disconnect_code > 0){
4078 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4079 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4083 connman_network_set_connected(network, false);
4084 connman_network_set_associating(network, false);
4085 wifi->disconnecting = false;
4087 start_autoscan(device);
4091 case G_SUPPLICANT_STATE_INACTIVE:
4092 #if defined TIZEN_EXT
4093 if (handle_wps_completion(interface, network, device, wifi) == false)
4096 connman_network_set_associating(network, false);
4097 start_autoscan(device);
4101 case G_SUPPLICANT_STATE_UNKNOWN:
4102 case G_SUPPLICANT_STATE_DISABLED:
4103 case G_SUPPLICANT_STATE_ASSOCIATED:
4104 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4105 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4109 old_connected = wifi->connected;
4110 wifi->state = state;
4112 /* Saving wpa_s state policy:
4113 * If connected and if the state changes are roaming related:
4114 * --> We stay connected
4116 * --> We are connected
4118 * --> We are not connected
4121 case G_SUPPLICANT_STATE_AUTHENTICATING:
4122 case G_SUPPLICANT_STATE_ASSOCIATING:
4123 case G_SUPPLICANT_STATE_ASSOCIATED:
4124 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4125 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4126 if (wifi->connected)
4127 connman_warn("Probably roaming right now!"
4128 " Staying connected...");
4130 case G_SUPPLICANT_STATE_SCANNING:
4131 wifi->connected = false;
4134 start_autoscan(device);
4136 case G_SUPPLICANT_STATE_COMPLETED:
4137 wifi->connected = true;
4140 wifi->connected = false;
4147 static void interface_removed(GSupplicantInterface *interface)
4149 const char *ifname = g_supplicant_interface_get_ifname(interface);
4150 struct wifi_data *wifi;
4152 DBG("ifname %s", ifname);
4154 wifi = g_supplicant_interface_get_data(interface);
4156 #if defined TIZEN_EXT_WIFI_MESH
4157 if (wifi && wifi->mesh_interface) {
4158 DBG("Notify mesh interface remove");
4159 connman_mesh_notify_interface_remove(true);
4160 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4161 g_free(mesh_info->parent_ifname);
4162 g_free(mesh_info->ifname);
4163 g_free(mesh_info->identifier);
4165 wifi->mesh_interface = false;
4166 wifi->mesh_info = NULL;
4172 wifi->interface = NULL;
4174 if (wifi && wifi->tethering)
4177 if (!wifi || !wifi->device) {
4178 DBG("wifi interface already removed");
4182 connman_device_set_powered(wifi->device, false);
4184 check_p2p_technology();
4185 #if defined TIZEN_EXT_WIFI_MESH
4186 check_mesh_technology();
4190 static void set_device_type(const char *type, char dev_type[17])
4192 const char *oui = "0050F204";
4193 const char *category = "0001";
4194 const char *sub_category = "0000";
4196 if (!g_strcmp0(type, "handset")) {
4198 sub_category = "0005";
4199 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4200 sub_category = "0001";
4201 else if (!g_strcmp0(type, "server"))
4202 sub_category = "0002";
4203 else if (!g_strcmp0(type, "laptop"))
4204 sub_category = "0005";
4205 else if (!g_strcmp0(type, "desktop"))
4206 sub_category = "0006";
4207 else if (!g_strcmp0(type, "tablet"))
4208 sub_category = "0009";
4209 else if (!g_strcmp0(type, "watch"))
4212 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4215 static void p2p_support(GSupplicantInterface *interface)
4217 char dev_type[17] = {};
4218 const char *hostname;
4225 if (!g_supplicant_interface_has_p2p(interface))
4228 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4229 DBG("Could not register P2P technology driver");
4233 hostname = connman_utsname_get_hostname();
4235 hostname = "ConnMan";
4237 set_device_type(connman_machine_get_type(), dev_type);
4238 g_supplicant_interface_set_p2p_device_config(interface,
4239 hostname, dev_type);
4240 connman_peer_driver_register(&peer_driver);
4243 static void scan_started(GSupplicantInterface *interface)
4248 static void scan_finished(GSupplicantInterface *interface)
4250 #if defined TIZEN_EXT
4251 struct wifi_data *wifi;
4252 bool is_associating = false;
4253 static bool is_scanning = true;
4258 #if defined TIZEN_EXT
4259 wifi = g_supplicant_interface_get_data(interface);
4260 if (wifi && wifi->scan_pending_network) {
4261 network_connect(wifi->scan_pending_network);
4262 wifi->scan_pending_network = NULL;
4265 //service state - associating
4266 if(!wifi || !wifi->network)
4269 is_associating = connman_network_get_associating(wifi->network);
4270 if(is_associating && is_scanning){
4271 is_scanning = false;
4272 DBG("send scan for connecting");
4273 throw_wifi_scan(wifi->device, scan_callback);
4284 static void ap_create_fail(GSupplicantInterface *interface)
4286 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4289 if ((wifi->tethering) && (wifi->tethering_param)) {
4290 DBG("%s create AP fail \n",
4291 g_supplicant_interface_get_ifname(wifi->interface));
4293 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4294 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4295 wifi->tethering = false;
4297 ret = tech_set_tethering(wifi->tethering_param->technology,
4298 wifi->tethering_param->ssid->ssid,
4299 wifi->tethering_param->ssid->passphrase,
4300 wifi->bridge, true);
4302 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4303 connman_technology_tethering_notify(wifi_technology,false);
4306 g_free(wifi->tethering_param->ssid);
4307 g_free(wifi->tethering_param);
4308 wifi->tethering_param = NULL;
4314 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4316 unsigned char strength;
4318 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4320 #if !defined TIZEN_EXT
4327 #if defined TIZEN_EXT_WIFI_MESH
4328 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4330 GSupplicantInterface *interface;
4331 struct wifi_data *wifi;
4332 const char *name, *security;
4333 struct connman_mesh *connman_mesh;
4334 struct wifi_mesh_info *mesh_info;
4335 const unsigned char *bssid;
4336 const char *identifier;
4341 interface = g_supplicant_network_get_interface(supplicant_network);
4342 wifi = g_supplicant_interface_get_data(interface);
4343 if (!wifi || !wifi->mesh_interface) {
4344 DBG("Virtual Mesh interface not created");
4348 bssid = g_supplicant_network_get_bssid(supplicant_network);
4349 address = g_malloc0(19);
4350 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4351 bssid[2], bssid[3], bssid[4], bssid[5]);
4353 identifier = g_supplicant_network_get_identifier(supplicant_network);
4354 name = g_supplicant_network_get_name(supplicant_network);
4355 security = g_supplicant_network_get_security(supplicant_network);
4356 frequency = g_supplicant_network_get_frequency(supplicant_network);
4358 mesh_info = wifi->mesh_info;
4359 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4363 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4365 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4366 connman_mesh_set_name(connman_mesh, name);
4367 connman_mesh_set_security(connman_mesh, security);
4368 connman_mesh_set_frequency(connman_mesh, frequency);
4369 connman_mesh_set_address(connman_mesh, address);
4370 connman_mesh_set_index(connman_mesh, mesh_info->index);
4371 connman_mesh_set_strength(connman_mesh,
4372 calculate_strength(supplicant_network));
4373 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4375 ret = connman_mesh_register(connman_mesh);
4376 if (ret == -EALREADY)
4377 DBG("Mesh Peer is already registered");
4383 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4385 GSupplicantInterface *interface;
4386 struct wifi_data *wifi;
4387 struct connman_mesh *connman_mesh;
4388 struct wifi_mesh_info *mesh_info;
4389 const char *identifier;
4391 interface = g_supplicant_network_get_interface(supplicant_network);
4392 wifi = g_supplicant_interface_get_data(interface);
4393 if (!wifi || !wifi->mesh_interface) {
4394 DBG("Virtual Mesh interface not created");
4398 identifier = g_supplicant_network_get_identifier(supplicant_network);
4400 DBG("Failed to get Mesh Peer identifier");
4404 mesh_info = wifi->mesh_info;
4405 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4407 /* Do not unregister connected mesh peer */
4408 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4409 DBG("Mesh Peer %s is connected", identifier);
4412 DBG("Mesh Peer identifier %s removed", identifier);
4413 connman_mesh_unregister(connman_mesh);
4418 static void network_added(GSupplicantNetwork *supplicant_network)
4420 struct connman_network *network;
4421 GSupplicantInterface *interface;
4422 struct wifi_data *wifi;
4423 const char *name, *identifier, *security, *group, *mode;
4424 const unsigned char *ssid;
4425 unsigned int ssid_len;
4429 bool wps_advertizing;
4431 #if defined TIZEN_EXT
4432 GSList *vsie_list = NULL;
4433 const unsigned char *country_code;
4434 ieee80211_modes_e phy_mode;
4437 mode = g_supplicant_network_get_mode(supplicant_network);
4438 identifier = g_supplicant_network_get_identifier(supplicant_network);
4440 DBG("%s", identifier);
4442 if (!g_strcmp0(mode, "adhoc"))
4445 #if defined TIZEN_EXT_WIFI_MESH
4446 if (!g_strcmp0(mode, "mesh")) {
4447 mesh_peer_added(supplicant_network);
4452 interface = g_supplicant_network_get_interface(supplicant_network);
4453 wifi = g_supplicant_interface_get_data(interface);
4454 name = g_supplicant_network_get_name(supplicant_network);
4455 security = g_supplicant_network_get_security(supplicant_network);
4456 group = g_supplicant_network_get_identifier(supplicant_network);
4457 wps = g_supplicant_network_get_wps(supplicant_network);
4458 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4459 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4460 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4461 supplicant_network);
4466 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4468 network = connman_device_get_network(wifi->device, identifier);
4471 network = connman_network_create(identifier,
4472 CONNMAN_NETWORK_TYPE_WIFI);
4476 connman_network_set_index(network, wifi->index);
4478 if (connman_device_add_network(wifi->device, network) < 0) {
4479 connman_network_unref(network);
4483 wifi->networks = g_slist_prepend(wifi->networks, network);
4486 if (name && name[0] != '\0')
4487 connman_network_set_name(network, name);
4489 connman_network_set_blob(network, "WiFi.SSID",
4491 #if defined TIZEN_EXT
4492 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4494 connman_network_set_vsie_list(network, vsie_list);
4496 DBG("vsie_list is NULL");
4497 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4498 connman_network_set_countrycode(network, country_code);
4499 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4500 connman_network_set_phy_mode(network, phy_mode);
4502 connman_network_set_string(network, "WiFi.Security", security);
4503 connman_network_set_strength(network,
4504 calculate_strength(supplicant_network));
4505 connman_network_set_bool(network, "WiFi.WPS", wps);
4508 /* Is AP advertizing for WPS association?
4509 * If so, we decide to use WPS by default */
4510 if (wps_ready && wps_pbc &&
4512 #if !defined TIZEN_EXT
4513 connman_network_set_bool(network, "WiFi.UseWPS", true);
4515 DBG("wps is activating by ap but ignore it.");
4520 connman_network_set_frequency(network,
4521 g_supplicant_network_get_frequency(supplicant_network));
4522 #if defined TIZEN_EXT
4523 connman_network_set_bssid(network,
4524 g_supplicant_network_get_bssid(supplicant_network));
4525 connman_network_set_maxrate(network,
4526 g_supplicant_network_get_maxrate(supplicant_network));
4527 connman_network_set_enc_mode(network,
4528 g_supplicant_network_get_enc_mode(supplicant_network));
4529 connman_network_set_rsn_mode(network,
4530 g_supplicant_network_get_rsn_mode(supplicant_network));
4531 connman_network_set_keymgmt(network,
4532 g_supplicant_network_get_keymgmt(supplicant_network));
4533 connman_network_set_bool(network, "WiFi.HS20AP",
4534 g_supplicant_network_is_hs20AP(supplicant_network));
4535 connman_network_set_bssid_list(network,
4536 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4538 connman_network_set_available(network, true);
4539 connman_network_set_string(network, "WiFi.Mode", mode);
4541 #if defined TIZEN_EXT
4546 connman_network_set_group(network, group);
4548 #if defined TIZEN_EXT
4549 if (wifi_first_scan == true)
4550 found_with_first_scan = true;
4553 if (wifi->hidden && ssid) {
4554 #if defined TIZEN_EXT
4555 if (network_security(wifi->hidden->security) ==
4556 network_security(security) &&
4558 if (!g_strcmp0(wifi->hidden->security, security) &&
4560 wifi->hidden->ssid_len == ssid_len &&
4561 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4562 connman_network_connect_hidden(network,
4563 wifi->hidden->identity,
4564 wifi->hidden->passphrase,
4565 wifi->hidden->user_data);
4566 wifi->hidden->user_data = NULL;
4567 hidden_free(wifi->hidden);
4568 wifi->hidden = NULL;
4573 static void network_removed(GSupplicantNetwork *network)
4575 GSupplicantInterface *interface;
4576 struct wifi_data *wifi;
4577 const char *name, *identifier;
4578 struct connman_network *connman_network;
4580 #if defined TIZEN_EXT_WIFI_MESH
4582 mode = g_supplicant_network_get_mode(network);
4583 if (!g_strcmp0(mode, "mesh")) {
4584 mesh_peer_removed(network);
4589 interface = g_supplicant_network_get_interface(network);
4590 wifi = g_supplicant_interface_get_data(interface);
4591 identifier = g_supplicant_network_get_identifier(network);
4592 name = g_supplicant_network_get_name(network);
4594 DBG("name %s", name);
4599 connman_network = connman_device_get_network(wifi->device, identifier);
4600 if (!connman_network)
4603 #if defined TIZEN_EXT
4604 if (connman_network == wifi->scan_pending_network)
4605 wifi->scan_pending_network = NULL;
4607 if (connman_network == wifi->pending_network)
4608 wifi->pending_network = NULL;
4610 if(connman_network_get_connecting(connman_network) == true){
4611 connman_network_set_connected(connman_network, false);
4615 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4617 connman_device_remove_network(wifi->device, connman_network);
4618 connman_network_unref(connman_network);
4621 static void network_changed(GSupplicantNetwork *network, const char *property)
4623 GSupplicantInterface *interface;
4624 struct wifi_data *wifi;
4625 const char *name, *identifier;
4626 struct connman_network *connman_network;
4628 #if defined TIZEN_EXT
4629 const unsigned char *bssid;
4630 unsigned int maxrate;
4633 const unsigned char *country_code;
4634 ieee80211_modes_e phy_mode;
4638 interface = g_supplicant_network_get_interface(network);
4639 wifi = g_supplicant_interface_get_data(interface);
4640 identifier = g_supplicant_network_get_identifier(network);
4641 name = g_supplicant_network_get_name(network);
4643 DBG("name %s", name);
4648 connman_network = connman_device_get_network(wifi->device, identifier);
4649 if (!connman_network)
4652 if (g_str_equal(property, "Signal")) {
4653 connman_network_set_strength(connman_network,
4654 calculate_strength(network));
4655 connman_network_update(connman_network);
4658 #if defined TIZEN_EXT
4659 bssid = g_supplicant_network_get_bssid(network);
4660 maxrate = g_supplicant_network_get_maxrate(network);
4661 frequency = g_supplicant_network_get_frequency(network);
4662 wps = g_supplicant_network_get_wps(network);
4663 phy_mode = g_supplicant_network_get_phy_mode(network);
4665 connman_network_set_bssid(connman_network, bssid);
4666 connman_network_set_maxrate(connman_network, maxrate);
4667 connman_network_set_frequency(connman_network, frequency);
4668 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4669 country_code = g_supplicant_network_get_countrycode(network);
4670 connman_network_set_countrycode(connman_network, country_code);
4671 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4672 connman_network_set_bssid_list(connman_network, bssid_list);
4673 connman_network_set_phy_mode(connman_network, phy_mode);
4675 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4676 connman_network_get_associating(connman_network))
4677 network_connect(connman_network);
4681 static void network_associated(GSupplicantNetwork *network)
4683 GSupplicantInterface *interface;
4684 struct wifi_data *wifi;
4685 struct connman_network *connman_network;
4686 const char *identifier;
4690 interface = g_supplicant_network_get_interface(network);
4694 wifi = g_supplicant_interface_get_data(interface);
4698 identifier = g_supplicant_network_get_identifier(network);
4700 connman_network = connman_device_get_network(wifi->device, identifier);
4701 if (!connman_network)
4704 if (wifi->network) {
4705 if (wifi->network == connman_network)
4709 * This should never happen, we got associated with
4710 * a network different than the one we were expecting.
4712 DBG("Associated to %p while expecting %p",
4713 connman_network, wifi->network);
4715 connman_network_set_associating(wifi->network, false);
4718 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4720 wifi->network = connman_network_ref(connman_network);
4724 * Interface state changes callback (interface_state) is always
4725 * called before network_associated callback thus we need to call
4726 * interface_state again in order to process the new state now that
4727 * we have the network properly set.
4729 interface_state(interface);
4732 static void apply_peer_services(GSupplicantPeer *peer,
4733 struct connman_peer *connman_peer)
4735 const unsigned char *data;
4740 connman_peer_reset_services(connman_peer);
4742 data = g_supplicant_peer_get_widi_ies(peer, &length);
4744 connman_peer_add_service(connman_peer,
4745 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4749 static void add_station(const char *mac)
4751 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4755 static void remove_station(const char *mac)
4757 connman_technology_tethering_remove_station(mac);
4760 static void peer_found(GSupplicantPeer *peer)
4762 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4763 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4764 struct connman_peer *connman_peer;
4765 const char *identifier, *name;
4767 #if defined TIZEN_EXT
4771 identifier = g_supplicant_peer_get_identifier(peer);
4772 name = g_supplicant_peer_get_name(peer);
4774 DBG("ident: %s", identifier);
4776 connman_peer = connman_peer_get(wifi->device, identifier);
4780 connman_peer = connman_peer_create(identifier);
4781 connman_peer_set_name(connman_peer, name);
4782 connman_peer_set_device(connman_peer, wifi->device);
4783 apply_peer_services(peer, connman_peer);
4785 ret = connman_peer_register(connman_peer);
4786 if (ret < 0 && ret != -EALREADY)
4787 connman_peer_unref(connman_peer);
4789 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4792 static void peer_lost(GSupplicantPeer *peer)
4794 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4795 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4796 struct connman_peer *connman_peer;
4797 const char *identifier;
4802 identifier = g_supplicant_peer_get_identifier(peer);
4804 DBG("ident: %s", identifier);
4806 connman_peer = connman_peer_get(wifi->device, identifier);
4808 if (wifi->p2p_connecting &&
4809 wifi->pending_peer == connman_peer) {
4810 peer_connect_timeout(wifi);
4812 connman_peer_unregister(connman_peer);
4813 connman_peer_unref(connman_peer);
4816 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4819 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4821 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4822 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4823 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4824 struct connman_peer *connman_peer;
4825 const char *identifier;
4827 identifier = g_supplicant_peer_get_identifier(peer);
4829 DBG("ident: %s", identifier);
4834 connman_peer = connman_peer_get(wifi->device, identifier);
4839 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4840 apply_peer_services(peer, connman_peer);
4841 connman_peer_services_changed(connman_peer);
4843 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4844 if (!g_supplicant_peer_is_in_a_group(peer))
4845 p_state = CONNMAN_PEER_STATE_IDLE;
4847 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4849 case G_SUPPLICANT_PEER_GROUP_STARTED:
4851 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4852 p_state = CONNMAN_PEER_STATE_IDLE;
4854 case G_SUPPLICANT_PEER_GROUP_JOINED:
4855 connman_peer_set_iface_address(connman_peer,
4856 g_supplicant_peer_get_iface_address(peer));
4858 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4859 p_state = CONNMAN_PEER_STATE_IDLE;
4861 case G_SUPPLICANT_PEER_GROUP_FAILED:
4862 if (g_supplicant_peer_has_requested_connection(peer))
4863 p_state = CONNMAN_PEER_STATE_IDLE;
4865 p_state = CONNMAN_PEER_STATE_FAILURE;
4869 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4870 p_state == CONNMAN_PEER_STATE_FAILURE) {
4871 if (wifi->p2p_connecting
4872 && connman_peer == wifi->pending_peer)
4873 peer_cancel_timeout(wifi);
4875 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4878 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4881 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4882 GSupplicantInterface *g_iface;
4883 struct wifi_data *g_wifi;
4885 g_iface = g_supplicant_peer_get_group_interface(peer);
4889 g_wifi = g_supplicant_interface_get_data(g_iface);
4893 connman_peer_set_as_master(connman_peer,
4894 !g_supplicant_peer_is_client(peer));
4895 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4898 * If wpa_supplicant didn't create a dedicated p2p-group
4899 * interface then mark this interface as p2p_device to avoid
4900 * scan and auto-scan are launched on it while P2P is connected.
4902 if (!g_list_find(p2p_iface_list, g_wifi))
4903 wifi->p2p_device = true;
4906 connman_peer_set_state(connman_peer, p_state);
4909 static void peer_request(GSupplicantPeer *peer)
4911 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4912 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4913 struct connman_peer *connman_peer;
4914 const char *identifier;
4916 #if defined TIZEN_EXT
4921 identifier = g_supplicant_peer_get_identifier(peer);
4923 DBG("ident: %s", identifier);
4925 connman_peer = connman_peer_get(wifi->device, identifier);
4929 connman_peer_request_connection(connman_peer);
4932 #if defined TIZEN_EXT
4933 static void system_power_off(void)
4936 struct wifi_data *wifi;
4937 struct connman_service *service;
4938 struct connman_ipconfig *ipconfig_ipv4;
4940 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4941 for (list = iface_list; list; list = list->next) {
4944 if (wifi->network != NULL) {
4945 service = connman_service_lookup_from_network(wifi->network);
4946 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4947 __connman_dhcp_stop(ipconfig_ipv4);
4953 static void network_merged(GSupplicantNetwork *network)
4955 GSupplicantInterface *interface;
4956 GSupplicantState state;
4957 struct wifi_data *wifi;
4958 const char *identifier;
4959 struct connman_network *connman_network;
4963 interface = g_supplicant_network_get_interface(network);
4967 state = g_supplicant_interface_get_state(interface);
4968 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4971 wifi = g_supplicant_interface_get_data(interface);
4975 identifier = g_supplicant_network_get_identifier(network);
4977 connman_network = connman_device_get_network(wifi->device, identifier);
4978 if (!connman_network)
4981 DBG("merged identifier %s", identifier);
4983 if (wifi->connected == FALSE) {
4985 case G_SUPPLICANT_STATE_AUTHENTICATING:
4986 case G_SUPPLICANT_STATE_ASSOCIATING:
4987 case G_SUPPLICANT_STATE_ASSOCIATED:
4988 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4989 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4990 connman_network_set_associating(connman_network, TRUE);
4992 case G_SUPPLICANT_STATE_COMPLETED:
4993 connman_network_set_connected(connman_network, TRUE);
4996 DBG("Not handled the state : %d", state);
5001 ishs20AP = g_supplicant_network_is_hs20AP(network);
5004 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5005 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5006 connman_network_set_string(connman_network, "WiFi.EAP",
5008 connman_network_set_string(connman_network, "WiFi.Identity",
5009 g_supplicant_network_get_identity(network));
5010 connman_network_set_string(connman_network, "WiFi.Phase2",
5011 g_supplicant_network_get_phase2(network));
5016 wifi->network = connman_network;
5019 static void assoc_failed(void *user_data)
5021 struct connman_network *network = user_data;
5022 connman_network_set_associating(network, false);
5026 static void debug(const char *str)
5028 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5029 connman_debug("%s", str);
5032 static void disconnect_reasoncode(GSupplicantInterface *interface,
5035 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5038 wifi->disconnect_code = reasoncode;
5042 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5044 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5047 wifi->assoc_code = status_code;
5051 static const GSupplicantCallbacks callbacks = {
5052 .system_ready = system_ready,
5053 .system_killed = system_killed,
5054 .interface_added = interface_added,
5055 .interface_state = interface_state,
5056 .interface_removed = interface_removed,
5057 .p2p_support = p2p_support,
5058 .scan_started = scan_started,
5059 .scan_finished = scan_finished,
5060 .ap_create_fail = ap_create_fail,
5061 .network_added = network_added,
5062 .network_removed = network_removed,
5063 .network_changed = network_changed,
5064 .network_associated = network_associated,
5065 .add_station = add_station,
5066 .remove_station = remove_station,
5067 .peer_found = peer_found,
5068 .peer_lost = peer_lost,
5069 .peer_changed = peer_changed,
5070 .peer_request = peer_request,
5071 #if defined TIZEN_EXT
5072 .system_power_off = system_power_off,
5073 .network_merged = network_merged,
5074 .assoc_failed = assoc_failed,
5077 .disconnect_reasoncode = disconnect_reasoncode,
5078 .assoc_status_code = assoc_status_code,
5079 #if defined TIZEN_EXT_WIFI_MESH
5080 .mesh_support = mesh_support,
5081 .mesh_group_started = mesh_group_started,
5082 .mesh_group_removed = mesh_group_removed,
5083 .mesh_peer_connected = mesh_peer_connected,
5084 .mesh_peer_disconnected = mesh_peer_disconnected,
5089 static int tech_probe(struct connman_technology *technology)
5091 wifi_technology = technology;
5096 static void tech_remove(struct connman_technology *technology)
5098 wifi_technology = NULL;
5101 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5102 const char *passphrase)
5104 GSupplicantSSID *ap;
5106 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5110 ap->mode = G_SUPPLICANT_MODE_MASTER;
5111 #if defined TIZEN_EXT
5112 ap->ssid = (void *) ssid;
5116 ap->ssid_len = strlen(ssid);
5120 if (!passphrase || strlen(passphrase) == 0) {
5121 ap->security = G_SUPPLICANT_SECURITY_NONE;
5122 ap->passphrase = NULL;
5124 ap->security = G_SUPPLICANT_SECURITY_PSK;
5125 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5126 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5127 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5128 ap->passphrase = passphrase;
5134 static void ap_start_callback(int result, GSupplicantInterface *interface,
5137 struct wifi_tethering_info *info = user_data;
5139 DBG("result %d index %d bridge %s",
5140 result, info->wifi->index, info->wifi->bridge);
5142 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5143 connman_inet_remove_from_bridge(info->wifi->index,
5144 info->wifi->bridge);
5146 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5147 connman_technology_tethering_notify(info->technology, false);
5148 g_free(info->wifi->tethering_param->ssid);
5149 g_free(info->wifi->tethering_param);
5150 info->wifi->tethering_param = NULL;
5154 g_free(info->ifname);
5158 static void ap_create_callback(int result,
5159 GSupplicantInterface *interface,
5162 struct wifi_tethering_info *info = user_data;
5164 DBG("result %d ifname %s", result,
5165 g_supplicant_interface_get_ifname(interface));
5167 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5168 connman_inet_remove_from_bridge(info->wifi->index,
5169 info->wifi->bridge);
5171 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5172 connman_technology_tethering_notify(info->technology, false);
5173 g_free(info->wifi->tethering_param->ssid);
5174 g_free(info->wifi->tethering_param);
5175 info->wifi->tethering_param = NULL;
5179 g_free(info->ifname);
5185 info->wifi->interface = interface;
5186 g_supplicant_interface_set_data(interface, info->wifi);
5188 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5189 connman_error("Failed to set interface ap_scan property");
5191 g_supplicant_interface_connect(interface, info->ssid,
5192 ap_start_callback, info);
5195 static void sta_remove_callback(int result,
5196 GSupplicantInterface *interface,
5199 struct wifi_tethering_info *info = user_data;
5200 const char *driver = connman_option_get_string("wifi");
5202 DBG("ifname %s result %d ", info->ifname, result);
5204 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5205 info->wifi->tethering = false;
5206 connman_technology_tethering_notify(info->technology, false);
5208 g_free(info->ifname);
5212 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5213 g_free(info->wifi->tethering_param->ssid);
5214 g_free(info->wifi->tethering_param);
5215 info->wifi->tethering_param = NULL;
5220 info->wifi->interface = NULL;
5222 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5227 static int enable_wifi_tethering(struct connman_technology *technology,
5228 const char *bridge, const char *identifier,
5229 const char *passphrase, bool available)
5232 GSupplicantInterface *interface;
5233 struct wifi_data *wifi;
5234 struct wifi_tethering_info *info;
5239 for (list = iface_list; list; list = list->next) {
5242 DBG("wifi %p network %p pending_network %p", wifi,
5243 wifi->network, wifi->pending_network);
5245 interface = wifi->interface;
5250 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5253 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5255 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5256 DBG("%s does not support AP mode (detected)", ifname);
5260 mode = g_supplicant_interface_get_mode(interface);
5261 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5262 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5263 DBG("%s does not support AP mode (capability)", ifname);
5267 if (wifi->network && available)
5270 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5274 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5275 if (!wifi->tethering_param) {
5281 info->technology = technology;
5282 info->wifi->bridge = bridge;
5283 info->ssid = ssid_ap_init(identifier, passphrase);
5287 info->ifname = g_strdup(ifname);
5291 wifi->tethering_param->technology = technology;
5292 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5293 if (!wifi->tethering_param->ssid)
5296 info->wifi->tethering = true;
5297 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5299 berr = connman_technology_tethering_notify(technology, true);
5303 err = g_supplicant_interface_remove(interface,
5304 sta_remove_callback,
5307 DBG("tethering wifi %p ifname %s", wifi, ifname);
5312 g_free(info->ifname);
5315 g_free(wifi->tethering_param);
5316 wifi->tethering_param = NULL;
5319 * Remove bridge if it was correctly created but remove
5320 * operation failed. Instead, if bridge creation failed then
5321 * break out and do not try again on another interface,
5322 * bridge set-up does not depend on it.
5325 connman_technology_tethering_notify(technology, false);
5333 static int tech_set_tethering(struct connman_technology *technology,
5334 const char *identifier, const char *passphrase,
5335 const char *bridge, bool enabled)
5338 struct wifi_data *wifi;
5344 for (list = iface_list; list; list = list->next) {
5347 if (wifi->tethering) {
5348 wifi->tethering = false;
5350 connman_inet_remove_from_bridge(wifi->index,
5352 wifi->bridged = false;
5356 connman_technology_tethering_notify(technology, false);
5361 DBG("trying tethering for available devices");
5362 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5366 DBG("trying tethering for any device");
5367 err = enable_wifi_tethering(technology, bridge, identifier,
5374 static void regdom_callback(int result, const char *alpha2, void *user_data)
5378 if (!wifi_technology)
5384 connman_technology_regdom_notify(wifi_technology, alpha2);
5387 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5389 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5392 static struct connman_technology_driver tech_driver = {
5394 .type = CONNMAN_SERVICE_TYPE_WIFI,
5395 .probe = tech_probe,
5396 .remove = tech_remove,
5397 .set_tethering = tech_set_tethering,
5398 .set_regdom = tech_set_regdom,
5401 static int wifi_init(void)
5405 err = connman_network_driver_register(&network_driver);
5409 err = g_supplicant_register(&callbacks);
5411 connman_network_driver_unregister(&network_driver);
5415 err = connman_technology_driver_register(&tech_driver);
5417 g_supplicant_unregister(&callbacks);
5418 connman_network_driver_unregister(&network_driver);
5422 #if defined TIZEN_EXT
5423 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5428 static void wifi_exit(void)
5432 connman_technology_driver_unregister(&tech_driver);
5434 g_supplicant_unregister(&callbacks);
5436 connman_network_driver_unregister(&network_driver);
5438 #if defined TIZEN_EXT
5439 g_hash_table_unref(failed_bssids);
5443 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5444 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)