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;
3179 else if (g_str_equal(security, "sae"))
3180 return G_SUPPLICANT_SECURITY_SAE;
3183 return G_SUPPLICANT_SECURITY_UNKNOWN;
3186 #if defined TIZEN_EXT
3187 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3189 if (security == NULL)
3190 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3192 if (g_str_equal(security, "FT") == TRUE)
3193 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3194 else if (g_str_equal(security, "CCKM") == TRUE)
3195 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3197 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3201 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3203 const char *security;
3204 #if defined TIZEN_EXT
3205 const void *ssid_data;
3208 memset(ssid, 0, sizeof(*ssid));
3209 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3210 #if defined TIZEN_EXT
3211 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3213 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3218 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3220 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3223 ssid->scan_ssid = 1;
3224 security = connman_network_get_string(network, "WiFi.Security");
3225 ssid->security = network_security(security);
3226 #if defined TIZEN_EXT
3227 ssid->ieee80211w = 1;
3229 ssid->passphrase = connman_network_get_string(network,
3231 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3234 * If our private key password is unset,
3235 * we use the supplied passphrase. That is needed
3236 * for PEAP where 2 passphrases (identity and client
3237 * cert may have to be provided.
3239 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3240 connman_network_set_string(network,
3241 "WiFi.PrivateKeyPassphrase",
3243 /* We must have an identity for both PEAP and TLS */
3244 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3246 /* Use agent provided identity as a fallback */
3247 if (!ssid->identity || strlen(ssid->identity) == 0)
3248 ssid->identity = connman_network_get_string(network,
3249 "WiFi.AgentIdentity");
3251 ssid->anonymous_identity = connman_network_get_string(network,
3252 "WiFi.AnonymousIdentity");
3253 ssid->ca_cert_path = connman_network_get_string(network,
3255 ssid->subject_match = connman_network_get_string(network,
3256 "WiFi.SubjectMatch");
3257 ssid->altsubject_match = connman_network_get_string(network,
3258 "WiFi.AltSubjectMatch");
3259 ssid->domain_suffix_match = connman_network_get_string(network,
3260 "WiFi.DomainSuffixMatch");
3261 ssid->domain_match = connman_network_get_string(network,
3262 "WiFi.DomainMatch");
3263 ssid->client_cert_path = connman_network_get_string(network,
3264 "WiFi.ClientCertFile");
3265 ssid->private_key_path = connman_network_get_string(network,
3266 "WiFi.PrivateKeyFile");
3267 ssid->private_key_passphrase = connman_network_get_string(network,
3268 "WiFi.PrivateKeyPassphrase");
3269 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3271 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3272 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3274 #if defined TIZEN_EXT
3275 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3276 ssid->bssid_for_connect_len = 6;
3277 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3278 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3279 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3280 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3281 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3283 ssid->freq = connman_network_get_frequency(network);
3286 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3287 if (bssid_list && g_slist_length(bssid_list) > 1) {
3289 /* If there are more than one bssid,
3290 * the user-specified bssid is tried only once at the beginning.
3291 * After that, the bssids in the list are tried in order.
3293 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3294 set_connman_bssid(RESET_BSSID, NULL);
3299 char buff[MAC_ADDRESS_LENGTH];
3300 for (list = bssid_list; list; list = list->next) {
3301 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3303 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3304 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3305 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3306 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3308 gchar *curr_bssid = g_strdup((const gchar *)buff);
3310 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3311 DBG("bssid match, try next bssid");
3315 g_hash_table_add(failed_bssids, curr_bssid);
3317 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3318 ssid->bssid = buff_bssid;
3319 ssid->freq = (unsigned int)bssids->frequency;
3325 ssid->bssid = connman_network_get_bssid(network);
3326 g_hash_table_remove_all(failed_bssids);
3329 ssid->bssid = connman_network_get_bssid(network);
3332 ssid->eap_keymgmt = network_eap_keymgmt(
3333 connman_network_get_string(network, "WiFi.KeymgmtType"));
3334 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3336 if(g_strcmp0(ssid->eap, "fast") == 0)
3337 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3340 if (connman_setting_get_bool("BackgroundScanning"))
3341 ssid->bgscan = BGSCAN_DEFAULT;
3344 static int network_connect(struct connman_network *network)
3346 struct connman_device *device = connman_network_get_device(network);
3347 struct wifi_data *wifi;
3348 GSupplicantInterface *interface;
3349 GSupplicantSSID *ssid;
3351 DBG("network %p", network);
3356 wifi = connman_device_get_data(device);
3360 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3364 interface = wifi->interface;
3366 ssid_init(ssid, network);
3368 if (wifi->disconnecting) {
3369 wifi->pending_network = network;
3370 #if defined TIZEN_EXT
3375 wifi->network = connman_network_ref(network);
3377 #if defined TIZEN_EXT
3378 wifi->scan_pending_network = NULL;
3381 return g_supplicant_interface_connect(interface, ssid,
3382 connect_callback, network);
3385 return -EINPROGRESS;
3388 static void disconnect_callback(int result, GSupplicantInterface *interface,
3391 #if defined TIZEN_EXT
3393 struct wifi_data *wifi;
3394 struct connman_network *network = user_data;
3396 DBG("network %p result %d", network, result);
3398 for (list = iface_list; list; list = list->next) {
3401 if (wifi->network == NULL && wifi->disconnecting == true)
3402 wifi->disconnecting = false;
3404 if (wifi->network == network)
3408 /* wifi_data may be invalid because wifi is already disabled */
3413 struct wifi_data *wifi = user_data;
3416 DBG("result %d supplicant interface %p wifi %p",
3417 result, interface, wifi);
3419 if (result == -ECONNABORTED) {
3420 DBG("wifi interface no longer available");
3424 if (wifi->network) {
3425 connman_network_set_connected(wifi->network, false);
3426 wifi->network = NULL;
3429 wifi->disconnecting = false;
3430 wifi->connected = false;
3432 if (wifi->pending_network) {
3433 network_connect(wifi->pending_network);
3434 wifi->pending_network = NULL;
3437 start_autoscan(wifi->device);
3440 static int network_disconnect(struct connman_network *network)
3442 struct connman_device *device = connman_network_get_device(network);
3443 struct wifi_data *wifi;
3445 #if defined TIZEN_EXT
3446 struct connman_service *service;
3449 DBG("network %p", network);
3451 wifi = connman_device_get_data(device);
3452 if (!wifi || !wifi->interface)
3455 #if defined TIZEN_EXT
3456 if (connman_network_get_associating(network) == true) {
3457 connman_network_clear_associating(network);
3458 connman_network_set_bool(network, "WiFi.UseWPS", false);
3460 service = connman_service_lookup_from_network(network);
3462 if (service != NULL &&
3463 (__connman_service_is_connected_state(service,
3464 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3465 __connman_service_is_connected_state(service,
3466 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3467 (connman_service_get_favorite(service) == false))
3468 __connman_service_set_passphrase(service, NULL);
3471 if (wifi->pending_network == network)
3472 wifi->pending_network = NULL;
3474 if (wifi->scan_pending_network == network)
3475 wifi->scan_pending_network = NULL;
3478 connman_network_set_associating(network, false);
3480 if (wifi->disconnecting)
3483 wifi->disconnecting = true;
3485 #if defined TIZEN_EXT
3486 err = g_supplicant_interface_disconnect(wifi->interface,
3487 disconnect_callback, network);
3489 err = g_supplicant_interface_disconnect(wifi->interface,
3490 disconnect_callback, wifi);
3494 wifi->disconnecting = false;
3499 #if defined TIZEN_EXT
3500 static void set_connection_mode(struct connman_network *network,
3503 ieee80211_modes_e phy_mode;
3504 connection_mode_e conn_mode;
3506 phy_mode = connman_network_get_phy_mode(network);
3508 case IEEE80211_MODE_B:
3509 if (linkspeed > 0 && linkspeed <= 11)
3510 conn_mode = CONNECTION_MODE_IEEE80211B;
3512 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3515 case IEEE80211_MODE_BG:
3516 if (linkspeed > 0 && linkspeed <= 11)
3517 conn_mode = CONNECTION_MODE_IEEE80211B;
3518 else if (linkspeed > 11 && linkspeed <= 54)
3519 conn_mode = CONNECTION_MODE_IEEE80211G;
3521 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3524 case IEEE80211_MODE_BGN:
3525 if (linkspeed > 0 && linkspeed <= 11)
3526 conn_mode = CONNECTION_MODE_IEEE80211B;
3527 else if (linkspeed > 11 && linkspeed <= 54)
3528 conn_mode = CONNECTION_MODE_IEEE80211G;
3529 else if (linkspeed > 54 && linkspeed <= 450)
3530 conn_mode = CONNECTION_MODE_IEEE80211N;
3532 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3535 case IEEE80211_MODE_A:
3536 if (linkspeed > 0 && linkspeed <= 54)
3537 conn_mode = CONNECTION_MODE_IEEE80211A;
3539 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3542 case IEEE80211_MODE_AN:
3543 if (linkspeed > 0 && linkspeed <= 54)
3544 conn_mode = CONNECTION_MODE_IEEE80211A;
3545 else if (linkspeed > 54 && linkspeed <= 450)
3546 conn_mode = CONNECTION_MODE_IEEE80211N;
3548 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3551 case IEEE80211_MODE_ANAC:
3552 if (linkspeed > 0 && linkspeed <= 54)
3553 conn_mode = CONNECTION_MODE_IEEE80211A;
3554 else if (linkspeed > 54 && linkspeed <= 450)
3555 conn_mode = CONNECTION_MODE_IEEE80211N;
3556 else if (linkspeed > 450 && linkspeed <= 1300)
3557 conn_mode = CONNECTION_MODE_IEEE80211AC;
3559 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3563 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3567 DBG("connection mode(%d)", conn_mode);
3568 connman_network_set_connection_mode(network, conn_mode);
3571 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3573 struct connman_network *network = user_data;
3576 DBG("Failed to get maxspeed from signalpoll !");
3580 DBG("maxspeed = %d", maxspeed);
3582 connman_network_set_maxspeed(network, maxspeed);
3583 set_connection_mode(network, maxspeed);
3587 static int network_signalpoll(struct wifi_data *wifi)
3589 GSupplicantInterface *interface;
3590 struct connman_network *network;
3592 if (!wifi || !wifi->network)
3595 interface = wifi->interface;
3596 network = wifi->network;
3598 DBG("network %p", network);
3600 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3603 static gboolean autosignalpoll_timeout(gpointer data)
3605 struct wifi_data *wifi = data;
3607 if (!wifi || !wifi->automaxspeed_timeout) {
3608 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3612 int ret = network_signalpoll(wifi);
3614 DBG("Fail to get max speed !!");
3615 wifi->automaxspeed_timeout = 0;
3623 static struct connman_network_driver network_driver = {
3625 .type = CONNMAN_NETWORK_TYPE_WIFI,
3626 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3627 .probe = network_probe,
3628 .remove = network_remove,
3629 .connect = network_connect,
3630 .disconnect = network_disconnect,
3633 static void interface_added(GSupplicantInterface *interface)
3635 const char *ifname = g_supplicant_interface_get_ifname(interface);
3636 const char *driver = g_supplicant_interface_get_driver(interface);
3637 #if defined TIZEN_EXT
3638 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3641 struct wifi_data *wifi;
3643 wifi = g_supplicant_interface_get_data(interface);
3645 wifi = get_pending_wifi_data(ifname);
3649 wifi->interface = interface;
3650 g_supplicant_interface_set_data(interface, wifi);
3651 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3652 wifi->p2p_device = true;
3655 DBG("ifname %s driver %s wifi %p tethering %d",
3656 ifname, driver, wifi, wifi->tethering);
3658 if (!wifi->device) {
3659 connman_error("WiFi device not set");
3663 connman_device_set_powered(wifi->device, true);
3664 #if defined TIZEN_EXT
3665 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3666 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3667 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3668 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3672 static bool is_idle(struct wifi_data *wifi)
3674 DBG("state %d", wifi->state);
3676 switch (wifi->state) {
3677 case G_SUPPLICANT_STATE_UNKNOWN:
3678 case G_SUPPLICANT_STATE_DISABLED:
3679 case G_SUPPLICANT_STATE_DISCONNECTED:
3680 case G_SUPPLICANT_STATE_INACTIVE:
3681 case G_SUPPLICANT_STATE_SCANNING:
3684 case G_SUPPLICANT_STATE_AUTHENTICATING:
3685 case G_SUPPLICANT_STATE_ASSOCIATING:
3686 case G_SUPPLICANT_STATE_ASSOCIATED:
3687 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3688 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3689 case G_SUPPLICANT_STATE_COMPLETED:
3696 static bool is_idle_wps(GSupplicantInterface *interface,
3697 struct wifi_data *wifi)
3699 /* First, let's check if WPS processing did not went wrong */
3700 if (g_supplicant_interface_get_wps_state(interface) ==
3701 G_SUPPLICANT_WPS_STATE_FAIL)
3704 /* Unlike normal connection, being associated while processing wps
3705 * actually means that we are idling. */
3706 switch (wifi->state) {
3707 case G_SUPPLICANT_STATE_UNKNOWN:
3708 case G_SUPPLICANT_STATE_DISABLED:
3709 case G_SUPPLICANT_STATE_DISCONNECTED:
3710 case G_SUPPLICANT_STATE_INACTIVE:
3711 case G_SUPPLICANT_STATE_SCANNING:
3712 case G_SUPPLICANT_STATE_ASSOCIATED:
3714 case G_SUPPLICANT_STATE_AUTHENTICATING:
3715 case G_SUPPLICANT_STATE_ASSOCIATING:
3716 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3717 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3718 case G_SUPPLICANT_STATE_COMPLETED:
3725 static bool handle_wps_completion(GSupplicantInterface *interface,
3726 struct connman_network *network,
3727 struct connman_device *device,
3728 struct wifi_data *wifi)
3732 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3734 const unsigned char *ssid, *wps_ssid;
3735 unsigned int ssid_len, wps_ssid_len;
3736 const char *wps_key;
3738 /* Checking if we got associated with requested
3740 ssid = connman_network_get_blob(network, "WiFi.SSID",
3743 wps_ssid = g_supplicant_interface_get_wps_ssid(
3744 interface, &wps_ssid_len);
3746 if (!wps_ssid || wps_ssid_len != ssid_len ||
3747 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3748 connman_network_set_associating(network, false);
3749 #if defined TIZEN_EXT
3750 g_supplicant_interface_disconnect(wifi->interface,
3751 disconnect_callback, wifi->network);
3753 connman_network_set_bool(network, "WiFi.UseWPS", false);
3754 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3756 g_supplicant_interface_disconnect(wifi->interface,
3757 disconnect_callback, wifi);
3762 wps_key = g_supplicant_interface_get_wps_key(interface);
3763 #if defined TIZEN_EXT
3764 /* Check the passphrase and encrypt it
3767 gchar *passphrase = g_strdup(wps_key);
3769 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3771 if (check_passphrase_ext(network, passphrase) < 0) {
3772 DBG("[WPS] Invalid passphrase");
3777 ret = send_encryption_request(passphrase, network);
3782 DBG("[WPS] Encryption request succeeded");
3784 DBG("[WPS] Encryption request failed %d", ret);
3787 connman_network_set_string(network, "WiFi.Passphrase",
3790 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3797 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3798 struct wifi_data *wifi)
3800 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3801 #if defined TIZEN_EXT
3802 wifi->assoc_code > 0 &&
3804 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3806 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3807 wifi->load_shaping_retries ++;
3810 wifi->load_shaping_retries = 0;
3814 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3815 struct connman_network *network,
3816 struct wifi_data *wifi)
3818 #if defined TIZEN_EXT
3819 const char *security;
3820 struct connman_service *service;
3822 if (wifi->connected)
3825 security = connman_network_get_string(network, "WiFi.Security");
3827 if (security && g_str_equal(security, "ieee8021x") == true &&
3828 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3830 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3835 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3838 struct connman_service *service;
3840 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3843 if (wifi->connected)
3847 service = connman_service_lookup_from_network(network);
3853 if (connman_service_get_favorite(service)) {
3854 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3859 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3864 #if defined TIZEN_EXT
3865 static bool handle_wifi_assoc_retry(struct connman_network *network,
3866 struct wifi_data *wifi)
3868 const char *security;
3870 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3871 connman_network_get_connecting(network) != true) {
3872 wifi->assoc_retry_count = 0;
3876 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3877 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3878 wifi->assoc_retry_count = 0;
3882 security = connman_network_get_string(network, "WiFi.Security");
3883 if (security && g_str_equal(security, "ieee8021x") == true &&
3884 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3885 wifi->assoc_retry_count = 0;
3889 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3890 wifi->assoc_retry_count = 0;
3892 /* Honestly it's not an invalid-key error,
3893 * however QA team recommends that the invalid-key error
3894 * might be better to display for user experience.
3896 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3905 static void interface_state(GSupplicantInterface *interface)
3907 struct connman_network *network;
3908 struct connman_device *device;
3909 struct wifi_data *wifi;
3910 GSupplicantState state = g_supplicant_interface_get_state(interface);
3914 wifi = g_supplicant_interface_get_data(interface);
3916 DBG("wifi %p interface state %d", wifi, state);
3921 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3922 if (wifi->tethering_param) {
3923 g_free(wifi->tethering_param->ssid);
3924 g_free(wifi->tethering_param);
3925 wifi->tethering_param = NULL;
3929 device = wifi->device;
3933 if (g_supplicant_interface_get_ready(interface) &&
3934 !wifi->interface_ready) {
3935 wifi->interface_ready = true;
3936 finalize_interface_creation(wifi);
3939 network = wifi->network;
3944 case G_SUPPLICANT_STATE_SCANNING:
3945 if (wifi->connected)
3946 connman_network_set_connected(network, false);
3950 case G_SUPPLICANT_STATE_AUTHENTICATING:
3951 case G_SUPPLICANT_STATE_ASSOCIATING:
3952 #if defined TIZEN_EXT
3953 reset_autoscan(device);
3955 stop_autoscan(device);
3958 if (!wifi->connected)
3959 connman_network_set_associating(network, true);
3963 case G_SUPPLICANT_STATE_COMPLETED:
3964 #if defined TIZEN_EXT
3965 /* though it should be already reset: */
3966 reset_autoscan(device);
3968 wifi->assoc_retry_count = 0;
3970 wifi->scan_pending_network = NULL;
3972 /* should be cleared scanning flag */
3973 bool scanning = connman_device_get_scanning(device);
3975 connman_device_set_scanning(device,
3976 CONNMAN_SERVICE_TYPE_WIFI, false);
3977 connman_device_unref(device);
3980 if (!wifi->automaxspeed_timeout) {
3981 DBG("Going to start signalpoll timer!!");
3982 int ret = network_signalpoll(wifi);
3984 DBG("Fail to get max speed !!");
3986 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
3989 g_hash_table_remove_all(failed_bssids);
3991 /* though it should be already stopped: */
3992 stop_autoscan(device);
3995 if (!handle_wps_completion(interface, network, device, wifi))
3998 connman_network_set_connected(network, true);
4000 wifi->disconnect_code = 0;
4001 wifi->assoc_code = 0;
4002 wifi->load_shaping_retries = 0;
4005 case G_SUPPLICANT_STATE_DISCONNECTED:
4006 #if defined TIZEN_EXT
4007 connman_network_set_maxspeed(network, 0);
4009 if (wifi->automaxspeed_timeout != 0) {
4010 g_source_remove(wifi->automaxspeed_timeout);
4011 wifi->automaxspeed_timeout = 0;
4012 DBG("Remove signalpoll timer!!");
4016 * If we're in one of the idle modes, we have
4017 * not started association yet and thus setting
4018 * those ones to FALSE could cancel an association
4021 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4023 if (is_idle_wps(interface, wifi))
4029 #if defined TIZEN_EXT
4030 if (handle_assoc_status_code(interface, wifi)) {
4031 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4032 guint bssid_length = 0;
4035 bssid_length = g_slist_length(bssid_list);
4037 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4038 network_connect(network);
4042 wifi->load_shaping_retries = 0;
4045 g_hash_table_remove_all(failed_bssids);
4047 if (handle_assoc_status_code(interface, wifi))
4051 /* If previous state was 4way-handshake, then
4052 * it's either: psk was incorrect and thus we retry
4053 * or if we reach the maximum retries we declare the
4055 if (handle_4way_handshake_failure(interface,
4059 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4060 switch (wifi->disconnect_code) {
4061 case 1: /* Unspecified reason */
4062 /* Let's assume it's because we got blocked */
4064 case 6: /* Class 2 frame received from nonauthenticated STA */
4065 connman_network_set_error(network,
4066 CONNMAN_NETWORK_ERROR_BLOCKED);
4073 #if defined TIZEN_EXT
4074 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4075 * Retry association until its retry count is expired */
4076 if (handle_wifi_assoc_retry(network, wifi) == true) {
4077 throw_wifi_scan(wifi->device, scan_callback);
4078 wifi->scan_pending_network = wifi->network;
4082 if(wifi->disconnect_code > 0){
4083 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4084 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4088 connman_network_set_connected(network, false);
4089 connman_network_set_associating(network, false);
4090 wifi->disconnecting = false;
4092 start_autoscan(device);
4096 case G_SUPPLICANT_STATE_INACTIVE:
4097 #if defined TIZEN_EXT
4098 if (handle_wps_completion(interface, network, device, wifi) == false)
4101 connman_network_set_associating(network, false);
4102 start_autoscan(device);
4106 case G_SUPPLICANT_STATE_UNKNOWN:
4107 case G_SUPPLICANT_STATE_DISABLED:
4108 case G_SUPPLICANT_STATE_ASSOCIATED:
4109 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4110 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4114 old_connected = wifi->connected;
4115 wifi->state = state;
4117 /* Saving wpa_s state policy:
4118 * If connected and if the state changes are roaming related:
4119 * --> We stay connected
4121 * --> We are connected
4123 * --> We are not connected
4126 case G_SUPPLICANT_STATE_AUTHENTICATING:
4127 case G_SUPPLICANT_STATE_ASSOCIATING:
4128 case G_SUPPLICANT_STATE_ASSOCIATED:
4129 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4130 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4131 if (wifi->connected)
4132 connman_warn("Probably roaming right now!"
4133 " Staying connected...");
4135 case G_SUPPLICANT_STATE_SCANNING:
4136 wifi->connected = false;
4139 start_autoscan(device);
4141 case G_SUPPLICANT_STATE_COMPLETED:
4142 wifi->connected = true;
4145 wifi->connected = false;
4152 static void interface_removed(GSupplicantInterface *interface)
4154 const char *ifname = g_supplicant_interface_get_ifname(interface);
4155 struct wifi_data *wifi;
4157 DBG("ifname %s", ifname);
4159 wifi = g_supplicant_interface_get_data(interface);
4161 #if defined TIZEN_EXT_WIFI_MESH
4162 if (wifi && wifi->mesh_interface) {
4163 DBG("Notify mesh interface remove");
4164 connman_mesh_notify_interface_remove(true);
4165 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4166 g_free(mesh_info->parent_ifname);
4167 g_free(mesh_info->ifname);
4168 g_free(mesh_info->identifier);
4170 wifi->mesh_interface = false;
4171 wifi->mesh_info = NULL;
4177 wifi->interface = NULL;
4179 if (wifi && wifi->tethering)
4182 if (!wifi || !wifi->device) {
4183 DBG("wifi interface already removed");
4187 connman_device_set_powered(wifi->device, false);
4189 check_p2p_technology();
4190 #if defined TIZEN_EXT_WIFI_MESH
4191 check_mesh_technology();
4195 static void set_device_type(const char *type, char dev_type[17])
4197 const char *oui = "0050F204";
4198 const char *category = "0001";
4199 const char *sub_category = "0000";
4201 if (!g_strcmp0(type, "handset")) {
4203 sub_category = "0005";
4204 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4205 sub_category = "0001";
4206 else if (!g_strcmp0(type, "server"))
4207 sub_category = "0002";
4208 else if (!g_strcmp0(type, "laptop"))
4209 sub_category = "0005";
4210 else if (!g_strcmp0(type, "desktop"))
4211 sub_category = "0006";
4212 else if (!g_strcmp0(type, "tablet"))
4213 sub_category = "0009";
4214 else if (!g_strcmp0(type, "watch"))
4217 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4220 static void p2p_support(GSupplicantInterface *interface)
4222 char dev_type[17] = {};
4223 const char *hostname;
4230 if (!g_supplicant_interface_has_p2p(interface))
4233 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4234 DBG("Could not register P2P technology driver");
4238 hostname = connman_utsname_get_hostname();
4240 hostname = "ConnMan";
4242 set_device_type(connman_machine_get_type(), dev_type);
4243 g_supplicant_interface_set_p2p_device_config(interface,
4244 hostname, dev_type);
4245 connman_peer_driver_register(&peer_driver);
4248 static void scan_started(GSupplicantInterface *interface)
4253 static void scan_finished(GSupplicantInterface *interface)
4255 #if defined TIZEN_EXT
4256 struct wifi_data *wifi;
4257 bool is_associating = false;
4258 static bool is_scanning = true;
4263 #if defined TIZEN_EXT
4264 wifi = g_supplicant_interface_get_data(interface);
4265 if (wifi && wifi->scan_pending_network) {
4266 network_connect(wifi->scan_pending_network);
4267 wifi->scan_pending_network = NULL;
4270 //service state - associating
4271 if(!wifi || !wifi->network)
4274 is_associating = connman_network_get_associating(wifi->network);
4275 if(is_associating && is_scanning){
4276 is_scanning = false;
4277 DBG("send scan for connecting");
4278 throw_wifi_scan(wifi->device, scan_callback);
4289 static void ap_create_fail(GSupplicantInterface *interface)
4291 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4294 if ((wifi->tethering) && (wifi->tethering_param)) {
4295 DBG("%s create AP fail \n",
4296 g_supplicant_interface_get_ifname(wifi->interface));
4298 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4299 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4300 wifi->tethering = false;
4302 ret = tech_set_tethering(wifi->tethering_param->technology,
4303 wifi->tethering_param->ssid->ssid,
4304 wifi->tethering_param->ssid->passphrase,
4305 wifi->bridge, true);
4307 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4308 connman_technology_tethering_notify(wifi_technology,false);
4311 g_free(wifi->tethering_param->ssid);
4312 g_free(wifi->tethering_param);
4313 wifi->tethering_param = NULL;
4319 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4321 unsigned char strength;
4323 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4325 #if !defined TIZEN_EXT
4332 #if defined TIZEN_EXT_WIFI_MESH
4333 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4335 GSupplicantInterface *interface;
4336 struct wifi_data *wifi;
4337 const char *name, *security;
4338 struct connman_mesh *connman_mesh;
4339 struct wifi_mesh_info *mesh_info;
4340 const unsigned char *bssid;
4341 const char *identifier;
4346 interface = g_supplicant_network_get_interface(supplicant_network);
4347 wifi = g_supplicant_interface_get_data(interface);
4348 if (!wifi || !wifi->mesh_interface) {
4349 DBG("Virtual Mesh interface not created");
4353 bssid = g_supplicant_network_get_bssid(supplicant_network);
4354 address = g_malloc0(19);
4355 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4356 bssid[2], bssid[3], bssid[4], bssid[5]);
4358 identifier = g_supplicant_network_get_identifier(supplicant_network);
4359 name = g_supplicant_network_get_name(supplicant_network);
4360 security = g_supplicant_network_get_security(supplicant_network);
4361 frequency = g_supplicant_network_get_frequency(supplicant_network);
4363 mesh_info = wifi->mesh_info;
4364 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4368 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4370 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4371 connman_mesh_set_name(connman_mesh, name);
4372 connman_mesh_set_security(connman_mesh, security);
4373 connman_mesh_set_frequency(connman_mesh, frequency);
4374 connman_mesh_set_address(connman_mesh, address);
4375 connman_mesh_set_index(connman_mesh, mesh_info->index);
4376 connman_mesh_set_strength(connman_mesh,
4377 calculate_strength(supplicant_network));
4378 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4380 ret = connman_mesh_register(connman_mesh);
4381 if (ret == -EALREADY)
4382 DBG("Mesh Peer is already registered");
4388 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4390 GSupplicantInterface *interface;
4391 struct wifi_data *wifi;
4392 struct connman_mesh *connman_mesh;
4393 struct wifi_mesh_info *mesh_info;
4394 const char *identifier;
4396 interface = g_supplicant_network_get_interface(supplicant_network);
4397 wifi = g_supplicant_interface_get_data(interface);
4398 if (!wifi || !wifi->mesh_interface) {
4399 DBG("Virtual Mesh interface not created");
4403 identifier = g_supplicant_network_get_identifier(supplicant_network);
4405 DBG("Failed to get Mesh Peer identifier");
4409 mesh_info = wifi->mesh_info;
4410 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4412 /* Do not unregister connected mesh peer */
4413 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4414 DBG("Mesh Peer %s is connected", identifier);
4417 DBG("Mesh Peer identifier %s removed", identifier);
4418 connman_mesh_unregister(connman_mesh);
4423 static void network_added(GSupplicantNetwork *supplicant_network)
4425 struct connman_network *network;
4426 GSupplicantInterface *interface;
4427 struct wifi_data *wifi;
4428 const char *name, *identifier, *security, *group, *mode;
4429 const unsigned char *ssid;
4430 unsigned int ssid_len;
4434 bool wps_advertizing;
4436 #if defined TIZEN_EXT
4437 GSList *vsie_list = NULL;
4438 const unsigned char *country_code;
4439 ieee80211_modes_e phy_mode;
4442 mode = g_supplicant_network_get_mode(supplicant_network);
4443 identifier = g_supplicant_network_get_identifier(supplicant_network);
4445 DBG("%s", identifier);
4447 if (!g_strcmp0(mode, "adhoc"))
4450 #if defined TIZEN_EXT_WIFI_MESH
4451 if (!g_strcmp0(mode, "mesh")) {
4452 mesh_peer_added(supplicant_network);
4457 interface = g_supplicant_network_get_interface(supplicant_network);
4458 wifi = g_supplicant_interface_get_data(interface);
4459 name = g_supplicant_network_get_name(supplicant_network);
4460 security = g_supplicant_network_get_security(supplicant_network);
4461 group = g_supplicant_network_get_identifier(supplicant_network);
4462 wps = g_supplicant_network_get_wps(supplicant_network);
4463 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4464 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4465 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4466 supplicant_network);
4471 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4473 network = connman_device_get_network(wifi->device, identifier);
4476 network = connman_network_create(identifier,
4477 CONNMAN_NETWORK_TYPE_WIFI);
4481 connman_network_set_index(network, wifi->index);
4483 if (connman_device_add_network(wifi->device, network) < 0) {
4484 connman_network_unref(network);
4488 wifi->networks = g_slist_prepend(wifi->networks, network);
4491 if (name && name[0] != '\0')
4492 connman_network_set_name(network, name);
4494 connman_network_set_blob(network, "WiFi.SSID",
4496 #if defined TIZEN_EXT
4497 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4499 connman_network_set_vsie_list(network, vsie_list);
4501 DBG("vsie_list is NULL");
4502 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4503 connman_network_set_countrycode(network, country_code);
4504 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4505 connman_network_set_phy_mode(network, phy_mode);
4507 connman_network_set_string(network, "WiFi.Security", security);
4508 connman_network_set_strength(network,
4509 calculate_strength(supplicant_network));
4510 connman_network_set_bool(network, "WiFi.WPS", wps);
4513 /* Is AP advertizing for WPS association?
4514 * If so, we decide to use WPS by default */
4515 if (wps_ready && wps_pbc &&
4517 #if !defined TIZEN_EXT
4518 connman_network_set_bool(network, "WiFi.UseWPS", true);
4520 DBG("wps is activating by ap but ignore it.");
4525 connman_network_set_frequency(network,
4526 g_supplicant_network_get_frequency(supplicant_network));
4527 #if defined TIZEN_EXT
4528 connman_network_set_bssid(network,
4529 g_supplicant_network_get_bssid(supplicant_network));
4530 connman_network_set_maxrate(network,
4531 g_supplicant_network_get_maxrate(supplicant_network));
4532 connman_network_set_enc_mode(network,
4533 g_supplicant_network_get_enc_mode(supplicant_network));
4534 connman_network_set_rsn_mode(network,
4535 g_supplicant_network_get_rsn_mode(supplicant_network));
4536 connman_network_set_keymgmt(network,
4537 g_supplicant_network_get_keymgmt(supplicant_network));
4538 connman_network_set_bool(network, "WiFi.HS20AP",
4539 g_supplicant_network_is_hs20AP(supplicant_network));
4540 connman_network_set_bssid_list(network,
4541 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4543 connman_network_set_available(network, true);
4544 connman_network_set_string(network, "WiFi.Mode", mode);
4546 #if defined TIZEN_EXT
4551 connman_network_set_group(network, group);
4553 #if defined TIZEN_EXT
4554 if (wifi_first_scan == true)
4555 found_with_first_scan = true;
4558 if (wifi->hidden && ssid) {
4559 #if defined TIZEN_EXT
4560 if (network_security(wifi->hidden->security) ==
4561 network_security(security) &&
4563 if (!g_strcmp0(wifi->hidden->security, security) &&
4565 wifi->hidden->ssid_len == ssid_len &&
4566 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4567 connman_network_connect_hidden(network,
4568 wifi->hidden->identity,
4569 wifi->hidden->passphrase,
4570 wifi->hidden->user_data);
4571 wifi->hidden->user_data = NULL;
4572 hidden_free(wifi->hidden);
4573 wifi->hidden = NULL;
4578 static void network_removed(GSupplicantNetwork *network)
4580 GSupplicantInterface *interface;
4581 struct wifi_data *wifi;
4582 const char *name, *identifier;
4583 struct connman_network *connman_network;
4585 #if defined TIZEN_EXT_WIFI_MESH
4587 mode = g_supplicant_network_get_mode(network);
4588 if (!g_strcmp0(mode, "mesh")) {
4589 mesh_peer_removed(network);
4594 interface = g_supplicant_network_get_interface(network);
4595 wifi = g_supplicant_interface_get_data(interface);
4596 identifier = g_supplicant_network_get_identifier(network);
4597 name = g_supplicant_network_get_name(network);
4599 DBG("name %s", name);
4604 connman_network = connman_device_get_network(wifi->device, identifier);
4605 if (!connman_network)
4608 #if defined TIZEN_EXT
4609 if (connman_network == wifi->scan_pending_network)
4610 wifi->scan_pending_network = NULL;
4612 if (connman_network == wifi->pending_network)
4613 wifi->pending_network = NULL;
4615 if(connman_network_get_connecting(connman_network) == true){
4616 connman_network_set_connected(connman_network, false);
4620 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4622 connman_device_remove_network(wifi->device, connman_network);
4623 connman_network_unref(connman_network);
4626 static void network_changed(GSupplicantNetwork *network, const char *property)
4628 GSupplicantInterface *interface;
4629 struct wifi_data *wifi;
4630 const char *name, *identifier;
4631 struct connman_network *connman_network;
4633 #if defined TIZEN_EXT
4634 const unsigned char *bssid;
4635 unsigned int maxrate;
4638 const unsigned char *country_code;
4639 ieee80211_modes_e phy_mode;
4643 interface = g_supplicant_network_get_interface(network);
4644 wifi = g_supplicant_interface_get_data(interface);
4645 identifier = g_supplicant_network_get_identifier(network);
4646 name = g_supplicant_network_get_name(network);
4648 DBG("name %s", name);
4653 connman_network = connman_device_get_network(wifi->device, identifier);
4654 if (!connman_network)
4657 if (g_str_equal(property, "Signal")) {
4658 connman_network_set_strength(connman_network,
4659 calculate_strength(network));
4660 connman_network_update(connman_network);
4663 #if defined TIZEN_EXT
4664 bssid = g_supplicant_network_get_bssid(network);
4665 maxrate = g_supplicant_network_get_maxrate(network);
4666 frequency = g_supplicant_network_get_frequency(network);
4667 wps = g_supplicant_network_get_wps(network);
4668 phy_mode = g_supplicant_network_get_phy_mode(network);
4670 connman_network_set_bssid(connman_network, bssid);
4671 connman_network_set_maxrate(connman_network, maxrate);
4672 connman_network_set_frequency(connman_network, frequency);
4673 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4674 country_code = g_supplicant_network_get_countrycode(network);
4675 connman_network_set_countrycode(connman_network, country_code);
4676 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4677 connman_network_set_bssid_list(connman_network, bssid_list);
4678 connman_network_set_phy_mode(connman_network, phy_mode);
4680 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4681 connman_network_get_associating(connman_network))
4682 network_connect(connman_network);
4686 static void network_associated(GSupplicantNetwork *network)
4688 GSupplicantInterface *interface;
4689 struct wifi_data *wifi;
4690 struct connman_network *connman_network;
4691 const char *identifier;
4695 interface = g_supplicant_network_get_interface(network);
4699 wifi = g_supplicant_interface_get_data(interface);
4703 identifier = g_supplicant_network_get_identifier(network);
4705 connman_network = connman_device_get_network(wifi->device, identifier);
4706 if (!connman_network)
4709 if (wifi->network) {
4710 if (wifi->network == connman_network)
4714 * This should never happen, we got associated with
4715 * a network different than the one we were expecting.
4717 DBG("Associated to %p while expecting %p",
4718 connman_network, wifi->network);
4720 connman_network_set_associating(wifi->network, false);
4723 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4725 wifi->network = connman_network_ref(connman_network);
4729 * Interface state changes callback (interface_state) is always
4730 * called before network_associated callback thus we need to call
4731 * interface_state again in order to process the new state now that
4732 * we have the network properly set.
4734 interface_state(interface);
4737 static void apply_peer_services(GSupplicantPeer *peer,
4738 struct connman_peer *connman_peer)
4740 const unsigned char *data;
4745 connman_peer_reset_services(connman_peer);
4747 data = g_supplicant_peer_get_widi_ies(peer, &length);
4749 connman_peer_add_service(connman_peer,
4750 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4754 static void add_station(const char *mac)
4756 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4760 static void remove_station(const char *mac)
4762 connman_technology_tethering_remove_station(mac);
4765 static void peer_found(GSupplicantPeer *peer)
4767 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4768 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4769 struct connman_peer *connman_peer;
4770 const char *identifier, *name;
4772 #if defined TIZEN_EXT
4776 identifier = g_supplicant_peer_get_identifier(peer);
4777 name = g_supplicant_peer_get_name(peer);
4779 DBG("ident: %s", identifier);
4781 connman_peer = connman_peer_get(wifi->device, identifier);
4785 connman_peer = connman_peer_create(identifier);
4786 connman_peer_set_name(connman_peer, name);
4787 connman_peer_set_device(connman_peer, wifi->device);
4788 apply_peer_services(peer, connman_peer);
4790 ret = connman_peer_register(connman_peer);
4791 if (ret < 0 && ret != -EALREADY)
4792 connman_peer_unref(connman_peer);
4794 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4797 static void peer_lost(GSupplicantPeer *peer)
4799 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4800 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4801 struct connman_peer *connman_peer;
4802 const char *identifier;
4807 identifier = g_supplicant_peer_get_identifier(peer);
4809 DBG("ident: %s", identifier);
4811 connman_peer = connman_peer_get(wifi->device, identifier);
4813 if (wifi->p2p_connecting &&
4814 wifi->pending_peer == connman_peer) {
4815 peer_connect_timeout(wifi);
4817 connman_peer_unregister(connman_peer);
4818 connman_peer_unref(connman_peer);
4821 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4824 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4826 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4827 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4828 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4829 struct connman_peer *connman_peer;
4830 const char *identifier;
4832 identifier = g_supplicant_peer_get_identifier(peer);
4834 DBG("ident: %s", identifier);
4839 connman_peer = connman_peer_get(wifi->device, identifier);
4844 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4845 apply_peer_services(peer, connman_peer);
4846 connman_peer_services_changed(connman_peer);
4848 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4849 if (!g_supplicant_peer_is_in_a_group(peer))
4850 p_state = CONNMAN_PEER_STATE_IDLE;
4852 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4854 case G_SUPPLICANT_PEER_GROUP_STARTED:
4856 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4857 p_state = CONNMAN_PEER_STATE_IDLE;
4859 case G_SUPPLICANT_PEER_GROUP_JOINED:
4860 connman_peer_set_iface_address(connman_peer,
4861 g_supplicant_peer_get_iface_address(peer));
4863 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4864 p_state = CONNMAN_PEER_STATE_IDLE;
4866 case G_SUPPLICANT_PEER_GROUP_FAILED:
4867 if (g_supplicant_peer_has_requested_connection(peer))
4868 p_state = CONNMAN_PEER_STATE_IDLE;
4870 p_state = CONNMAN_PEER_STATE_FAILURE;
4874 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4875 p_state == CONNMAN_PEER_STATE_FAILURE) {
4876 if (wifi->p2p_connecting
4877 && connman_peer == wifi->pending_peer)
4878 peer_cancel_timeout(wifi);
4880 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4883 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4886 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4887 GSupplicantInterface *g_iface;
4888 struct wifi_data *g_wifi;
4890 g_iface = g_supplicant_peer_get_group_interface(peer);
4894 g_wifi = g_supplicant_interface_get_data(g_iface);
4898 connman_peer_set_as_master(connman_peer,
4899 !g_supplicant_peer_is_client(peer));
4900 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4903 * If wpa_supplicant didn't create a dedicated p2p-group
4904 * interface then mark this interface as p2p_device to avoid
4905 * scan and auto-scan are launched on it while P2P is connected.
4907 if (!g_list_find(p2p_iface_list, g_wifi))
4908 wifi->p2p_device = true;
4911 connman_peer_set_state(connman_peer, p_state);
4914 static void peer_request(GSupplicantPeer *peer)
4916 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4917 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4918 struct connman_peer *connman_peer;
4919 const char *identifier;
4921 #if defined TIZEN_EXT
4926 identifier = g_supplicant_peer_get_identifier(peer);
4928 DBG("ident: %s", identifier);
4930 connman_peer = connman_peer_get(wifi->device, identifier);
4934 connman_peer_request_connection(connman_peer);
4937 #if defined TIZEN_EXT
4938 static void system_power_off(void)
4941 struct wifi_data *wifi;
4942 struct connman_service *service;
4943 struct connman_ipconfig *ipconfig_ipv4;
4945 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4946 for (list = iface_list; list; list = list->next) {
4949 if (wifi->network != NULL) {
4950 service = connman_service_lookup_from_network(wifi->network);
4951 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4952 __connman_dhcp_stop(ipconfig_ipv4);
4958 static void network_merged(GSupplicantNetwork *network)
4960 GSupplicantInterface *interface;
4961 GSupplicantState state;
4962 struct wifi_data *wifi;
4963 const char *identifier;
4964 struct connman_network *connman_network;
4968 interface = g_supplicant_network_get_interface(network);
4972 state = g_supplicant_interface_get_state(interface);
4973 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4976 wifi = g_supplicant_interface_get_data(interface);
4980 identifier = g_supplicant_network_get_identifier(network);
4982 connman_network = connman_device_get_network(wifi->device, identifier);
4983 if (!connman_network)
4986 DBG("merged identifier %s", identifier);
4988 if (wifi->connected == FALSE) {
4990 case G_SUPPLICANT_STATE_AUTHENTICATING:
4991 case G_SUPPLICANT_STATE_ASSOCIATING:
4992 case G_SUPPLICANT_STATE_ASSOCIATED:
4993 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4994 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4995 connman_network_set_associating(connman_network, TRUE);
4997 case G_SUPPLICANT_STATE_COMPLETED:
4998 connman_network_set_connected(connman_network, TRUE);
5001 DBG("Not handled the state : %d", state);
5006 ishs20AP = g_supplicant_network_is_hs20AP(network);
5009 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5010 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5011 connman_network_set_string(connman_network, "WiFi.EAP",
5013 connman_network_set_string(connman_network, "WiFi.Identity",
5014 g_supplicant_network_get_identity(network));
5015 connman_network_set_string(connman_network, "WiFi.Phase2",
5016 g_supplicant_network_get_phase2(network));
5021 wifi->network = connman_network;
5024 static void assoc_failed(void *user_data)
5026 struct connman_network *network = user_data;
5027 connman_network_set_associating(network, false);
5031 static void debug(const char *str)
5033 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5034 connman_debug("%s", str);
5037 static void disconnect_reasoncode(GSupplicantInterface *interface,
5040 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5043 wifi->disconnect_code = reasoncode;
5047 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5049 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5052 wifi->assoc_code = status_code;
5056 static const GSupplicantCallbacks callbacks = {
5057 .system_ready = system_ready,
5058 .system_killed = system_killed,
5059 .interface_added = interface_added,
5060 .interface_state = interface_state,
5061 .interface_removed = interface_removed,
5062 .p2p_support = p2p_support,
5063 .scan_started = scan_started,
5064 .scan_finished = scan_finished,
5065 .ap_create_fail = ap_create_fail,
5066 .network_added = network_added,
5067 .network_removed = network_removed,
5068 .network_changed = network_changed,
5069 .network_associated = network_associated,
5070 .add_station = add_station,
5071 .remove_station = remove_station,
5072 .peer_found = peer_found,
5073 .peer_lost = peer_lost,
5074 .peer_changed = peer_changed,
5075 .peer_request = peer_request,
5076 #if defined TIZEN_EXT
5077 .system_power_off = system_power_off,
5078 .network_merged = network_merged,
5079 .assoc_failed = assoc_failed,
5082 .disconnect_reasoncode = disconnect_reasoncode,
5083 .assoc_status_code = assoc_status_code,
5084 #if defined TIZEN_EXT_WIFI_MESH
5085 .mesh_support = mesh_support,
5086 .mesh_group_started = mesh_group_started,
5087 .mesh_group_removed = mesh_group_removed,
5088 .mesh_peer_connected = mesh_peer_connected,
5089 .mesh_peer_disconnected = mesh_peer_disconnected,
5094 static int tech_probe(struct connman_technology *technology)
5096 wifi_technology = technology;
5101 static void tech_remove(struct connman_technology *technology)
5103 wifi_technology = NULL;
5106 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5107 const char *passphrase)
5109 GSupplicantSSID *ap;
5111 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5115 ap->mode = G_SUPPLICANT_MODE_MASTER;
5116 #if defined TIZEN_EXT
5117 ap->ssid = (void *) ssid;
5121 ap->ssid_len = strlen(ssid);
5125 if (!passphrase || strlen(passphrase) == 0) {
5126 ap->security = G_SUPPLICANT_SECURITY_NONE;
5127 ap->passphrase = NULL;
5129 ap->security = G_SUPPLICANT_SECURITY_PSK;
5130 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5131 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5132 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5133 ap->passphrase = passphrase;
5139 static void ap_start_callback(int result, GSupplicantInterface *interface,
5142 struct wifi_tethering_info *info = user_data;
5144 DBG("result %d index %d bridge %s",
5145 result, info->wifi->index, info->wifi->bridge);
5147 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5148 connman_inet_remove_from_bridge(info->wifi->index,
5149 info->wifi->bridge);
5151 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5152 connman_technology_tethering_notify(info->technology, false);
5153 g_free(info->wifi->tethering_param->ssid);
5154 g_free(info->wifi->tethering_param);
5155 info->wifi->tethering_param = NULL;
5159 g_free(info->ifname);
5163 static void ap_create_callback(int result,
5164 GSupplicantInterface *interface,
5167 struct wifi_tethering_info *info = user_data;
5169 DBG("result %d ifname %s", result,
5170 g_supplicant_interface_get_ifname(interface));
5172 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5173 connman_inet_remove_from_bridge(info->wifi->index,
5174 info->wifi->bridge);
5176 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5177 connman_technology_tethering_notify(info->technology, false);
5178 g_free(info->wifi->tethering_param->ssid);
5179 g_free(info->wifi->tethering_param);
5180 info->wifi->tethering_param = NULL;
5184 g_free(info->ifname);
5190 info->wifi->interface = interface;
5191 g_supplicant_interface_set_data(interface, info->wifi);
5193 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5194 connman_error("Failed to set interface ap_scan property");
5196 g_supplicant_interface_connect(interface, info->ssid,
5197 ap_start_callback, info);
5200 static void sta_remove_callback(int result,
5201 GSupplicantInterface *interface,
5204 struct wifi_tethering_info *info = user_data;
5205 const char *driver = connman_option_get_string("wifi");
5207 DBG("ifname %s result %d ", info->ifname, result);
5209 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5210 info->wifi->tethering = false;
5211 connman_technology_tethering_notify(info->technology, false);
5213 g_free(info->ifname);
5217 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5218 g_free(info->wifi->tethering_param->ssid);
5219 g_free(info->wifi->tethering_param);
5220 info->wifi->tethering_param = NULL;
5225 info->wifi->interface = NULL;
5227 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5232 static int enable_wifi_tethering(struct connman_technology *technology,
5233 const char *bridge, const char *identifier,
5234 const char *passphrase, bool available)
5237 GSupplicantInterface *interface;
5238 struct wifi_data *wifi;
5239 struct wifi_tethering_info *info;
5244 for (list = iface_list; list; list = list->next) {
5247 DBG("wifi %p network %p pending_network %p", wifi,
5248 wifi->network, wifi->pending_network);
5250 interface = wifi->interface;
5255 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5258 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5260 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5261 DBG("%s does not support AP mode (detected)", ifname);
5265 mode = g_supplicant_interface_get_mode(interface);
5266 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5267 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5268 DBG("%s does not support AP mode (capability)", ifname);
5272 if (wifi->network && available)
5275 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5279 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5280 if (!wifi->tethering_param) {
5286 info->technology = technology;
5287 info->wifi->bridge = bridge;
5288 info->ssid = ssid_ap_init(identifier, passphrase);
5292 info->ifname = g_strdup(ifname);
5296 wifi->tethering_param->technology = technology;
5297 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5298 if (!wifi->tethering_param->ssid)
5301 info->wifi->tethering = true;
5302 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5304 berr = connman_technology_tethering_notify(technology, true);
5308 err = g_supplicant_interface_remove(interface,
5309 sta_remove_callback,
5312 DBG("tethering wifi %p ifname %s", wifi, ifname);
5317 g_free(info->ifname);
5320 g_free(wifi->tethering_param);
5321 wifi->tethering_param = NULL;
5324 * Remove bridge if it was correctly created but remove
5325 * operation failed. Instead, if bridge creation failed then
5326 * break out and do not try again on another interface,
5327 * bridge set-up does not depend on it.
5330 connman_technology_tethering_notify(technology, false);
5338 static int tech_set_tethering(struct connman_technology *technology,
5339 const char *identifier, const char *passphrase,
5340 const char *bridge, bool enabled)
5343 struct wifi_data *wifi;
5349 for (list = iface_list; list; list = list->next) {
5352 if (wifi->tethering) {
5353 wifi->tethering = false;
5355 connman_inet_remove_from_bridge(wifi->index,
5357 wifi->bridged = false;
5361 connman_technology_tethering_notify(technology, false);
5366 DBG("trying tethering for available devices");
5367 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5371 DBG("trying tethering for any device");
5372 err = enable_wifi_tethering(technology, bridge, identifier,
5379 static void regdom_callback(int result, const char *alpha2, void *user_data)
5383 if (!wifi_technology)
5389 connman_technology_regdom_notify(wifi_technology, alpha2);
5392 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5394 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5397 static struct connman_technology_driver tech_driver = {
5399 .type = CONNMAN_SERVICE_TYPE_WIFI,
5400 .probe = tech_probe,
5401 .remove = tech_remove,
5402 .set_tethering = tech_set_tethering,
5403 .set_regdom = tech_set_regdom,
5406 static int wifi_init(void)
5410 err = connman_network_driver_register(&network_driver);
5414 err = g_supplicant_register(&callbacks);
5416 connman_network_driver_unregister(&network_driver);
5420 err = connman_technology_driver_register(&tech_driver);
5422 g_supplicant_unregister(&callbacks);
5423 connman_network_driver_unregister(&network_driver);
5427 #if defined TIZEN_EXT
5428 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5433 static void wifi_exit(void)
5437 connman_technology_driver_unregister(&tech_driver);
5439 g_supplicant_unregister(&callbacks);
5441 connman_network_driver_unregister(&network_driver);
5443 #if defined TIZEN_EXT
5444 g_hash_table_unref(failed_bssids);
5448 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5449 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)