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;
190 static GList *iface_list = NULL;
192 static GList *pending_wifi_device = NULL;
193 static GList *p2p_iface_list = NULL;
194 bool wfd_service_registered = false;
196 static void start_autoscan(struct connman_device *device);
198 static int tech_set_tethering(struct connman_technology *technology,
199 const char *identifier, const char *passphrase,
200 const char *bridge, bool enabled);
202 #if defined TIZEN_EXT
203 #define NETCONFIG_SERVICE "net.netconfig"
204 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
205 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
207 struct enc_method_call_data {
208 DBusConnection *connection;
209 struct connman_network *network;
212 static struct enc_method_call_data encrypt_request_data;
214 static void encryption_request_reply(DBusPendingCall *call,
219 DBusMessageIter args;
221 struct connman_service *service;
222 gchar* encrypted_value = NULL;
223 struct connman_network *network = encrypt_request_data.network;
227 reply = dbus_pending_call_steal_reply(call);
229 dbus_error_init(&error);
230 if (dbus_set_error_from_message(&error, reply)) {
231 DBG("send_encryption_request() %s %s", error.name, error.message);
232 dbus_error_free(&error);
236 if (dbus_message_iter_init(reply, &args) == FALSE)
239 dbus_message_iter_get_basic(&args, &out_data);
241 encrypted_value = g_strdup((const gchar *)out_data);
242 service = connman_service_lookup_from_network(network);
245 DBG("encryption result: no service");
249 if (connman_service_get_favorite(service)) {
250 __connman_service_set_passphrase(service, encrypted_value);
251 __connman_service_save(service);
253 connman_network_set_string(network, "WiFi.Passphrase",
256 DBG("encryption result: succeeded");
259 dbus_message_unref(reply);
260 dbus_pending_call_unref(call);
261 dbus_connection_unref(encrypt_request_data.connection);
262 g_free(encrypted_value);
264 encrypt_request_data.connection = NULL;
265 encrypt_request_data.network = NULL;
268 static int send_encryption_request(const char *passphrase,
269 struct connman_network *network)
271 DBusConnection *connection = NULL;
272 DBusMessage *msg = NULL;
273 DBusPendingCall *call;
276 DBG("Invalid parameter");
280 connection = connman_dbus_get_connection();
282 DBG("dbus connection does not exist");
286 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
287 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
289 dbus_connection_unref(connection);
293 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
296 if (!dbus_connection_send_with_reply(connection, msg,
297 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
298 dbus_message_unref(msg);
299 dbus_connection_unref(connection);
304 dbus_message_unref(msg);
305 dbus_connection_unref(connection);
309 encrypt_request_data.connection = connection;
310 encrypt_request_data.network = network;
312 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
313 dbus_message_unref(msg);
319 static int p2p_tech_probe(struct connman_technology *technology)
321 p2p_technology = technology;
326 static void p2p_tech_remove(struct connman_technology *technology)
328 p2p_technology = NULL;
331 static struct connman_technology_driver p2p_tech_driver = {
333 .type = CONNMAN_SERVICE_TYPE_P2P,
334 .probe = p2p_tech_probe,
335 .remove = p2p_tech_remove,
338 static bool is_p2p_connecting(void)
342 for (list = iface_list; list; list = list->next) {
343 struct wifi_data *wifi = list->data;
345 if (wifi->p2p_connecting)
352 static void add_pending_wifi_device(struct wifi_data *wifi)
354 if (g_list_find(pending_wifi_device, wifi))
357 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
360 #if defined TIZEN_EXT_WIFI_MESH
361 struct wifi_mesh_info {
362 struct wifi_data *wifi;
363 GSupplicantInterface *interface;
364 struct connman_mesh *mesh;
371 struct mesh_change_peer_status_info {
373 enum connman_mesh_peer_status peer_status;
374 mesh_change_peer_status_cb_t callback;
378 static struct connman_technology_driver mesh_tech_driver = {
380 .type = CONNMAN_SERVICE_TYPE_MESH,
383 static void mesh_interface_create_callback(int result,
384 GSupplicantInterface *interface,
387 struct wifi_mesh_info *mesh_info = user_data;
388 struct wifi_data *wifi;
389 bool success = false;
391 DBG("result %d ifname %s, mesh_info %p", result,
392 g_supplicant_interface_get_ifname(interface),
395 if (result < 0 || !mesh_info)
398 wifi = mesh_info->wifi;
400 mesh_info->interface = interface;
401 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
402 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
403 DBG("Mesh Interface identifier %s", mesh_info->identifier);
404 wifi->mesh_interface = true;
405 wifi->mesh_info = mesh_info;
406 g_supplicant_interface_set_data(interface, wifi);
410 connman_mesh_notify_interface_create(success);
413 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
416 struct wifi_data *wifi;
417 struct wifi_mesh_info *mesh_info;
418 const char *wifi_ifname;
419 bool parent_found = false;
420 const char *driver = "nl80211";
422 for (list = iface_list; list; list = list->next) {
425 if (!g_supplicant_interface_has_mesh(wifi->interface))
428 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
432 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
439 DBG("Parent interface %s doesn't exist", parent_ifname);
443 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
447 mesh_info->wifi = wifi;
448 mesh_info->ifname = g_strdup(ifname);
449 mesh_info->parent_ifname = g_strdup(parent_ifname);
451 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
452 mesh_interface_create_callback, mesh_info);
456 static void mesh_interface_remove_callback(int result,
457 GSupplicantInterface *interface,
460 struct wifi_data *wifi = user_data;
461 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
462 bool success = false;
464 DBG("result %d mesh_info %p", result, mesh_info);
466 if (result < 0 || !mesh_info)
469 mesh_info->interface = NULL;
470 g_free(mesh_info->parent_ifname);
471 g_free(mesh_info->ifname);
472 g_free(mesh_info->identifier);
474 wifi->mesh_interface = false;
475 wifi->mesh_info = NULL;
479 connman_mesh_notify_interface_remove(success);
482 static int remove_mesh_interface(const char *ifname)
485 struct wifi_data *wifi;
486 struct wifi_mesh_info *mesh_info;
487 bool mesh_if_found = false;
490 for (list = iface_list; list; list = list->next) {
493 if (wifi->mesh_interface) {
494 mesh_if_found = true;
499 if (!mesh_if_found) {
500 DBG("Mesh interface %s doesn't exist", ifname);
504 mesh_info = wifi->mesh_info;
505 ret = g_supplicant_interface_remove(mesh_info->interface,
506 mesh_interface_remove_callback, wifi);
513 static void mesh_disconnect_callback(int result,
514 GSupplicantInterface *interface, void *user_data)
516 struct connman_mesh *mesh = user_data;
518 DBG("result %d interface %p mesh %p", result, interface, mesh);
521 static int mesh_peer_disconnect(struct connman_mesh *mesh)
524 struct wifi_data *wifi;
525 struct wifi_mesh_info *mesh_info;
526 bool mesh_if_found = false;
527 GSupplicantInterface *interface;
529 for (list = iface_list; list; list = list->next) {
532 if (wifi->mesh_interface) {
533 mesh_if_found = true;
538 if (!mesh_if_found) {
539 DBG("Mesh interface is not created");
543 mesh_info = wifi->mesh_info;
545 interface = mesh_info->interface;
546 return g_supplicant_interface_disconnect(interface,
547 mesh_disconnect_callback, mesh);
550 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
553 struct connman_mesh *mesh = user_data;
554 DBG("mesh %p result %d", mesh, result);
557 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
559 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
562 static GSupplicantSecurity mesh_network_security(const char *security)
564 if (g_str_equal(security, "none"))
565 return G_SUPPLICANT_SECURITY_NONE;
566 else if (g_str_equal(security, "sae"))
567 return G_SUPPLICANT_SECURITY_SAE;
569 return G_SUPPLICANT_SECURITY_UNKNOWN;
572 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
575 const char *security;
580 memset(ssid, 0, sizeof(*ssid));
581 ssid->mode = G_SUPPLICANT_MODE_MESH;
583 security = connman_mesh_get_security(mesh);
584 ssid->security = mesh_network_security(security);
586 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
587 ssid->passphrase = connman_mesh_get_passphrase(mesh);
589 ssid->freq = connman_mesh_get_frequency(mesh);
590 name = connman_mesh_get_name(mesh);
592 ssid->ssid_len = strlen(name);
593 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
594 memcpy(ssid->ssid, name, ssid->ssid_len);
599 static int mesh_peer_connect(struct connman_mesh *mesh)
602 struct wifi_data *wifi;
603 struct wifi_mesh_info *mesh_info;
604 bool mesh_if_found = false;
605 GSupplicantInterface *interface;
606 GSupplicantSSID *ssid;
608 for (list = iface_list; list; list = list->next) {
611 if (wifi->mesh_interface) {
612 mesh_if_found = true;
617 if (!mesh_if_found) {
618 DBG("Mesh interface is not created");
622 mesh_info = wifi->mesh_info;
624 interface = mesh_info->interface;
626 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
630 mesh_info->mesh = mesh;
632 mesh_ssid_init(ssid, mesh);
633 return g_supplicant_interface_connect(interface, ssid,
634 mesh_connect_callback, mesh);
637 static void mesh_peer_change_status_callback(int result,
638 GSupplicantInterface *interface,
641 struct mesh_change_peer_status_info *data = user_data;
643 DBG("result %d Peer Status %d", result, data->peer_status);
645 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
646 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
647 connman_mesh_remove_connected_peer(data->peer_address, 52);
651 data->callback(result, data->user_data);
653 g_free(data->peer_address);
658 static int mesh_change_peer_status(const char *peer_address,
659 enum connman_mesh_peer_status status,
660 mesh_change_peer_status_cb_t callback, void *user_data)
663 struct wifi_data *wifi;
664 struct wifi_mesh_info *mesh_info;
665 bool mesh_if_found = false;
666 GSupplicantInterface *interface;
667 struct mesh_change_peer_status_info *data;
670 for (list = iface_list; list; list = list->next) {
673 if (wifi->mesh_interface) {
674 mesh_if_found = true;
679 if (!mesh_if_found) {
680 DBG("Mesh interface is not created");
684 mesh_info = wifi->mesh_info;
686 interface = mesh_info->interface;
689 case CONNMAN_MESH_PEER_ADD:
690 method = "MeshPeerAdd";
692 case CONNMAN_MESH_PEER_REMOVE:
693 method = "MeshPeerRemove";
696 DBG("Invalid method");
700 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
702 DBG("Memory allocation failed");
706 data->peer_address = g_strdup(peer_address);
707 data->peer_status = status;
708 data->callback = callback;
709 data->user_data = user_data;
711 return g_supplicant_interface_mesh_peer_change_status(interface,
712 mesh_peer_change_status_callback, peer_address, method,
716 static struct connman_mesh_driver mesh_driver = {
717 .add_interface = add_mesh_interface,
718 .remove_interface = remove_mesh_interface,
719 .connect = mesh_peer_connect,
720 .disconnect = mesh_peer_disconnect,
721 .change_peer_status = mesh_change_peer_status,
724 static void mesh_support(GSupplicantInterface *interface)
728 if (!g_supplicant_interface_has_mesh(interface))
731 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
732 DBG("Could not register Mesh technology driver");
736 connman_mesh_driver_register(&mesh_driver);
739 static void check_mesh_technology(void)
741 bool mesh_exists = false;
744 for (list = iface_list; list; list = list->next) {
745 struct wifi_data *w = list->data;
748 g_supplicant_interface_has_mesh(w->interface))
753 connman_technology_driver_unregister(&mesh_tech_driver);
754 connman_mesh_driver_unregister(&mesh_driver);
758 static void mesh_group_started(GSupplicantInterface *interface)
760 struct wifi_data *wifi;
761 struct wifi_mesh_info *mesh_info;
762 struct connman_mesh *mesh;
763 const unsigned char *ssid;
764 unsigned int ssid_len;
767 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
768 memcpy(name, ssid, ssid_len);
769 name[ssid_len] = '\0';
770 DBG("name %s", name);
771 wifi = g_supplicant_interface_get_data(interface);
772 DBG("wifi %p", wifi);
777 mesh_info = wifi->mesh_info;
781 mesh = mesh_info->mesh;
785 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
788 static void mesh_group_removed(GSupplicantInterface *interface)
790 struct wifi_data *wifi;
791 struct wifi_mesh_info *mesh_info;
792 struct connman_mesh *mesh;
793 const unsigned char *ssid;
794 unsigned int ssid_len;
795 int disconnect_reason;
798 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
799 memcpy(name, ssid, ssid_len);
800 name[ssid_len] = '\0';
801 DBG("name %s", name);
803 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
804 DBG("Disconnect Reason %d", disconnect_reason);
806 wifi = g_supplicant_interface_get_data(interface);
807 DBG("wifi %p", wifi);
812 mesh_info = wifi->mesh_info;
816 mesh = connman_get_connected_mesh_from_name(name);
818 DBG("%s is not connected", name);
819 mesh = connman_get_connecting_mesh_from_name(name);
821 DBG("%s is not connecting", name);
826 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
827 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
830 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
832 const char *peer_address;
834 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
839 DBG("Peer %s connected", peer_address);
840 connman_mesh_add_connected_peer(peer_address);
843 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
845 const char *peer_address;
848 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
853 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
855 DBG("Peer %s disconnected with reason %d", peer_address, reason);
856 connman_mesh_remove_connected_peer(peer_address, reason);
860 static struct wifi_data *get_pending_wifi_data(const char *ifname)
864 for (list = pending_wifi_device; list; list = list->next) {
865 struct wifi_data *wifi;
866 const char *dev_name;
869 if (!wifi || !wifi->device)
872 dev_name = connman_device_get_string(wifi->device, "Interface");
873 if (!g_strcmp0(ifname, dev_name)) {
874 pending_wifi_device = g_list_delete_link(
875 pending_wifi_device, list);
883 static void remove_pending_wifi_device(struct wifi_data *wifi)
887 link = g_list_find(pending_wifi_device, wifi);
892 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
895 static void peer_cancel_timeout(struct wifi_data *wifi)
897 if (wifi->p2p_connection_timeout > 0)
898 g_source_remove(wifi->p2p_connection_timeout);
900 wifi->p2p_connection_timeout = 0;
901 wifi->p2p_connecting = false;
903 if (wifi->pending_peer) {
904 connman_peer_unref(wifi->pending_peer);
905 wifi->pending_peer = NULL;
909 static gboolean peer_connect_timeout(gpointer data)
911 struct wifi_data *wifi = data;
915 if (wifi->p2p_connecting) {
916 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
917 GSupplicantPeer *gs_peer =
918 g_supplicant_interface_peer_lookup(wifi->interface,
919 connman_peer_get_identifier(wifi->pending_peer));
921 if (g_supplicant_peer_has_requested_connection(gs_peer))
922 state = CONNMAN_PEER_STATE_IDLE;
924 connman_peer_set_state(wifi->pending_peer, state);
927 peer_cancel_timeout(wifi);
932 static void peer_connect_callback(int result, GSupplicantInterface *interface,
935 struct wifi_data *wifi = user_data;
936 struct connman_peer *peer = wifi->pending_peer;
938 DBG("peer %p - %d", peer, result);
944 peer_connect_timeout(wifi);
948 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
950 wifi->p2p_connection_timeout = g_timeout_add_seconds(
951 P2P_CONNECTION_TIMEOUT,
952 peer_connect_timeout, wifi);
955 static int peer_connect(struct connman_peer *peer,
956 enum connman_peer_wps_method wps_method,
959 struct connman_device *device = connman_peer_get_device(peer);
960 GSupplicantPeerParams *peer_params;
961 GSupplicantPeer *gs_peer;
962 struct wifi_data *wifi;
966 DBG("peer %p", peer);
971 wifi = connman_device_get_data(device);
972 if (!wifi || !wifi->interface)
975 if (wifi->p2p_connecting)
978 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
979 connman_peer_get_identifier(peer));
983 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
984 pin = g_supplicant_peer_is_wps_pin(gs_peer);
986 switch (wps_method) {
987 case CONNMAN_PEER_WPS_UNKNOWN:
988 if ((pbc && pin) || pin)
991 case CONNMAN_PEER_WPS_PBC:
996 case CONNMAN_PEER_WPS_PIN:
997 if (!pin || !wps_pin)
1002 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1006 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1008 peer_params->wps_pin = g_strdup(wps_pin);
1010 peer_params->master = connman_peer_service_is_master();
1012 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1013 peer_connect_callback, wifi);
1014 if (ret == -EINPROGRESS) {
1015 wifi->pending_peer = connman_peer_ref(peer);
1016 wifi->p2p_connecting = true;
1017 } else if (ret < 0) {
1018 g_free(peer_params->path);
1019 g_free(peer_params->wps_pin);
1020 g_free(peer_params);
1026 static int peer_disconnect(struct connman_peer *peer)
1028 struct connman_device *device = connman_peer_get_device(peer);
1029 GSupplicantPeerParams peer_params = {};
1030 GSupplicantPeer *gs_peer;
1031 struct wifi_data *wifi;
1034 DBG("peer %p", peer);
1039 wifi = connman_device_get_data(device);
1043 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1044 connman_peer_get_identifier(peer));
1048 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1050 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1052 g_free(peer_params.path);
1054 if (ret == -EINPROGRESS) {
1055 peer_cancel_timeout(wifi);
1056 wifi->p2p_device = false;
1062 struct peer_service_registration {
1063 peer_service_registration_cb_t callback;
1067 static bool is_service_wfd(const unsigned char *specs, int length)
1069 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1075 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1077 struct wifi_data *wifi = data;
1079 if (!wifi->interface ||
1080 !g_supplicant_interface_has_p2p(wifi->interface))
1083 if (!wifi->servicing) {
1084 g_supplicant_interface_p2p_listen(wifi->interface,
1085 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1091 static void register_wfd_service_cb(int result,
1092 GSupplicantInterface *iface, void *user_data)
1094 struct peer_service_registration *reg_data = user_data;
1099 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1101 if (reg_data && reg_data->callback) {
1102 reg_data->callback(result, reg_data->user_data);
1107 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1108 const unsigned char *spec,
1109 int spec_length, const unsigned char *query,
1110 int query_length, int version)
1112 GSupplicantP2PServiceParams *params;
1114 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1119 params->version = version;
1120 params->service = g_memdup(spec, spec_length);
1121 } else if (query_length > 0 && spec_length > 0) {
1122 params->query = g_memdup(query, query_length);
1123 params->query_length = query_length;
1125 params->response = g_memdup(spec, spec_length);
1126 params->response_length = spec_length;
1128 params->wfd_ies = g_memdup(spec, spec_length);
1129 params->wfd_ies_length = spec_length;
1135 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1140 g_free(params->service);
1141 g_free(params->query);
1142 g_free(params->response);
1143 g_free(params->wfd_ies);
1148 static int peer_register_wfd_service(const unsigned char *specification,
1149 int specification_length,
1150 peer_service_registration_cb_t callback,
1153 struct peer_service_registration *reg_data = NULL;
1154 static GSupplicantP2PServiceParams *params;
1159 if (wfd_service_registered)
1162 params = fill_in_peer_service_params(specification,
1163 specification_length, NULL, 0, 0);
1167 reg_data = g_try_malloc0(sizeof(*reg_data));
1173 reg_data->callback = callback;
1174 reg_data->user_data = user_data;
1176 ret = g_supplicant_set_widi_ies(params,
1177 register_wfd_service_cb, reg_data);
1178 if (ret < 0 && ret != -EINPROGRESS)
1181 wfd_service_registered = true;
1185 free_peer_service_params(params);
1191 static void register_peer_service_cb(int result,
1192 GSupplicantInterface *iface, void *user_data)
1194 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1195 struct peer_service_registration *reg_data = user_data;
1197 #if defined TIZEN_EXT
1205 apply_p2p_listen_on_iface(wifi, NULL);
1207 if (reg_data->callback)
1208 reg_data->callback(result, reg_data->user_data);
1213 static int peer_register_service(const unsigned char *specification,
1214 int specification_length,
1215 const unsigned char *query,
1216 int query_length, int version,
1217 peer_service_registration_cb_t callback,
1220 struct peer_service_registration *reg_data;
1221 GSupplicantP2PServiceParams *params;
1228 if (specification && !version && !query &&
1229 is_service_wfd(specification, specification_length)) {
1230 return peer_register_wfd_service(specification,
1231 specification_length, callback, user_data);
1234 reg_data = g_try_malloc0(sizeof(*reg_data));
1238 reg_data->callback = callback;
1239 reg_data->user_data = user_data;
1241 ret_f = -EOPNOTSUPP;
1243 for (list = iface_list; list; list = list->next) {
1244 struct wifi_data *wifi = list->data;
1245 GSupplicantInterface *iface = wifi->interface;
1247 if (!g_supplicant_interface_has_p2p(iface))
1250 params = fill_in_peer_service_params(specification,
1251 specification_length, query,
1252 query_length, version);
1259 ret_f = g_supplicant_interface_p2p_add_service(iface,
1260 register_peer_service_cb, params, reg_data);
1261 if (ret_f == 0 || ret_f == -EINPROGRESS)
1265 ret = g_supplicant_interface_p2p_add_service(iface,
1266 register_peer_service_cb, params, NULL);
1267 if (ret != 0 && ret != -EINPROGRESS)
1268 free_peer_service_params(params);
1271 if (ret_f != 0 && ret_f != -EINPROGRESS)
1277 static int peer_unregister_wfd_service(void)
1279 GSupplicantP2PServiceParams *params;
1282 if (!wfd_service_registered)
1285 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1289 wfd_service_registered = false;
1291 g_supplicant_set_widi_ies(params, NULL, NULL);
1293 for (list = iface_list; list; list = list->next) {
1294 struct wifi_data *wifi = list->data;
1296 if (!g_supplicant_interface_has_p2p(wifi->interface))
1300 if (!wifi->servicing || wifi->servicing < 0) {
1301 g_supplicant_interface_p2p_listen(wifi->interface,
1303 wifi->servicing = 0;
1310 static int peer_unregister_service(const unsigned char *specification,
1311 int specification_length,
1312 const unsigned char *query,
1313 int query_length, int version)
1315 GSupplicantP2PServiceParams *params;
1320 if (specification && !version && !query &&
1321 is_service_wfd(specification, specification_length)) {
1322 ret = peer_unregister_wfd_service();
1323 if (ret != 0 && ret != -EINPROGRESS)
1328 for (list = iface_list; list; list = list->next) {
1329 struct wifi_data *wifi = list->data;
1330 GSupplicantInterface *iface = wifi->interface;
1333 goto stop_listening;
1335 if (!g_supplicant_interface_has_p2p(iface))
1338 params = fill_in_peer_service_params(specification,
1339 specification_length, query,
1340 query_length, version);
1346 ret = g_supplicant_interface_p2p_del_service(iface, params);
1347 if (ret != 0 && ret != -EINPROGRESS)
1348 free_peer_service_params(params);
1351 if (!wifi->servicing || wifi->servicing < 0) {
1352 g_supplicant_interface_p2p_listen(iface, 0, 0);
1353 wifi->servicing = 0;
1360 static struct connman_peer_driver peer_driver = {
1361 .connect = peer_connect,
1362 .disconnect = peer_disconnect,
1363 .register_service = peer_register_service,
1364 .unregister_service = peer_unregister_service,
1367 static void handle_tethering(struct wifi_data *wifi)
1369 if (!wifi->tethering)
1378 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1380 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1383 wifi->bridged = true;
1386 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1388 struct connman_device *device = user_data;
1389 struct wifi_data *wifi = connman_device_get_data(device);
1394 DBG("index %d flags %d change %d", wifi->index, flags, change);
1396 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1398 DBG("interface up");
1400 DBG("interface down");
1403 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1404 if (flags & IFF_LOWER_UP) {
1407 handle_tethering(wifi);
1412 wifi->flags = flags;
1415 static int wifi_probe(struct connman_device *device)
1417 struct wifi_data *wifi;
1419 DBG("device %p", device);
1421 wifi = g_try_new0(struct wifi_data, 1);
1425 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1426 wifi->ap_supported = WIFI_AP_UNKNOWN;
1427 wifi->tethering_param = NULL;
1429 connman_device_set_data(device, wifi);
1430 wifi->device = connman_device_ref(device);
1432 wifi->index = connman_device_get_index(device);
1435 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1436 wifi_newlink, device);
1437 if (is_p2p_connecting())
1438 add_pending_wifi_device(wifi);
1440 iface_list = g_list_append(iface_list, wifi);
1445 static void remove_networks(struct connman_device *device,
1446 struct wifi_data *wifi)
1450 for (list = wifi->networks; list; list = list->next) {
1451 struct connman_network *network = list->data;
1453 connman_device_remove_network(device, network);
1454 connman_network_unref(network);
1457 g_slist_free(wifi->networks);
1458 wifi->networks = NULL;
1461 static void remove_peers(struct wifi_data *wifi)
1465 for (list = wifi->peers; list; list = list->next) {
1466 struct connman_peer *peer = list->data;
1468 connman_peer_unregister(peer);
1469 connman_peer_unref(peer);
1472 g_slist_free(wifi->peers);
1476 static void reset_autoscan(struct connman_device *device)
1478 struct wifi_data *wifi = connman_device_get_data(device);
1479 struct autoscan_params *autoscan;
1483 if (!wifi || !wifi->autoscan)
1486 autoscan = wifi->autoscan;
1488 if (autoscan->timeout == 0 && autoscan->interval == 0)
1491 g_source_remove(autoscan->timeout);
1493 autoscan->timeout = 0;
1494 autoscan->interval = 0;
1496 connman_device_unref(device);
1499 static void stop_autoscan(struct connman_device *device)
1501 const struct wifi_data *wifi = connman_device_get_data(device);
1503 if (!wifi || !wifi->autoscan)
1506 reset_autoscan(device);
1508 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1511 static void check_p2p_technology(void)
1513 bool p2p_exists = false;
1516 for (list = iface_list; list; list = list->next) {
1517 struct wifi_data *w = list->data;
1520 g_supplicant_interface_has_p2p(w->interface))
1525 connman_technology_driver_unregister(&p2p_tech_driver);
1526 connman_peer_driver_unregister(&peer_driver);
1530 static void wifi_remove(struct connman_device *device)
1532 struct wifi_data *wifi = connman_device_get_data(device);
1534 DBG("device %p wifi %p", device, wifi);
1539 stop_autoscan(device);
1541 if (wifi->p2p_device)
1542 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1544 iface_list = g_list_remove(iface_list, wifi);
1546 check_p2p_technology();
1547 #if defined TIZEN_EXT_WIFI_MESH
1548 check_mesh_technology();
1551 remove_pending_wifi_device(wifi);
1553 if (wifi->p2p_find_timeout) {
1554 g_source_remove(wifi->p2p_find_timeout);
1555 connman_device_unref(wifi->device);
1558 if (wifi->p2p_connection_timeout)
1559 g_source_remove(wifi->p2p_connection_timeout);
1561 #if defined TIZEN_EXT
1562 if (wifi->automaxspeed_timeout != 0) {
1563 g_source_remove(wifi->automaxspeed_timeout);
1564 wifi->automaxspeed_timeout = 0;
1568 remove_networks(device, wifi);
1571 connman_device_set_powered(device, false);
1572 connman_device_set_data(device, NULL);
1573 connman_device_unref(wifi->device);
1574 connman_rtnl_remove_watch(wifi->watch);
1576 g_supplicant_interface_set_data(wifi->interface, NULL);
1578 g_supplicant_interface_cancel(wifi->interface);
1580 if (wifi->scan_params)
1581 g_supplicant_free_scan_params(wifi->scan_params);
1583 g_free(wifi->autoscan);
1584 g_free(wifi->identifier);
1588 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1592 for (iter = list; iter; iter = g_slist_next(iter)) {
1593 struct scan_ssid *scan_ssid = iter->data;
1595 if (ssid_len == scan_ssid->ssid_len &&
1596 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1603 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1604 int freq, GSupplicantScanParams *scan_data,
1605 int driver_max_scan_ssids, char *ssid_name)
1608 struct scan_ssid *scan_ssid;
1610 if ((driver_max_scan_ssids == 0 ||
1611 driver_max_scan_ssids > scan_data->num_ssids) &&
1612 (hex_ssid || raw_ssid)) {
1614 unsigned int j = 0, hex;
1617 size_t hex_ssid_len = strlen(hex_ssid);
1619 ssid = g_try_malloc0(hex_ssid_len / 2);
1623 for (i = 0; i < hex_ssid_len; i += 2) {
1624 sscanf(hex_ssid + i, "%02x", &hex);
1633 * If we have already added hidden AP to the list,
1634 * then do not do it again. This might happen if you have
1635 * used or are using multiple wifi cards, so in that case
1636 * you might have multiple service files for same AP.
1638 if (is_duplicate(scan_data->ssids, ssid, j)) {
1644 scan_ssid = g_try_new(struct scan_ssid, 1);
1651 memcpy(scan_ssid->ssid, ssid, j);
1652 scan_ssid->ssid_len = j;
1653 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1656 scan_data->num_ssids++;
1658 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1659 scan_data->num_ssids);
1666 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1668 if (!scan_data->freqs) {
1669 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1670 if (!scan_data->freqs) {
1671 g_slist_free_full(scan_data->ssids, g_free);
1675 scan_data->num_freqs = 1;
1676 scan_data->freqs[0] = freq;
1678 bool duplicate = false;
1680 /* Don't add duplicate entries */
1681 for (i = 0; i < scan_data->num_freqs; i++) {
1682 if (scan_data->freqs[i] == freq) {
1689 scan_data->num_freqs++;
1690 scan_data->freqs = g_try_realloc(scan_data->freqs,
1691 sizeof(uint16_t) * scan_data->num_freqs);
1692 if (!scan_data->freqs) {
1693 g_slist_free_full(scan_data->ssids, g_free);
1696 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1703 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1705 struct connman_config_entry **entries;
1711 int num_ssids = 0, add_param_failed = 0;
1713 services = connman_storage_get_services();
1714 for (i = 0; services && services[i]; i++) {
1715 if (strncmp(services[i], "wifi_", 5) != 0)
1718 keyfile = connman_storage_load_service(services[i]);
1722 value = g_key_file_get_boolean(keyfile,
1723 services[i], "Hidden", NULL);
1725 g_key_file_free(keyfile);
1729 value = g_key_file_get_boolean(keyfile,
1730 services[i], "Favorite", NULL);
1732 g_key_file_free(keyfile);
1736 #if defined TIZEN_EXT
1737 value = g_key_file_get_boolean(keyfile,
1738 services[i], "AutoConnect", NULL);
1740 g_key_file_free(keyfile);
1745 ssid = g_key_file_get_string(keyfile,
1746 services[i], "SSID", NULL);
1748 name = g_key_file_get_string(keyfile, services[i], "Name",
1751 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1759 g_key_file_free(keyfile);
1763 * Check if there are any hidden AP that needs to be provisioned.
1765 entries = connman_config_get_entries("wifi");
1766 for (i = 0; entries && entries[i]; i++) {
1769 if (!entries[i]->hidden)
1772 if (!entries[i]->ssid) {
1773 ssid = entries[i]->name;
1776 ssid = entries[i]->ssid;
1777 len = entries[i]->ssid_len;
1783 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1790 connman_config_free_entries(entries);
1792 if (add_param_failed > 0)
1793 DBG("Unable to scan %d out of %d SSIDs",
1794 add_param_failed, num_ssids);
1796 g_strfreev(services);
1801 static int get_hidden_connections_params(struct wifi_data *wifi,
1802 GSupplicantScanParams *scan_params)
1804 int driver_max_ssids, i;
1805 GSupplicantScanParams *orig_params;
1808 * Scan hidden networks so that we can autoconnect to them.
1809 * We will assume 1 as a default number of ssid to scan.
1811 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1813 if (driver_max_ssids == 0)
1814 driver_max_ssids = 1;
1816 DBG("max ssids %d", driver_max_ssids);
1818 if (!wifi->scan_params) {
1819 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1820 if (!wifi->scan_params)
1823 if (get_hidden_connections(wifi->scan_params) == 0) {
1824 g_supplicant_free_scan_params(wifi->scan_params);
1825 wifi->scan_params = NULL;
1831 orig_params = wifi->scan_params;
1833 /* Let's transfer driver_max_ssids params */
1834 for (i = 0; i < driver_max_ssids; i++) {
1835 struct scan_ssid *ssid;
1837 if (!wifi->scan_params->ssids)
1840 ssid = orig_params->ssids->data;
1841 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1842 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1846 scan_params->num_ssids = i;
1847 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1849 scan_params->freqs = g_memdup(orig_params->freqs,
1850 sizeof(uint16_t) * orig_params->num_freqs);
1851 if (!scan_params->freqs)
1854 scan_params->num_freqs = orig_params->num_freqs;
1859 orig_params->num_ssids -= scan_params->num_ssids;
1861 return scan_params->num_ssids;
1864 g_slist_free_full(scan_params->ssids, g_free);
1865 g_supplicant_free_scan_params(wifi->scan_params);
1866 wifi->scan_params = NULL;
1871 static int throw_wifi_scan(struct connman_device *device,
1872 GSupplicantInterfaceCallback callback)
1874 struct wifi_data *wifi = connman_device_get_data(device);
1880 DBG("device %p %p", device, wifi->interface);
1882 if (wifi->tethering)
1884 #if defined TIZEN_EXT
1885 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1887 if (connman_device_get_scanning(device))
1891 connman_device_ref(device);
1893 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1896 connman_device_set_scanning(device,
1897 CONNMAN_SERVICE_TYPE_WIFI, true);
1899 connman_device_unref(device);
1904 static void hidden_free(struct hidden_params *hidden)
1909 if (hidden->scan_params)
1910 g_supplicant_free_scan_params(hidden->scan_params);
1911 g_free(hidden->identity);
1912 g_free(hidden->passphrase);
1913 g_free(hidden->security);
1917 #if defined TIZEN_EXT
1918 static void service_state_changed(struct connman_service *service,
1919 enum connman_service_state state);
1921 static int network_connect(struct connman_network *network);
1923 static struct connman_notifier notifier = {
1925 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1926 .service_state_changed = service_state_changed,
1929 static void service_state_changed(struct connman_service *service,
1930 enum connman_service_state state)
1932 enum connman_service_type type;
1934 type = connman_service_get_type(service);
1935 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1938 DBG("service %p state %d", service, state);
1941 case CONNMAN_SERVICE_STATE_READY:
1942 case CONNMAN_SERVICE_STATE_ONLINE:
1943 case CONNMAN_SERVICE_STATE_FAILURE:
1944 connman_notifier_unregister(¬ifier);
1945 is_wifi_notifier_registered = FALSE;
1947 __connman_device_request_scan(type);
1956 static void scan_callback(int result, GSupplicantInterface *interface,
1959 struct connman_device *device = user_data;
1960 struct wifi_data *wifi = connman_device_get_data(device);
1963 DBG("result %d wifi %p", result, wifi);
1966 if (wifi->hidden && !wifi->postpone_hidden) {
1967 connman_network_clear_hidden(wifi->hidden->user_data);
1968 hidden_free(wifi->hidden);
1969 wifi->hidden = NULL;
1972 if (wifi->scan_params) {
1973 g_supplicant_free_scan_params(wifi->scan_params);
1974 wifi->scan_params = NULL;
1979 connman_device_reset_scanning(device);
1981 /* User is connecting to a hidden AP, let's wait for finished event */
1982 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1983 GSupplicantScanParams *scan_params;
1986 wifi->postpone_hidden = false;
1987 scan_params = wifi->hidden->scan_params;
1988 wifi->hidden->scan_params = NULL;
1990 reset_autoscan(device);
1992 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1993 scan_callback, device);
1997 /* On error, let's recall scan_callback, which will cleanup */
1998 return scan_callback(ret, interface, user_data);
2001 #if defined TIZEN_EXT
2002 if (wifi && wifi->allow_full_scan) {
2004 DBG("Trigger Full Channel Scan");
2005 wifi->allow_full_scan = FALSE;
2007 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2008 scan_callback, device);
2012 /* On error, let's recall scan_callback, which will cleanup */
2013 return scan_callback(ret, interface, user_data);
2017 scanning = connman_device_get_scanning(device);
2019 connman_device_set_scanning(device,
2020 CONNMAN_SERVICE_TYPE_WIFI, false);
2022 if (result != -ENOLINK)
2023 #if defined TIZEN_EXT
2026 start_autoscan(device);
2029 * If we are here then we were scanning; however, if we are
2030 * also mid-flight disabling the interface, then wifi_disable
2031 * has already cleared the device scanning state and
2032 * unreferenced the device, obviating the need to do it here.
2036 connman_device_unref(device);
2038 #if defined TIZEN_EXT
2039 if (wifi && wifi->scan_pending_network && result != -EIO) {
2040 network_connect(wifi->scan_pending_network);
2041 wifi->scan_pending_network = NULL;
2042 connman_network_set_connecting(wifi->network);
2045 if (is_wifi_notifier_registered != true &&
2046 wifi_first_scan == true && found_with_first_scan == true) {
2047 wifi_first_scan = false;
2048 found_with_first_scan = false;
2050 connman_notifier_register(¬ifier);
2051 is_wifi_notifier_registered = true;
2056 static void scan_callback_hidden(int result,
2057 GSupplicantInterface *interface, void *user_data)
2059 struct connman_device *device = user_data;
2060 struct wifi_data *wifi = connman_device_get_data(device);
2061 GSupplicantScanParams *scan_params;
2064 DBG("result %d wifi %p", result, wifi);
2069 /* User is trying to connect to a hidden AP */
2070 if (wifi->hidden && wifi->postpone_hidden)
2073 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2077 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2078 ret = g_supplicant_interface_scan(wifi->interface,
2080 scan_callback_hidden,
2086 g_supplicant_free_scan_params(scan_params);
2089 scan_callback(result, interface, user_data);
2092 static gboolean autoscan_timeout(gpointer data)
2094 struct connman_device *device = data;
2095 struct wifi_data *wifi = connman_device_get_data(device);
2096 struct autoscan_params *autoscan;
2102 autoscan = wifi->autoscan;
2104 if (autoscan->interval <= 0) {
2105 interval = autoscan->base;
2108 interval = autoscan->interval * autoscan->base;
2110 #if defined TIZEN_EXT
2111 if (autoscan->interval >= autoscan->limit)
2113 if (interval > autoscan->limit)
2115 interval = autoscan->limit;
2117 throw_wifi_scan(wifi->device, scan_callback_hidden);
2120 DBG("interval %d", interval);
2122 autoscan->interval = interval;
2124 autoscan->timeout = g_timeout_add_seconds(interval,
2125 autoscan_timeout, device);
2130 static void start_autoscan(struct connman_device *device)
2132 struct wifi_data *wifi = connman_device_get_data(device);
2133 struct autoscan_params *autoscan;
2140 if (wifi->p2p_device)
2143 if (wifi->connected)
2146 autoscan = wifi->autoscan;
2150 if (autoscan->timeout > 0 || autoscan->interval > 0)
2153 connman_device_ref(device);
2155 autoscan_timeout(device);
2158 static struct autoscan_params *parse_autoscan_params(const char *params)
2160 struct autoscan_params *autoscan;
2165 DBG("Emulating autoscan");
2167 list_params = g_strsplit(params, ":", 0);
2168 if (list_params == 0)
2171 if (g_strv_length(list_params) < 3) {
2172 g_strfreev(list_params);
2176 base = atoi(list_params[1]);
2177 limit = atoi(list_params[2]);
2179 g_strfreev(list_params);
2181 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2183 DBG("Could not allocate memory for autoscan");
2187 DBG("base %d - limit %d", base, limit);
2188 autoscan->base = base;
2189 autoscan->limit = limit;
2194 static void setup_autoscan(struct wifi_data *wifi)
2196 if (!wifi->autoscan)
2197 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2199 start_autoscan(wifi->device);
2202 static void finalize_interface_creation(struct wifi_data *wifi)
2204 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2206 if (!wifi->device) {
2207 connman_error("WiFi device not set");
2211 connman_device_set_powered(wifi->device, true);
2213 if (!connman_setting_get_bool("BackgroundScanning"))
2216 if (wifi->p2p_device)
2219 setup_autoscan(wifi);
2222 static void interface_create_callback(int result,
2223 GSupplicantInterface *interface,
2226 struct wifi_data *wifi = user_data;
2228 DBG("result %d ifname %s, wifi %p", result,
2229 g_supplicant_interface_get_ifname(interface),
2232 if (result < 0 || !wifi)
2235 wifi->interface = interface;
2236 g_supplicant_interface_set_data(interface, wifi);
2238 if (g_supplicant_interface_get_ready(interface)) {
2239 wifi->interface_ready = true;
2240 finalize_interface_creation(wifi);
2244 static int wifi_enable(struct connman_device *device)
2246 struct wifi_data *wifi = connman_device_get_data(device);
2249 const char *driver = connman_option_get_string("wifi");
2252 DBG("device %p %p", device, wifi);
2254 index = connman_device_get_index(device);
2255 if (!wifi || index < 0)
2258 if (is_p2p_connecting())
2259 return -EINPROGRESS;
2261 interface = connman_inet_ifname(index);
2262 ret = g_supplicant_interface_create(interface, driver, NULL,
2263 interface_create_callback,
2270 return -EINPROGRESS;
2273 static int wifi_disable(struct connman_device *device)
2275 struct wifi_data *wifi = connman_device_get_data(device);
2278 DBG("device %p wifi %p", device, wifi);
2283 wifi->connected = false;
2284 wifi->disconnecting = false;
2286 if (wifi->pending_network)
2287 wifi->pending_network = NULL;
2289 stop_autoscan(device);
2291 if (wifi->p2p_find_timeout) {
2292 g_source_remove(wifi->p2p_find_timeout);
2293 wifi->p2p_find_timeout = 0;
2294 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2295 connman_device_unref(wifi->device);
2298 #if defined TIZEN_EXT
2299 if (wifi->automaxspeed_timeout != 0) {
2300 g_source_remove(wifi->automaxspeed_timeout);
2301 wifi->automaxspeed_timeout = 0;
2305 /* In case of a user scan, device is still referenced */
2306 if (connman_device_get_scanning(device)) {
2307 connman_device_set_scanning(device,
2308 CONNMAN_SERVICE_TYPE_WIFI, false);
2309 connman_device_unref(wifi->device);
2312 remove_networks(device, wifi);
2315 #if defined TIZEN_EXT
2316 wifi->scan_pending_network = NULL;
2318 if (is_wifi_notifier_registered == true) {
2319 connman_notifier_unregister(¬ifier);
2320 is_wifi_notifier_registered = false;
2324 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2328 return -EINPROGRESS;
2331 struct last_connected {
2337 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
2339 GTimeVal *aval = (GTimeVal *)a;
2340 GTimeVal *bval = (GTimeVal *)b;
2342 /* Note that the sort order is descending */
2343 if (aval->tv_sec < bval->tv_sec)
2346 if (aval->tv_sec > bval->tv_sec)
2352 static void free_entry(gpointer data)
2354 struct last_connected *entry = data;
2356 g_free(entry->ssid);
2360 static int get_latest_connections(int max_ssids,
2361 GSupplicantScanParams *scan_data)
2363 GSequenceIter *iter;
2364 GSequence *latest_list;
2365 struct last_connected *entry;
2374 latest_list = g_sequence_new(free_entry);
2378 services = connman_storage_get_services();
2379 for (i = 0; services && services[i]; i++) {
2380 if (strncmp(services[i], "wifi_", 5) != 0)
2383 keyfile = connman_storage_load_service(services[i]);
2387 str = g_key_file_get_string(keyfile,
2388 services[i], "Favorite", NULL);
2389 if (!str || g_strcmp0(str, "true")) {
2391 g_key_file_free(keyfile);
2396 str = g_key_file_get_string(keyfile,
2397 services[i], "AutoConnect", NULL);
2398 if (!str || g_strcmp0(str, "true")) {
2400 g_key_file_free(keyfile);
2405 str = g_key_file_get_string(keyfile,
2406 services[i], "Modified", NULL);
2408 g_key_file_free(keyfile);
2411 g_time_val_from_iso8601(str, &modified);
2414 ssid = g_key_file_get_string(keyfile,
2415 services[i], "SSID", NULL);
2417 freq = g_key_file_get_integer(keyfile, services[i],
2420 entry = g_try_new(struct last_connected, 1);
2422 g_sequence_free(latest_list);
2423 g_key_file_free(keyfile);
2429 entry->modified = modified;
2432 g_sequence_insert_sorted(latest_list, entry,
2438 g_key_file_free(keyfile);
2441 g_strfreev(services);
2443 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2445 iter = g_sequence_get_begin_iter(latest_list);
2447 for (i = 0; i < num_ssids; i++) {
2448 entry = g_sequence_get(iter);
2450 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2451 entry->modified.tv_sec);
2453 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2454 max_ssids, entry->ssid);
2456 iter = g_sequence_iter_next(iter);
2459 g_sequence_free(latest_list);
2463 static int wifi_scan_simple(struct connman_device *device)
2465 reset_autoscan(device);
2467 return throw_wifi_scan(device, scan_callback_hidden);
2470 static gboolean p2p_find_stop(gpointer data)
2472 struct connman_device *device = data;
2473 struct wifi_data *wifi = connman_device_get_data(device);
2478 wifi->p2p_find_timeout = 0;
2480 g_supplicant_interface_p2p_stop_find(wifi->interface);
2483 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2485 connman_device_unref(device);
2486 reset_autoscan(device);
2491 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2494 struct connman_device *device = user_data;
2495 struct wifi_data *wifi = connman_device_get_data(device);
2497 DBG("result %d wifi %p", result, wifi);
2502 if (wifi->p2p_find_timeout) {
2503 g_source_remove(wifi->p2p_find_timeout);
2504 wifi->p2p_find_timeout = 0;
2510 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2511 p2p_find_stop, device);
2512 if (!wifi->p2p_find_timeout)
2517 p2p_find_stop(device);
2520 static int p2p_find(struct connman_device *device)
2522 struct wifi_data *wifi;
2527 if (!p2p_technology)
2530 wifi = connman_device_get_data(device);
2532 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2535 reset_autoscan(device);
2536 connman_device_ref(device);
2538 ret = g_supplicant_interface_p2p_find(wifi->interface,
2539 p2p_find_callback, device);
2541 connman_device_unref(device);
2542 start_autoscan(device);
2544 connman_device_set_scanning(device,
2545 CONNMAN_SERVICE_TYPE_P2P, true);
2551 #if defined TIZEN_EXT
2552 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2555 struct connman_device *device = user_data;
2556 struct wifi_data *wifi = connman_device_get_data(device);
2559 DBG("result %d wifi %p", result, wifi);
2561 if (wifi && wifi->scan_params) {
2562 g_supplicant_free_scan_params(wifi->scan_params);
2563 wifi->scan_params = NULL;
2566 scanning = connman_device_get_scanning(device);
2568 connman_device_set_scanning(device,
2569 CONNMAN_SERVICE_TYPE_WIFI, false);
2570 connman_device_unref(device);
2574 static int wifi_specific_scan(enum connman_service_type type,
2575 struct connman_device *device, int scan_type,
2576 GSList *specific_scan_list, void *user_data)
2578 GSList *list = NULL;
2580 struct wifi_data *wifi = connman_device_get_data(device);
2581 GSupplicantScanParams *scan_params = NULL;
2582 struct scan_ssid *scan_ssid = NULL;
2591 if (wifi->p2p_device)
2594 if (type == CONNMAN_SERVICE_TYPE_P2P)
2595 return p2p_find(device);
2597 if (wifi->tethering)
2600 scanning = connman_device_get_scanning(device);
2604 DBG("scan_type: %d", scan_type);
2605 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2606 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2608 DBG("Failed to allocate memory.");
2612 for (list = specific_scan_list; list; list = list->next) {
2613 ssid = (char *)list->data;
2614 int ssid_len = strlen(ssid);
2616 scan_ssid = g_try_new0(struct scan_ssid, 1);
2618 DBG("Failed to allocate memory.");
2619 g_supplicant_free_scan_params(scan_params);
2623 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2624 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2625 scan_ssid->ssid_len = ssid_len;
2626 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2629 scan_params->num_ssids = count;
2631 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2633 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2635 DBG("Failed to allocate memory.");
2639 guint num_freqs = g_slist_length(specific_scan_list);
2640 DBG("num_freqs: %d", num_freqs);
2642 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2643 if (!scan_params->freqs) {
2644 DBG("Failed to allocate memory.");
2645 g_free(scan_params);
2650 for (list = specific_scan_list; list; list = list->next) {
2651 freq = (int)list->data;
2653 scan_params->freqs[count] = freq;
2654 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2657 scan_params->num_freqs = count;
2659 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2660 int freq_count, ap_count;
2661 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2663 DBG("Failed to allocate memory.");
2667 guint size = g_slist_length(specific_scan_list);
2669 scan_params->freqs = g_try_new0(uint16_t, size/2);
2670 if (!scan_params->freqs) {
2671 DBG("Failed to allocate memory.");
2672 g_free(scan_params);
2676 ap_count = freq_count = 0;
2677 for (list = specific_scan_list; list; list = list->next) {
2678 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2679 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2680 int ssid_len = strlen(ssid);
2682 scan_ssid = g_try_new0(struct scan_ssid, 1);
2684 DBG("Failed to allocate memory.");
2685 g_supplicant_free_scan_params(scan_params);
2689 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2690 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2691 scan_ssid->ssid_len = ssid_len;
2692 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2696 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2697 scan_params->freqs[freq_count] = freq;
2698 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2702 scan_params->num_ssids = ap_count;
2703 scan_params->num_freqs = freq_count;
2705 DBG("Invalid scan");
2709 reset_autoscan(device);
2710 connman_device_ref(device);
2712 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2713 specific_scan_callback, device);
2716 connman_device_set_scanning(device,
2717 CONNMAN_SERVICE_TYPE_WIFI, true);
2719 g_supplicant_free_scan_params(scan_params);
2720 connman_device_unref(device);
2727 #if defined TIZEN_EXT_WIFI_MESH
2728 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2731 struct connman_device *device = user_data;
2732 struct wifi_data *wifi = connman_device_get_data(device);
2735 DBG("result %d wifi %p", result, wifi);
2737 scanning = connman_device_get_scanning(device);
2739 connman_device_set_scanning(device,
2740 CONNMAN_SERVICE_TYPE_MESH, false);
2743 connman_device_unref(device);
2746 static int mesh_scan(struct connman_device *device)
2748 struct wifi_data *wifi;
2749 struct wifi_mesh_info *mesh_info;
2754 wifi = connman_device_get_data(device);
2756 if (!wifi->mesh_interface)
2759 mesh_info = wifi->mesh_info;
2760 reset_autoscan(device);
2761 connman_device_ref(device);
2763 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2764 mesh_scan_callback, device);
2766 connman_device_unref(device);
2768 connman_device_set_scanning(device,
2769 CONNMAN_SERVICE_TYPE_MESH, true);
2774 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2777 struct connman_device *device = user_data;
2778 struct wifi_data *wifi = connman_device_get_data(device);
2780 DBG("result %d wifi %p", result, wifi);
2782 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2785 static int mesh_abort_scan(enum connman_service_type type,
2786 struct connman_device *device)
2788 struct wifi_data *wifi = connman_device_get_data(device);
2789 struct wifi_mesh_info *mesh_info;
2793 if (!wifi || !wifi->mesh_interface)
2796 if (type != CONNMAN_SERVICE_TYPE_MESH)
2799 mesh_info = wifi->mesh_info;
2801 scanning = connman_device_get_scanning(device);
2805 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2806 abort_scan_callback, device);
2811 static int mesh_specific_scan(enum connman_service_type type,
2812 struct connman_device *device, const char *ssid,
2813 unsigned int freq, void *user_data)
2815 struct wifi_data *wifi = connman_device_get_data(device);
2816 GSupplicantScanParams *scan_params = NULL;
2817 struct wifi_mesh_info *mesh_info;
2818 struct scan_ssid *scan_ssid;
2822 if (!wifi || !wifi->mesh_interface)
2825 if (type != CONNMAN_SERVICE_TYPE_MESH)
2828 if (wifi->p2p_device)
2831 mesh_info = wifi->mesh_info;
2833 scanning = connman_device_get_scanning(device);
2837 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2841 scan_ssid = g_try_new(struct scan_ssid, 1);
2843 g_free(scan_params);
2847 scan_ssid->ssid_len = strlen(ssid);
2848 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2849 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2850 scan_params->num_ssids = 1;
2852 scan_params->freqs = g_try_new(uint16_t, 1);
2853 if (!scan_params->freqs) {
2854 g_slist_free_full(scan_params->ssids, g_free);
2855 g_free(scan_params);
2859 scan_params->freqs[0] = freq;
2860 scan_params->num_freqs = 1;
2862 reset_autoscan(device);
2863 connman_device_ref(device);
2865 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2866 mesh_scan_callback, device);
2869 connman_device_set_scanning(device,
2870 CONNMAN_SERVICE_TYPE_MESH, true);
2872 g_supplicant_free_scan_params(scan_params);
2873 connman_device_unref(device);
2881 * Note that the hidden scan is only used when connecting to this specific
2882 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2884 static int wifi_scan(enum connman_service_type type,
2885 struct connman_device *device,
2886 const char *ssid, unsigned int ssid_len,
2887 const char *identity, const char* passphrase,
2888 const char *security, void *user_data)
2890 struct wifi_data *wifi = connman_device_get_data(device);
2891 GSupplicantScanParams *scan_params = NULL;
2892 struct scan_ssid *scan_ssid;
2893 struct hidden_params *hidden;
2895 int driver_max_ssids = 0;
2902 if (wifi->p2p_device)
2905 if (wifi->tethering)
2908 if (type == CONNMAN_SERVICE_TYPE_P2P)
2909 return p2p_find(device);
2911 #if defined TIZEN_EXT_WIFI_MESH
2912 if (type == CONNMAN_SERVICE_TYPE_MESH)
2913 return mesh_scan(device);
2916 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2918 scanning = connman_device_get_scanning(device);
2920 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2924 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2926 DBG("max ssids %d", driver_max_ssids);
2927 if (driver_max_ssids == 0)
2928 return wifi_scan_simple(device);
2932 if (scanning && wifi->hidden && wifi->postpone_hidden)
2938 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2943 scan_ssid = g_try_new(struct scan_ssid, 1);
2945 g_free(scan_params);
2949 memcpy(scan_ssid->ssid, ssid, ssid_len);
2950 scan_ssid->ssid_len = ssid_len;
2951 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2953 scan_params->num_ssids = 1;
2955 hidden = g_try_new0(struct hidden_params, 1);
2957 g_supplicant_free_scan_params(scan_params);
2962 hidden_free(wifi->hidden);
2963 wifi->hidden = NULL;
2966 memcpy(hidden->ssid, ssid, ssid_len);
2967 hidden->ssid_len = ssid_len;
2968 hidden->identity = g_strdup(identity);
2969 hidden->passphrase = g_strdup(passphrase);
2970 hidden->security = g_strdup(security);
2971 hidden->user_data = user_data;
2972 wifi->hidden = hidden;
2975 /* Let's keep this active scan for later,
2976 * when current scan will be over. */
2977 wifi->postpone_hidden = TRUE;
2978 hidden->scan_params = scan_params;
2982 } else if (wifi->connected) {
2983 g_supplicant_free_scan_params(scan_params);
2984 return wifi_scan_simple(device);
2986 ret = get_latest_connections(driver_max_ssids, scan_params);
2988 g_supplicant_free_scan_params(scan_params);
2989 return wifi_scan_simple(device);
2993 connman_device_ref(device);
2995 reset_autoscan(device);
2997 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2998 scan_callback, device);
3001 connman_device_set_scanning(device,
3002 CONNMAN_SERVICE_TYPE_WIFI, true);
3003 #if defined TIZEN_EXT
3004 /*To allow the Full Scan after ssid based scan, set the flag here
3005 It is required because Tizen does not use the ConnMan specific
3006 backgroung Scan feature.Tizen has added the BG Scan feature in
3007 net-config. To sync with up ConnMan, we need to issue the Full Scan
3008 after SSID specific scan.*/
3009 wifi->allow_full_scan = TRUE;
3012 g_supplicant_free_scan_params(scan_params);
3013 connman_device_unref(device);
3016 hidden_free(wifi->hidden);
3017 wifi->hidden = NULL;
3024 static void wifi_regdom_callback(int result,
3028 struct connman_device *device = user_data;
3030 connman_device_regdom_notify(device, result, alpha2);
3032 connman_device_unref(device);
3035 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3037 struct wifi_data *wifi = connman_device_get_data(device);
3043 connman_device_ref(device);
3045 ret = g_supplicant_interface_set_country(wifi->interface,
3046 wifi_regdom_callback,
3049 connman_device_unref(device);
3054 static struct connman_device_driver wifi_ng_driver = {
3056 .type = CONNMAN_DEVICE_TYPE_WIFI,
3057 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3058 .probe = wifi_probe,
3059 .remove = wifi_remove,
3060 .enable = wifi_enable,
3061 .disable = wifi_disable,
3063 .set_regdom = wifi_set_regdom,
3064 #if defined TIZEN_EXT
3065 .specific_scan = wifi_specific_scan,
3067 #if defined TIZEN_EXT_WIFI_MESH
3068 .abort_scan = mesh_abort_scan,
3069 .mesh_specific_scan = mesh_specific_scan,
3073 static void system_ready(void)
3077 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3078 connman_error("Failed to register WiFi driver");
3081 static void system_killed(void)
3085 connman_device_driver_unregister(&wifi_ng_driver);
3088 static int network_probe(struct connman_network *network)
3090 DBG("network %p", network);
3095 static void network_remove(struct connman_network *network)
3097 struct connman_device *device = connman_network_get_device(network);
3098 struct wifi_data *wifi;
3100 DBG("network %p", network);
3102 wifi = connman_device_get_data(device);
3106 if (wifi->network != network)
3109 wifi->network = NULL;
3111 #if defined TIZEN_EXT
3112 wifi->disconnecting = false;
3114 if (wifi->pending_network == network)
3115 wifi->pending_network = NULL;
3117 if (wifi->scan_pending_network == network)
3118 wifi->scan_pending_network = NULL;
3122 static void connect_callback(int result, GSupplicantInterface *interface,
3125 #if defined TIZEN_EXT
3127 struct wifi_data *wifi;
3129 struct connman_network *network = user_data;
3131 DBG("network %p result %d", network, result);
3133 #if defined TIZEN_EXT
3134 set_connman_bssid(RESET_BSSID, NULL);
3136 for (list = iface_list; list; list = list->next) {
3139 if (wifi && wifi->network == network)
3143 /* wifi_data may be invalid because wifi is already disabled */
3148 if (result == -ENOKEY) {
3149 connman_network_set_error(network,
3150 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3151 } else if (result < 0) {
3152 connman_network_set_error(network,
3153 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3156 connman_network_unref(network);
3159 static GSupplicantSecurity network_security(const char *security)
3161 if (g_str_equal(security, "none"))
3162 return G_SUPPLICANT_SECURITY_NONE;
3163 else if (g_str_equal(security, "wep"))
3164 return G_SUPPLICANT_SECURITY_WEP;
3165 else if (g_str_equal(security, "psk"))
3166 return G_SUPPLICANT_SECURITY_PSK;
3167 else if (g_str_equal(security, "wpa"))
3168 return G_SUPPLICANT_SECURITY_PSK;
3169 else if (g_str_equal(security, "rsn"))
3170 return G_SUPPLICANT_SECURITY_PSK;
3171 else if (g_str_equal(security, "ieee8021x"))
3172 return G_SUPPLICANT_SECURITY_IEEE8021X;
3173 #if defined TIZEN_EXT
3174 else if (g_str_equal(security, "ft_psk") == TRUE)
3175 return G_SUPPLICANT_SECURITY_FT_PSK;
3176 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3177 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3180 return G_SUPPLICANT_SECURITY_UNKNOWN;
3183 #if defined TIZEN_EXT
3184 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3186 if (security == NULL)
3187 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3189 if (g_str_equal(security, "FT") == TRUE)
3190 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3191 else if (g_str_equal(security, "CCKM") == TRUE)
3192 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3194 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3198 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3200 const char *security;
3201 #if defined TIZEN_EXT
3202 const void *ssid_data;
3205 memset(ssid, 0, sizeof(*ssid));
3206 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3207 #if defined TIZEN_EXT
3208 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3210 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3215 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3217 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3220 ssid->scan_ssid = 1;
3221 security = connman_network_get_string(network, "WiFi.Security");
3222 ssid->security = network_security(security);
3223 ssid->passphrase = connman_network_get_string(network,
3225 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3228 * If our private key password is unset,
3229 * we use the supplied passphrase. That is needed
3230 * for PEAP where 2 passphrases (identity and client
3231 * cert may have to be provided.
3233 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3234 connman_network_set_string(network,
3235 "WiFi.PrivateKeyPassphrase",
3237 /* We must have an identity for both PEAP and TLS */
3238 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3240 /* Use agent provided identity as a fallback */
3241 if (!ssid->identity || strlen(ssid->identity) == 0)
3242 ssid->identity = connman_network_get_string(network,
3243 "WiFi.AgentIdentity");
3245 ssid->anonymous_identity = connman_network_get_string(network,
3246 "WiFi.AnonymousIdentity");
3247 ssid->ca_cert_path = connman_network_get_string(network,
3249 ssid->subject_match = connman_network_get_string(network,
3250 "WiFi.SubjectMatch");
3251 ssid->altsubject_match = connman_network_get_string(network,
3252 "WiFi.AltSubjectMatch");
3253 ssid->domain_suffix_match = connman_network_get_string(network,
3254 "WiFi.DomainSuffixMatch");
3255 ssid->domain_match = connman_network_get_string(network,
3256 "WiFi.DomainMatch");
3257 ssid->client_cert_path = connman_network_get_string(network,
3258 "WiFi.ClientCertFile");
3259 ssid->private_key_path = connman_network_get_string(network,
3260 "WiFi.PrivateKeyFile");
3261 ssid->private_key_passphrase = connman_network_get_string(network,
3262 "WiFi.PrivateKeyPassphrase");
3263 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3265 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3266 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3268 #if defined TIZEN_EXT
3269 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3270 ssid->bssid_for_connect_len = 6;
3271 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3272 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3273 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3274 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3275 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3277 ssid->freq = connman_network_get_frequency(network);
3280 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3281 if (bssid_list && g_slist_length(bssid_list) > 1) {
3283 /* If there are more than one bssid,
3284 * the user-specified bssid is tried only once at the beginning.
3285 * After that, the bssids in the list are tried in order.
3287 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3288 set_connman_bssid(RESET_BSSID, NULL);
3293 char buff[MAC_ADDRESS_LENGTH];
3294 for (list = bssid_list; list; list = list->next) {
3295 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3297 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3298 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3299 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3300 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3302 gchar *curr_bssids = g_strdup((const gchar *)buff);
3304 if (g_hash_table_contains(failed_bssids, curr_bssids)) {
3305 DBG("bssid match, try next bssid");
3306 g_free(curr_bssids);
3309 g_hash_table_add(failed_bssids, curr_bssids);
3311 ssid->bssid = &(bssids->bssid[0]);
3312 ssid->freq = (unsigned int)bssids->frequency;
3318 ssid->bssid = connman_network_get_bssid(network);
3319 g_hash_table_remove_all(failed_bssids);
3322 ssid->bssid = connman_network_get_bssid(network);
3325 ssid->eap_keymgmt = network_eap_keymgmt(
3326 connman_network_get_string(network, "WiFi.KeymgmtType"));
3327 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3329 if(g_strcmp0(ssid->eap, "fast") == 0)
3330 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3333 if (connman_setting_get_bool("BackgroundScanning"))
3334 ssid->bgscan = BGSCAN_DEFAULT;
3337 static int network_connect(struct connman_network *network)
3339 struct connman_device *device = connman_network_get_device(network);
3340 struct wifi_data *wifi;
3341 GSupplicantInterface *interface;
3342 GSupplicantSSID *ssid;
3344 DBG("network %p", network);
3349 wifi = connman_device_get_data(device);
3353 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3357 interface = wifi->interface;
3359 ssid_init(ssid, network);
3361 if (wifi->disconnecting) {
3362 wifi->pending_network = network;
3363 #if defined TIZEN_EXT
3368 wifi->network = connman_network_ref(network);
3370 #if defined TIZEN_EXT
3371 wifi->scan_pending_network = NULL;
3374 return g_supplicant_interface_connect(interface, ssid,
3375 connect_callback, network);
3378 return -EINPROGRESS;
3381 static void disconnect_callback(int result, GSupplicantInterface *interface,
3384 #if defined TIZEN_EXT
3386 struct wifi_data *wifi;
3387 struct connman_network *network = user_data;
3389 DBG("network %p result %d", network, result);
3391 for (list = iface_list; list; list = list->next) {
3394 if (wifi->network == NULL && wifi->disconnecting == true)
3395 wifi->disconnecting = false;
3397 if (wifi->network == network)
3401 /* wifi_data may be invalid because wifi is already disabled */
3406 struct wifi_data *wifi = user_data;
3409 DBG("result %d supplicant interface %p wifi %p",
3410 result, interface, wifi);
3412 if (result == -ECONNABORTED) {
3413 DBG("wifi interface no longer available");
3417 if (wifi->network) {
3418 connman_network_set_connected(wifi->network, false);
3419 wifi->network = NULL;
3422 wifi->disconnecting = false;
3423 wifi->connected = false;
3425 if (wifi->pending_network) {
3426 network_connect(wifi->pending_network);
3427 wifi->pending_network = NULL;
3430 start_autoscan(wifi->device);
3433 static int network_disconnect(struct connman_network *network)
3435 struct connman_device *device = connman_network_get_device(network);
3436 struct wifi_data *wifi;
3438 #if defined TIZEN_EXT
3439 struct connman_service *service;
3442 DBG("network %p", network);
3444 wifi = connman_device_get_data(device);
3445 if (!wifi || !wifi->interface)
3448 #if defined TIZEN_EXT
3449 if (connman_network_get_associating(network) == true) {
3450 connman_network_clear_associating(network);
3451 connman_network_set_bool(network, "WiFi.UseWPS", false);
3453 service = connman_service_lookup_from_network(network);
3455 if (service != NULL &&
3456 (__connman_service_is_connected_state(service,
3457 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3458 __connman_service_is_connected_state(service,
3459 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3460 (connman_service_get_favorite(service) == false))
3461 __connman_service_set_passphrase(service, NULL);
3464 if (wifi->pending_network == network)
3465 wifi->pending_network = NULL;
3467 if (wifi->scan_pending_network == network)
3468 wifi->scan_pending_network = NULL;
3471 connman_network_set_associating(network, false);
3473 if (wifi->disconnecting)
3476 wifi->disconnecting = true;
3478 #if defined TIZEN_EXT
3479 err = g_supplicant_interface_disconnect(wifi->interface,
3480 disconnect_callback, network);
3482 err = g_supplicant_interface_disconnect(wifi->interface,
3483 disconnect_callback, wifi);
3487 wifi->disconnecting = false;
3492 #if defined TIZEN_EXT
3493 static void set_connection_mode(struct connman_network *network,
3496 ieee80211_modes_e phy_mode;
3497 connection_mode_e conn_mode;
3499 phy_mode = connman_network_get_phy_mode(network);
3501 case IEEE80211_MODE_B:
3502 if (linkspeed > 0 && linkspeed <= 11)
3503 conn_mode = CONNECTION_MODE_IEEE80211B;
3505 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3508 case IEEE80211_MODE_BG:
3509 if (linkspeed > 0 && linkspeed <= 11)
3510 conn_mode = CONNECTION_MODE_IEEE80211B;
3511 else if (linkspeed > 11 && linkspeed <= 54)
3512 conn_mode = CONNECTION_MODE_IEEE80211G;
3514 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3517 case IEEE80211_MODE_BGN:
3518 if (linkspeed > 0 && linkspeed <= 11)
3519 conn_mode = CONNECTION_MODE_IEEE80211B;
3520 else if (linkspeed > 11 && linkspeed <= 54)
3521 conn_mode = CONNECTION_MODE_IEEE80211G;
3522 else if (linkspeed > 54 && linkspeed <= 450)
3523 conn_mode = CONNECTION_MODE_IEEE80211N;
3525 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3528 case IEEE80211_MODE_A:
3529 if (linkspeed > 0 && linkspeed <= 54)
3530 conn_mode = CONNECTION_MODE_IEEE80211A;
3532 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3535 case IEEE80211_MODE_AN:
3536 if (linkspeed > 0 && linkspeed <= 54)
3537 conn_mode = CONNECTION_MODE_IEEE80211A;
3538 else if (linkspeed > 54 && linkspeed <= 450)
3539 conn_mode = CONNECTION_MODE_IEEE80211N;
3541 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3544 case IEEE80211_MODE_ANAC:
3545 if (linkspeed > 0 && linkspeed <= 54)
3546 conn_mode = CONNECTION_MODE_IEEE80211A;
3547 else if (linkspeed > 54 && linkspeed <= 450)
3548 conn_mode = CONNECTION_MODE_IEEE80211N;
3549 else if (linkspeed > 450 && linkspeed <= 1300)
3550 conn_mode = CONNECTION_MODE_IEEE80211AC;
3552 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3556 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3560 DBG("connection mode(%d)", conn_mode);
3561 connman_network_set_connection_mode(network, conn_mode);
3564 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3566 struct connman_network *network = user_data;
3569 DBG("Failed to get maxspeed from signalpoll !");
3573 DBG("maxspeed = %d", maxspeed);
3575 connman_network_set_maxspeed(network, maxspeed);
3576 set_connection_mode(network, maxspeed);
3580 static int network_signalpoll(struct wifi_data *wifi)
3582 GSupplicantInterface *interface;
3583 struct connman_network *network;
3585 if (!wifi || !wifi->network)
3588 interface = wifi->interface;
3589 network = wifi->network;
3591 DBG("network %p", network);
3593 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3596 static gboolean autosignalpoll_timeout(gpointer data)
3598 struct wifi_data *wifi = data;
3600 if (!wifi || !wifi->automaxspeed_timeout) {
3601 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3605 int ret = network_signalpoll(wifi);
3607 DBG("Fail to get max speed !!");
3608 wifi->automaxspeed_timeout = 0;
3616 static struct connman_network_driver network_driver = {
3618 .type = CONNMAN_NETWORK_TYPE_WIFI,
3619 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3620 .probe = network_probe,
3621 .remove = network_remove,
3622 .connect = network_connect,
3623 .disconnect = network_disconnect,
3626 static void interface_added(GSupplicantInterface *interface)
3628 const char *ifname = g_supplicant_interface_get_ifname(interface);
3629 const char *driver = g_supplicant_interface_get_driver(interface);
3630 #if defined TIZEN_EXT
3631 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3634 struct wifi_data *wifi;
3636 wifi = g_supplicant_interface_get_data(interface);
3638 wifi = get_pending_wifi_data(ifname);
3642 wifi->interface = interface;
3643 g_supplicant_interface_set_data(interface, wifi);
3644 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3645 wifi->p2p_device = true;
3648 DBG("ifname %s driver %s wifi %p tethering %d",
3649 ifname, driver, wifi, wifi->tethering);
3651 if (!wifi->device) {
3652 connman_error("WiFi device not set");
3656 connman_device_set_powered(wifi->device, true);
3657 #if defined TIZEN_EXT
3658 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3659 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3660 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3661 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3665 static bool is_idle(struct wifi_data *wifi)
3667 DBG("state %d", wifi->state);
3669 switch (wifi->state) {
3670 case G_SUPPLICANT_STATE_UNKNOWN:
3671 case G_SUPPLICANT_STATE_DISABLED:
3672 case G_SUPPLICANT_STATE_DISCONNECTED:
3673 case G_SUPPLICANT_STATE_INACTIVE:
3674 case G_SUPPLICANT_STATE_SCANNING:
3677 case G_SUPPLICANT_STATE_AUTHENTICATING:
3678 case G_SUPPLICANT_STATE_ASSOCIATING:
3679 case G_SUPPLICANT_STATE_ASSOCIATED:
3680 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3681 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3682 case G_SUPPLICANT_STATE_COMPLETED:
3689 static bool is_idle_wps(GSupplicantInterface *interface,
3690 struct wifi_data *wifi)
3692 /* First, let's check if WPS processing did not went wrong */
3693 if (g_supplicant_interface_get_wps_state(interface) ==
3694 G_SUPPLICANT_WPS_STATE_FAIL)
3697 /* Unlike normal connection, being associated while processing wps
3698 * actually means that we are idling. */
3699 switch (wifi->state) {
3700 case G_SUPPLICANT_STATE_UNKNOWN:
3701 case G_SUPPLICANT_STATE_DISABLED:
3702 case G_SUPPLICANT_STATE_DISCONNECTED:
3703 case G_SUPPLICANT_STATE_INACTIVE:
3704 case G_SUPPLICANT_STATE_SCANNING:
3705 case G_SUPPLICANT_STATE_ASSOCIATED:
3707 case G_SUPPLICANT_STATE_AUTHENTICATING:
3708 case G_SUPPLICANT_STATE_ASSOCIATING:
3709 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3710 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3711 case G_SUPPLICANT_STATE_COMPLETED:
3718 static bool handle_wps_completion(GSupplicantInterface *interface,
3719 struct connman_network *network,
3720 struct connman_device *device,
3721 struct wifi_data *wifi)
3725 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3727 const unsigned char *ssid, *wps_ssid;
3728 unsigned int ssid_len, wps_ssid_len;
3729 const char *wps_key;
3731 /* Checking if we got associated with requested
3733 ssid = connman_network_get_blob(network, "WiFi.SSID",
3736 wps_ssid = g_supplicant_interface_get_wps_ssid(
3737 interface, &wps_ssid_len);
3739 if (!wps_ssid || wps_ssid_len != ssid_len ||
3740 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3741 connman_network_set_associating(network, false);
3742 #if defined TIZEN_EXT
3743 g_supplicant_interface_disconnect(wifi->interface,
3744 disconnect_callback, wifi->network);
3746 connman_network_set_bool(network, "WiFi.UseWPS", false);
3747 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3749 g_supplicant_interface_disconnect(wifi->interface,
3750 disconnect_callback, wifi);
3755 wps_key = g_supplicant_interface_get_wps_key(interface);
3756 #if defined TIZEN_EXT
3757 /* Check the passphrase and encrypt it
3760 gchar *passphrase = g_strdup(wps_key);
3762 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3764 if (check_passphrase_ext(network, passphrase) < 0) {
3765 DBG("[WPS] Invalid passphrase");
3770 ret = send_encryption_request(passphrase, network);
3775 DBG("[WPS] Encryption request succeeded");
3777 DBG("[WPS] Encryption request failed %d", ret);
3780 connman_network_set_string(network, "WiFi.Passphrase",
3783 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3790 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3791 struct wifi_data *wifi)
3793 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3794 #if defined TIZEN_EXT
3795 wifi->assoc_code > 0 &&
3797 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3799 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3800 wifi->load_shaping_retries ++;
3803 wifi->load_shaping_retries = 0;
3807 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3808 struct connman_network *network,
3809 struct wifi_data *wifi)
3811 #if defined TIZEN_EXT
3812 const char *security;
3813 struct connman_service *service;
3815 if (wifi->connected)
3818 security = connman_network_get_string(network, "WiFi.Security");
3820 if (security && g_str_equal(security, "ieee8021x") == true &&
3821 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3823 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3828 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3831 struct connman_service *service;
3833 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3836 if (wifi->connected)
3840 service = connman_service_lookup_from_network(network);
3846 if (connman_service_get_favorite(service)) {
3847 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3852 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3857 #if defined TIZEN_EXT
3858 static bool handle_wifi_assoc_retry(struct connman_network *network,
3859 struct wifi_data *wifi)
3861 const char *security;
3863 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3864 connman_network_get_connecting(network) != true) {
3865 wifi->assoc_retry_count = 0;
3869 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3870 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3871 wifi->assoc_retry_count = 0;
3875 security = connman_network_get_string(network, "WiFi.Security");
3876 if (security && g_str_equal(security, "ieee8021x") == true &&
3877 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3878 wifi->assoc_retry_count = 0;
3882 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3883 wifi->assoc_retry_count = 0;
3885 /* Honestly it's not an invalid-key error,
3886 * however QA team recommends that the invalid-key error
3887 * might be better to display for user experience.
3889 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3898 static void interface_state(GSupplicantInterface *interface)
3900 struct connman_network *network;
3901 struct connman_device *device;
3902 struct wifi_data *wifi;
3903 GSupplicantState state = g_supplicant_interface_get_state(interface);
3907 wifi = g_supplicant_interface_get_data(interface);
3909 DBG("wifi %p interface state %d", wifi, state);
3914 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3915 if (wifi->tethering_param) {
3916 g_free(wifi->tethering_param->ssid);
3917 g_free(wifi->tethering_param);
3918 wifi->tethering_param = NULL;
3922 device = wifi->device;
3926 if (g_supplicant_interface_get_ready(interface) &&
3927 !wifi->interface_ready) {
3928 wifi->interface_ready = true;
3929 finalize_interface_creation(wifi);
3932 network = wifi->network;
3937 case G_SUPPLICANT_STATE_SCANNING:
3938 if (wifi->connected)
3939 connman_network_set_connected(network, false);
3943 case G_SUPPLICANT_STATE_AUTHENTICATING:
3944 case G_SUPPLICANT_STATE_ASSOCIATING:
3945 #if defined TIZEN_EXT
3946 reset_autoscan(device);
3948 stop_autoscan(device);
3951 if (!wifi->connected)
3952 connman_network_set_associating(network, true);
3956 case G_SUPPLICANT_STATE_COMPLETED:
3957 #if defined TIZEN_EXT
3958 /* though it should be already reset: */
3959 reset_autoscan(device);
3961 wifi->assoc_retry_count = 0;
3963 wifi->scan_pending_network = NULL;
3965 /* should be cleared scanning flag */
3966 bool scanning = connman_device_get_scanning(device);
3968 connman_device_set_scanning(device,
3969 CONNMAN_SERVICE_TYPE_WIFI, false);
3970 connman_device_unref(device);
3973 if (!wifi->automaxspeed_timeout) {
3974 DBG("Going to start signalpoll timer!!");
3975 int ret = network_signalpoll(wifi);
3977 DBG("Fail to get max speed !!");
3979 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
3982 g_hash_table_remove_all(failed_bssids);
3984 /* though it should be already stopped: */
3985 stop_autoscan(device);
3988 if (!handle_wps_completion(interface, network, device, wifi))
3991 connman_network_set_connected(network, true);
3993 wifi->disconnect_code = 0;
3994 wifi->assoc_code = 0;
3995 wifi->load_shaping_retries = 0;
3998 case G_SUPPLICANT_STATE_DISCONNECTED:
3999 #if defined TIZEN_EXT
4000 connman_network_set_maxspeed(network, 0);
4002 if (wifi->automaxspeed_timeout != 0) {
4003 g_source_remove(wifi->automaxspeed_timeout);
4004 wifi->automaxspeed_timeout = 0;
4005 DBG("Remove signalpoll timer!!");
4009 * If we're in one of the idle modes, we have
4010 * not started association yet and thus setting
4011 * those ones to FALSE could cancel an association
4014 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4016 if (is_idle_wps(interface, wifi))
4022 #if defined TIZEN_EXT
4023 if (handle_assoc_status_code(interface, wifi)) {
4024 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4025 guint bssid_length = 0;
4028 bssid_length = g_slist_length(bssid_list);
4030 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4031 network_connect(network);
4035 wifi->load_shaping_retries = 0;
4038 g_hash_table_remove_all(failed_bssids);
4040 if (handle_assoc_status_code(interface, wifi))
4044 /* If previous state was 4way-handshake, then
4045 * it's either: psk was incorrect and thus we retry
4046 * or if we reach the maximum retries we declare the
4048 if (handle_4way_handshake_failure(interface,
4052 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4053 switch (wifi->disconnect_code) {
4054 case 1: /* Unspecified reason */
4055 /* Let's assume it's because we got blocked */
4057 case 6: /* Class 2 frame received from nonauthenticated STA */
4058 connman_network_set_error(network,
4059 CONNMAN_NETWORK_ERROR_BLOCKED);
4066 #if defined TIZEN_EXT
4067 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4068 * Retry association until its retry count is expired */
4069 if (handle_wifi_assoc_retry(network, wifi) == true) {
4070 throw_wifi_scan(wifi->device, scan_callback);
4071 wifi->scan_pending_network = wifi->network;
4075 if(wifi->disconnect_code > 0){
4076 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4077 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4081 connman_network_set_connected(network, false);
4082 connman_network_set_associating(network, false);
4083 wifi->disconnecting = false;
4085 start_autoscan(device);
4089 case G_SUPPLICANT_STATE_INACTIVE:
4090 #if defined TIZEN_EXT
4091 if (handle_wps_completion(interface, network, device, wifi) == false)
4094 connman_network_set_associating(network, false);
4095 start_autoscan(device);
4099 case G_SUPPLICANT_STATE_UNKNOWN:
4100 case G_SUPPLICANT_STATE_DISABLED:
4101 case G_SUPPLICANT_STATE_ASSOCIATED:
4102 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4103 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4107 old_connected = wifi->connected;
4108 wifi->state = state;
4110 /* Saving wpa_s state policy:
4111 * If connected and if the state changes are roaming related:
4112 * --> We stay connected
4114 * --> We are connected
4116 * --> We are not connected
4119 case G_SUPPLICANT_STATE_AUTHENTICATING:
4120 case G_SUPPLICANT_STATE_ASSOCIATING:
4121 case G_SUPPLICANT_STATE_ASSOCIATED:
4122 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4123 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4124 if (wifi->connected)
4125 connman_warn("Probably roaming right now!"
4126 " Staying connected...");
4128 case G_SUPPLICANT_STATE_SCANNING:
4129 wifi->connected = false;
4132 start_autoscan(device);
4134 case G_SUPPLICANT_STATE_COMPLETED:
4135 wifi->connected = true;
4138 wifi->connected = false;
4145 static void interface_removed(GSupplicantInterface *interface)
4147 const char *ifname = g_supplicant_interface_get_ifname(interface);
4148 struct wifi_data *wifi;
4150 DBG("ifname %s", ifname);
4152 wifi = g_supplicant_interface_get_data(interface);
4154 #if defined TIZEN_EXT_WIFI_MESH
4155 if (wifi && wifi->mesh_interface) {
4156 DBG("Notify mesh interface remove");
4157 connman_mesh_notify_interface_remove(true);
4158 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4159 g_free(mesh_info->parent_ifname);
4160 g_free(mesh_info->ifname);
4161 g_free(mesh_info->identifier);
4163 wifi->mesh_interface = false;
4164 wifi->mesh_info = NULL;
4170 wifi->interface = NULL;
4172 if (wifi && wifi->tethering)
4175 if (!wifi || !wifi->device) {
4176 DBG("wifi interface already removed");
4180 connman_device_set_powered(wifi->device, false);
4182 check_p2p_technology();
4183 #if defined TIZEN_EXT_WIFI_MESH
4184 check_mesh_technology();
4188 static void set_device_type(const char *type, char dev_type[17])
4190 const char *oui = "0050F204";
4191 const char *category = "0001";
4192 const char *sub_category = "0000";
4194 if (!g_strcmp0(type, "handset")) {
4196 sub_category = "0005";
4197 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4198 sub_category = "0001";
4199 else if (!g_strcmp0(type, "server"))
4200 sub_category = "0002";
4201 else if (!g_strcmp0(type, "laptop"))
4202 sub_category = "0005";
4203 else if (!g_strcmp0(type, "desktop"))
4204 sub_category = "0006";
4205 else if (!g_strcmp0(type, "tablet"))
4206 sub_category = "0009";
4207 else if (!g_strcmp0(type, "watch"))
4210 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4213 static void p2p_support(GSupplicantInterface *interface)
4215 char dev_type[17] = {};
4216 const char *hostname;
4223 if (!g_supplicant_interface_has_p2p(interface))
4226 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4227 DBG("Could not register P2P technology driver");
4231 hostname = connman_utsname_get_hostname();
4233 hostname = "ConnMan";
4235 set_device_type(connman_machine_get_type(), dev_type);
4236 g_supplicant_interface_set_p2p_device_config(interface,
4237 hostname, dev_type);
4238 connman_peer_driver_register(&peer_driver);
4241 static void scan_started(GSupplicantInterface *interface)
4246 static void scan_finished(GSupplicantInterface *interface)
4248 #if defined TIZEN_EXT
4249 struct wifi_data *wifi;
4250 bool is_associating = false;
4251 static bool is_scanning = true;
4256 #if defined TIZEN_EXT
4257 wifi = g_supplicant_interface_get_data(interface);
4258 if (wifi && wifi->scan_pending_network) {
4259 network_connect(wifi->scan_pending_network);
4260 wifi->scan_pending_network = NULL;
4263 //service state - associating
4264 if(!wifi || !wifi->network)
4267 is_associating = connman_network_get_associating(wifi->network);
4268 if(is_associating && is_scanning){
4269 is_scanning = false;
4270 DBG("send scan for connecting");
4271 throw_wifi_scan(wifi->device, scan_callback);
4282 static void ap_create_fail(GSupplicantInterface *interface)
4284 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4287 if ((wifi->tethering) && (wifi->tethering_param)) {
4288 DBG("%s create AP fail \n",
4289 g_supplicant_interface_get_ifname(wifi->interface));
4291 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4292 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4293 wifi->tethering = false;
4295 ret = tech_set_tethering(wifi->tethering_param->technology,
4296 wifi->tethering_param->ssid->ssid,
4297 wifi->tethering_param->ssid->passphrase,
4298 wifi->bridge, true);
4300 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4301 connman_technology_tethering_notify(wifi_technology,false);
4304 g_free(wifi->tethering_param->ssid);
4305 g_free(wifi->tethering_param);
4306 wifi->tethering_param = NULL;
4312 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4314 unsigned char strength;
4316 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4318 #if !defined TIZEN_EXT
4325 #if defined TIZEN_EXT_WIFI_MESH
4326 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4328 GSupplicantInterface *interface;
4329 struct wifi_data *wifi;
4330 const char *name, *security;
4331 struct connman_mesh *connman_mesh;
4332 struct wifi_mesh_info *mesh_info;
4333 const unsigned char *bssid;
4334 const char *identifier;
4339 interface = g_supplicant_network_get_interface(supplicant_network);
4340 wifi = g_supplicant_interface_get_data(interface);
4341 if (!wifi || !wifi->mesh_interface) {
4342 DBG("Virtual Mesh interface not created");
4346 bssid = g_supplicant_network_get_bssid(supplicant_network);
4347 address = g_malloc0(19);
4348 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4349 bssid[2], bssid[3], bssid[4], bssid[5]);
4351 identifier = g_supplicant_network_get_identifier(supplicant_network);
4352 name = g_supplicant_network_get_name(supplicant_network);
4353 security = g_supplicant_network_get_security(supplicant_network);
4354 frequency = g_supplicant_network_get_frequency(supplicant_network);
4356 mesh_info = wifi->mesh_info;
4357 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4361 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4363 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4364 connman_mesh_set_name(connman_mesh, name);
4365 connman_mesh_set_security(connman_mesh, security);
4366 connman_mesh_set_frequency(connman_mesh, frequency);
4367 connman_mesh_set_address(connman_mesh, address);
4368 connman_mesh_set_index(connman_mesh, mesh_info->index);
4369 connman_mesh_set_strength(connman_mesh,
4370 calculate_strength(supplicant_network));
4371 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4373 ret = connman_mesh_register(connman_mesh);
4374 if (ret == -EALREADY)
4375 DBG("Mesh Peer is already registered");
4381 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4383 GSupplicantInterface *interface;
4384 struct wifi_data *wifi;
4385 struct connman_mesh *connman_mesh;
4386 struct wifi_mesh_info *mesh_info;
4387 const char *identifier;
4389 interface = g_supplicant_network_get_interface(supplicant_network);
4390 wifi = g_supplicant_interface_get_data(interface);
4391 if (!wifi || !wifi->mesh_interface) {
4392 DBG("Virtual Mesh interface not created");
4396 identifier = g_supplicant_network_get_identifier(supplicant_network);
4398 DBG("Failed to get Mesh Peer identifier");
4402 mesh_info = wifi->mesh_info;
4403 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4405 /* Do not unregister connected mesh peer */
4406 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4407 DBG("Mesh Peer %s is connected", identifier);
4410 DBG("Mesh Peer identifier %s removed", identifier);
4411 connman_mesh_unregister(connman_mesh);
4416 static void network_added(GSupplicantNetwork *supplicant_network)
4418 struct connman_network *network;
4419 GSupplicantInterface *interface;
4420 struct wifi_data *wifi;
4421 const char *name, *identifier, *security, *group, *mode;
4422 const unsigned char *ssid;
4423 unsigned int ssid_len;
4427 bool wps_advertizing;
4429 #if defined TIZEN_EXT
4430 GSList *vsie_list = NULL;
4431 const unsigned char *country_code;
4432 ieee80211_modes_e phy_mode;
4435 mode = g_supplicant_network_get_mode(supplicant_network);
4436 identifier = g_supplicant_network_get_identifier(supplicant_network);
4438 DBG("%s", identifier);
4440 if (!g_strcmp0(mode, "adhoc"))
4443 #if defined TIZEN_EXT_WIFI_MESH
4444 if (!g_strcmp0(mode, "mesh")) {
4445 mesh_peer_added(supplicant_network);
4450 interface = g_supplicant_network_get_interface(supplicant_network);
4451 wifi = g_supplicant_interface_get_data(interface);
4452 name = g_supplicant_network_get_name(supplicant_network);
4453 security = g_supplicant_network_get_security(supplicant_network);
4454 group = g_supplicant_network_get_identifier(supplicant_network);
4455 wps = g_supplicant_network_get_wps(supplicant_network);
4456 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4457 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4458 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4459 supplicant_network);
4464 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4466 network = connman_device_get_network(wifi->device, identifier);
4469 network = connman_network_create(identifier,
4470 CONNMAN_NETWORK_TYPE_WIFI);
4474 connman_network_set_index(network, wifi->index);
4476 if (connman_device_add_network(wifi->device, network) < 0) {
4477 connman_network_unref(network);
4481 wifi->networks = g_slist_prepend(wifi->networks, network);
4484 if (name && name[0] != '\0')
4485 connman_network_set_name(network, name);
4487 connman_network_set_blob(network, "WiFi.SSID",
4489 #if defined TIZEN_EXT
4490 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4492 connman_network_set_vsie_list(network, vsie_list);
4494 DBG("vsie_list is NULL");
4495 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4496 connman_network_set_countrycode(network, country_code);
4497 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4498 connman_network_set_phy_mode(network, phy_mode);
4500 connman_network_set_string(network, "WiFi.Security", security);
4501 connman_network_set_strength(network,
4502 calculate_strength(supplicant_network));
4503 connman_network_set_bool(network, "WiFi.WPS", wps);
4506 /* Is AP advertizing for WPS association?
4507 * If so, we decide to use WPS by default */
4508 if (wps_ready && wps_pbc &&
4510 #if !defined TIZEN_EXT
4511 connman_network_set_bool(network, "WiFi.UseWPS", true);
4513 DBG("wps is activating by ap but ignore it.");
4518 connman_network_set_frequency(network,
4519 g_supplicant_network_get_frequency(supplicant_network));
4520 #if defined TIZEN_EXT
4521 connman_network_set_bssid(network,
4522 g_supplicant_network_get_bssid(supplicant_network));
4523 connman_network_set_maxrate(network,
4524 g_supplicant_network_get_maxrate(supplicant_network));
4525 connman_network_set_enc_mode(network,
4526 g_supplicant_network_get_enc_mode(supplicant_network));
4527 connman_network_set_rsn_mode(network,
4528 g_supplicant_network_get_rsn_mode(supplicant_network));
4529 connman_network_set_keymgmt(network,
4530 g_supplicant_network_get_keymgmt(supplicant_network));
4531 connman_network_set_bool(network, "WiFi.HS20AP",
4532 g_supplicant_network_is_hs20AP(supplicant_network));
4533 connman_network_set_bssid_list(network,
4534 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4536 connman_network_set_available(network, true);
4537 connman_network_set_string(network, "WiFi.Mode", mode);
4539 #if defined TIZEN_EXT
4544 connman_network_set_group(network, group);
4546 #if defined TIZEN_EXT
4547 if (wifi_first_scan == true)
4548 found_with_first_scan = true;
4551 if (wifi->hidden && ssid) {
4552 #if defined TIZEN_EXT
4553 if (network_security(wifi->hidden->security) ==
4554 network_security(security) &&
4556 if (!g_strcmp0(wifi->hidden->security, security) &&
4558 wifi->hidden->ssid_len == ssid_len &&
4559 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4560 connman_network_connect_hidden(network,
4561 wifi->hidden->identity,
4562 wifi->hidden->passphrase,
4563 wifi->hidden->user_data);
4564 wifi->hidden->user_data = NULL;
4565 hidden_free(wifi->hidden);
4566 wifi->hidden = NULL;
4571 static void network_removed(GSupplicantNetwork *network)
4573 GSupplicantInterface *interface;
4574 struct wifi_data *wifi;
4575 const char *name, *identifier;
4576 struct connman_network *connman_network;
4578 #if defined TIZEN_EXT_WIFI_MESH
4580 mode = g_supplicant_network_get_mode(network);
4581 if (!g_strcmp0(mode, "mesh")) {
4582 mesh_peer_removed(network);
4587 interface = g_supplicant_network_get_interface(network);
4588 wifi = g_supplicant_interface_get_data(interface);
4589 identifier = g_supplicant_network_get_identifier(network);
4590 name = g_supplicant_network_get_name(network);
4592 DBG("name %s", name);
4597 connman_network = connman_device_get_network(wifi->device, identifier);
4598 if (!connman_network)
4601 #if defined TIZEN_EXT
4602 if (connman_network == wifi->scan_pending_network)
4603 wifi->scan_pending_network = NULL;
4605 if (connman_network == wifi->pending_network)
4606 wifi->pending_network = NULL;
4608 if(connman_network_get_connecting(connman_network) == true){
4609 connman_network_set_connected(connman_network, false);
4613 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4615 connman_device_remove_network(wifi->device, connman_network);
4616 connman_network_unref(connman_network);
4619 static void network_changed(GSupplicantNetwork *network, const char *property)
4621 GSupplicantInterface *interface;
4622 struct wifi_data *wifi;
4623 const char *name, *identifier;
4624 struct connman_network *connman_network;
4626 #if defined TIZEN_EXT
4627 const unsigned char *bssid;
4628 unsigned int maxrate;
4631 const unsigned char *country_code;
4632 ieee80211_modes_e phy_mode;
4636 interface = g_supplicant_network_get_interface(network);
4637 wifi = g_supplicant_interface_get_data(interface);
4638 identifier = g_supplicant_network_get_identifier(network);
4639 name = g_supplicant_network_get_name(network);
4641 DBG("name %s", name);
4646 connman_network = connman_device_get_network(wifi->device, identifier);
4647 if (!connman_network)
4650 if (g_str_equal(property, "Signal")) {
4651 connman_network_set_strength(connman_network,
4652 calculate_strength(network));
4653 connman_network_update(connman_network);
4656 #if defined TIZEN_EXT
4657 bssid = g_supplicant_network_get_bssid(network);
4658 maxrate = g_supplicant_network_get_maxrate(network);
4659 frequency = g_supplicant_network_get_frequency(network);
4660 wps = g_supplicant_network_get_wps(network);
4661 phy_mode = g_supplicant_network_get_phy_mode(network);
4663 connman_network_set_bssid(connman_network, bssid);
4664 connman_network_set_maxrate(connman_network, maxrate);
4665 connman_network_set_frequency(connman_network, frequency);
4666 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4667 country_code = g_supplicant_network_get_countrycode(network);
4668 connman_network_set_countrycode(connman_network, country_code);
4669 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4670 connman_network_set_bssid_list(connman_network, bssid_list);
4671 connman_network_set_phy_mode(connman_network, phy_mode);
4673 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4674 connman_network_get_associating(connman_network))
4675 network_connect(connman_network);
4679 static void network_associated(GSupplicantNetwork *network)
4681 GSupplicantInterface *interface;
4682 struct wifi_data *wifi;
4683 struct connman_network *connman_network;
4684 const char *identifier;
4688 interface = g_supplicant_network_get_interface(network);
4692 wifi = g_supplicant_interface_get_data(interface);
4696 identifier = g_supplicant_network_get_identifier(network);
4698 connman_network = connman_device_get_network(wifi->device, identifier);
4699 if (!connman_network)
4702 if (wifi->network) {
4703 if (wifi->network == connman_network)
4707 * This should never happen, we got associated with
4708 * a network different than the one we were expecting.
4710 DBG("Associated to %p while expecting %p",
4711 connman_network, wifi->network);
4713 connman_network_set_associating(wifi->network, false);
4716 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4718 wifi->network = connman_network_ref(connman_network);
4722 * Interface state changes callback (interface_state) is always
4723 * called before network_associated callback thus we need to call
4724 * interface_state again in order to process the new state now that
4725 * we have the network properly set.
4727 interface_state(interface);
4730 static void apply_peer_services(GSupplicantPeer *peer,
4731 struct connman_peer *connman_peer)
4733 const unsigned char *data;
4738 connman_peer_reset_services(connman_peer);
4740 data = g_supplicant_peer_get_widi_ies(peer, &length);
4742 connman_peer_add_service(connman_peer,
4743 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4747 static void add_station(const char *mac)
4749 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4753 static void remove_station(const char *mac)
4755 connman_technology_tethering_remove_station(mac);
4758 static void peer_found(GSupplicantPeer *peer)
4760 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4761 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4762 struct connman_peer *connman_peer;
4763 const char *identifier, *name;
4765 #if defined TIZEN_EXT
4769 identifier = g_supplicant_peer_get_identifier(peer);
4770 name = g_supplicant_peer_get_name(peer);
4772 DBG("ident: %s", identifier);
4774 connman_peer = connman_peer_get(wifi->device, identifier);
4778 connman_peer = connman_peer_create(identifier);
4779 connman_peer_set_name(connman_peer, name);
4780 connman_peer_set_device(connman_peer, wifi->device);
4781 apply_peer_services(peer, connman_peer);
4783 ret = connman_peer_register(connman_peer);
4784 if (ret < 0 && ret != -EALREADY)
4785 connman_peer_unref(connman_peer);
4787 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4790 static void peer_lost(GSupplicantPeer *peer)
4792 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4793 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4794 struct connman_peer *connman_peer;
4795 const char *identifier;
4800 identifier = g_supplicant_peer_get_identifier(peer);
4802 DBG("ident: %s", identifier);
4804 connman_peer = connman_peer_get(wifi->device, identifier);
4806 if (wifi->p2p_connecting &&
4807 wifi->pending_peer == connman_peer) {
4808 peer_connect_timeout(wifi);
4810 connman_peer_unregister(connman_peer);
4811 connman_peer_unref(connman_peer);
4814 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4817 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4819 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4820 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4821 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4822 struct connman_peer *connman_peer;
4823 const char *identifier;
4825 identifier = g_supplicant_peer_get_identifier(peer);
4827 DBG("ident: %s", identifier);
4832 connman_peer = connman_peer_get(wifi->device, identifier);
4837 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4838 apply_peer_services(peer, connman_peer);
4839 connman_peer_services_changed(connman_peer);
4841 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4842 if (!g_supplicant_peer_is_in_a_group(peer))
4843 p_state = CONNMAN_PEER_STATE_IDLE;
4845 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4847 case G_SUPPLICANT_PEER_GROUP_STARTED:
4849 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4850 p_state = CONNMAN_PEER_STATE_IDLE;
4852 case G_SUPPLICANT_PEER_GROUP_JOINED:
4853 connman_peer_set_iface_address(connman_peer,
4854 g_supplicant_peer_get_iface_address(peer));
4856 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4857 p_state = CONNMAN_PEER_STATE_IDLE;
4859 case G_SUPPLICANT_PEER_GROUP_FAILED:
4860 if (g_supplicant_peer_has_requested_connection(peer))
4861 p_state = CONNMAN_PEER_STATE_IDLE;
4863 p_state = CONNMAN_PEER_STATE_FAILURE;
4867 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4868 p_state == CONNMAN_PEER_STATE_FAILURE) {
4869 if (wifi->p2p_connecting
4870 && connman_peer == wifi->pending_peer)
4871 peer_cancel_timeout(wifi);
4873 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4876 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4879 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4880 GSupplicantInterface *g_iface;
4881 struct wifi_data *g_wifi;
4883 g_iface = g_supplicant_peer_get_group_interface(peer);
4887 g_wifi = g_supplicant_interface_get_data(g_iface);
4891 connman_peer_set_as_master(connman_peer,
4892 !g_supplicant_peer_is_client(peer));
4893 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4896 * If wpa_supplicant didn't create a dedicated p2p-group
4897 * interface then mark this interface as p2p_device to avoid
4898 * scan and auto-scan are launched on it while P2P is connected.
4900 if (!g_list_find(p2p_iface_list, g_wifi))
4901 wifi->p2p_device = true;
4904 connman_peer_set_state(connman_peer, p_state);
4907 static void peer_request(GSupplicantPeer *peer)
4909 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4910 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4911 struct connman_peer *connman_peer;
4912 const char *identifier;
4914 #if defined TIZEN_EXT
4919 identifier = g_supplicant_peer_get_identifier(peer);
4921 DBG("ident: %s", identifier);
4923 connman_peer = connman_peer_get(wifi->device, identifier);
4927 connman_peer_request_connection(connman_peer);
4930 #if defined TIZEN_EXT
4931 static void system_power_off(void)
4934 struct wifi_data *wifi;
4935 struct connman_service *service;
4936 struct connman_ipconfig *ipconfig_ipv4;
4938 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4939 for (list = iface_list; list; list = list->next) {
4942 if (wifi->network != NULL) {
4943 service = connman_service_lookup_from_network(wifi->network);
4944 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4945 __connman_dhcp_stop(ipconfig_ipv4);
4951 static void network_merged(GSupplicantNetwork *network)
4953 GSupplicantInterface *interface;
4954 GSupplicantState state;
4955 struct wifi_data *wifi;
4956 const char *identifier;
4957 struct connman_network *connman_network;
4961 interface = g_supplicant_network_get_interface(network);
4965 state = g_supplicant_interface_get_state(interface);
4966 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4969 wifi = g_supplicant_interface_get_data(interface);
4973 identifier = g_supplicant_network_get_identifier(network);
4975 connman_network = connman_device_get_network(wifi->device, identifier);
4976 if (!connman_network)
4979 DBG("merged identifier %s", identifier);
4981 if (wifi->connected == FALSE) {
4983 case G_SUPPLICANT_STATE_AUTHENTICATING:
4984 case G_SUPPLICANT_STATE_ASSOCIATING:
4985 case G_SUPPLICANT_STATE_ASSOCIATED:
4986 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4987 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4988 connman_network_set_associating(connman_network, TRUE);
4990 case G_SUPPLICANT_STATE_COMPLETED:
4991 connman_network_set_connected(connman_network, TRUE);
4994 DBG("Not handled the state : %d", state);
4999 ishs20AP = g_supplicant_network_is_hs20AP(network);
5002 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5003 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5004 connman_network_set_string(connman_network, "WiFi.EAP",
5006 connman_network_set_string(connman_network, "WiFi.Identity",
5007 g_supplicant_network_get_identity(network));
5008 connman_network_set_string(connman_network, "WiFi.Phase2",
5009 g_supplicant_network_get_phase2(network));
5014 wifi->network = connman_network;
5017 static void assoc_failed(void *user_data)
5019 struct connman_network *network = user_data;
5020 connman_network_set_associating(network, false);
5024 static void debug(const char *str)
5026 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5027 connman_debug("%s", str);
5030 static void disconnect_reasoncode(GSupplicantInterface *interface,
5033 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5036 wifi->disconnect_code = reasoncode;
5040 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5042 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5045 wifi->assoc_code = status_code;
5049 static const GSupplicantCallbacks callbacks = {
5050 .system_ready = system_ready,
5051 .system_killed = system_killed,
5052 .interface_added = interface_added,
5053 .interface_state = interface_state,
5054 .interface_removed = interface_removed,
5055 .p2p_support = p2p_support,
5056 .scan_started = scan_started,
5057 .scan_finished = scan_finished,
5058 .ap_create_fail = ap_create_fail,
5059 .network_added = network_added,
5060 .network_removed = network_removed,
5061 .network_changed = network_changed,
5062 .network_associated = network_associated,
5063 .add_station = add_station,
5064 .remove_station = remove_station,
5065 .peer_found = peer_found,
5066 .peer_lost = peer_lost,
5067 .peer_changed = peer_changed,
5068 .peer_request = peer_request,
5069 #if defined TIZEN_EXT
5070 .system_power_off = system_power_off,
5071 .network_merged = network_merged,
5072 .assoc_failed = assoc_failed,
5075 .disconnect_reasoncode = disconnect_reasoncode,
5076 .assoc_status_code = assoc_status_code,
5077 #if defined TIZEN_EXT_WIFI_MESH
5078 .mesh_support = mesh_support,
5079 .mesh_group_started = mesh_group_started,
5080 .mesh_group_removed = mesh_group_removed,
5081 .mesh_peer_connected = mesh_peer_connected,
5082 .mesh_peer_disconnected = mesh_peer_disconnected,
5087 static int tech_probe(struct connman_technology *technology)
5089 wifi_technology = technology;
5094 static void tech_remove(struct connman_technology *technology)
5096 wifi_technology = NULL;
5099 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5100 const char *passphrase)
5102 GSupplicantSSID *ap;
5104 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5108 ap->mode = G_SUPPLICANT_MODE_MASTER;
5109 #if defined TIZEN_EXT
5110 ap->ssid = (void *) ssid;
5114 ap->ssid_len = strlen(ssid);
5118 if (!passphrase || strlen(passphrase) == 0) {
5119 ap->security = G_SUPPLICANT_SECURITY_NONE;
5120 ap->passphrase = NULL;
5122 ap->security = G_SUPPLICANT_SECURITY_PSK;
5123 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5124 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5125 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5126 ap->passphrase = passphrase;
5132 static void ap_start_callback(int result, GSupplicantInterface *interface,
5135 struct wifi_tethering_info *info = user_data;
5137 DBG("result %d index %d bridge %s",
5138 result, info->wifi->index, info->wifi->bridge);
5140 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5141 connman_inet_remove_from_bridge(info->wifi->index,
5142 info->wifi->bridge);
5144 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5145 connman_technology_tethering_notify(info->technology, false);
5146 g_free(info->wifi->tethering_param->ssid);
5147 g_free(info->wifi->tethering_param);
5148 info->wifi->tethering_param = NULL;
5152 g_free(info->ifname);
5156 static void ap_create_callback(int result,
5157 GSupplicantInterface *interface,
5160 struct wifi_tethering_info *info = user_data;
5162 DBG("result %d ifname %s", result,
5163 g_supplicant_interface_get_ifname(interface));
5165 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5166 connman_inet_remove_from_bridge(info->wifi->index,
5167 info->wifi->bridge);
5169 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5170 connman_technology_tethering_notify(info->technology, false);
5171 g_free(info->wifi->tethering_param->ssid);
5172 g_free(info->wifi->tethering_param);
5173 info->wifi->tethering_param = NULL;
5177 g_free(info->ifname);
5183 info->wifi->interface = interface;
5184 g_supplicant_interface_set_data(interface, info->wifi);
5186 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5187 connman_error("Failed to set interface ap_scan property");
5189 g_supplicant_interface_connect(interface, info->ssid,
5190 ap_start_callback, info);
5193 static void sta_remove_callback(int result,
5194 GSupplicantInterface *interface,
5197 struct wifi_tethering_info *info = user_data;
5198 const char *driver = connman_option_get_string("wifi");
5200 DBG("ifname %s result %d ", info->ifname, result);
5202 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5203 info->wifi->tethering = false;
5204 connman_technology_tethering_notify(info->technology, false);
5206 g_free(info->ifname);
5210 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5211 g_free(info->wifi->tethering_param->ssid);
5212 g_free(info->wifi->tethering_param);
5213 info->wifi->tethering_param = NULL;
5218 info->wifi->interface = NULL;
5220 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5225 static int enable_wifi_tethering(struct connman_technology *technology,
5226 const char *bridge, const char *identifier,
5227 const char *passphrase, bool available)
5230 GSupplicantInterface *interface;
5231 struct wifi_data *wifi;
5232 struct wifi_tethering_info *info;
5237 for (list = iface_list; list; list = list->next) {
5240 DBG("wifi %p network %p pending_network %p", wifi,
5241 wifi->network, wifi->pending_network);
5243 interface = wifi->interface;
5248 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5251 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5253 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5254 DBG("%s does not support AP mode (detected)", ifname);
5258 mode = g_supplicant_interface_get_mode(interface);
5259 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5260 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5261 DBG("%s does not support AP mode (capability)", ifname);
5265 if (wifi->network && available)
5268 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5272 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5273 if (!wifi->tethering_param) {
5279 info->technology = technology;
5280 info->wifi->bridge = bridge;
5281 info->ssid = ssid_ap_init(identifier, passphrase);
5285 info->ifname = g_strdup(ifname);
5289 wifi->tethering_param->technology = technology;
5290 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5291 if (!wifi->tethering_param->ssid)
5294 info->wifi->tethering = true;
5295 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5297 berr = connman_technology_tethering_notify(technology, true);
5301 err = g_supplicant_interface_remove(interface,
5302 sta_remove_callback,
5305 DBG("tethering wifi %p ifname %s", wifi, ifname);
5310 g_free(info->ifname);
5313 g_free(wifi->tethering_param);
5314 wifi->tethering_param = NULL;
5317 * Remove bridge if it was correctly created but remove
5318 * operation failed. Instead, if bridge creation failed then
5319 * break out and do not try again on another interface,
5320 * bridge set-up does not depend on it.
5323 connman_technology_tethering_notify(technology, false);
5331 static int tech_set_tethering(struct connman_technology *technology,
5332 const char *identifier, const char *passphrase,
5333 const char *bridge, bool enabled)
5336 struct wifi_data *wifi;
5342 for (list = iface_list; list; list = list->next) {
5345 if (wifi->tethering) {
5346 wifi->tethering = false;
5348 connman_inet_remove_from_bridge(wifi->index,
5350 wifi->bridged = false;
5354 connman_technology_tethering_notify(technology, false);
5359 DBG("trying tethering for available devices");
5360 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5364 DBG("trying tethering for any device");
5365 err = enable_wifi_tethering(technology, bridge, identifier,
5372 static void regdom_callback(int result, const char *alpha2, void *user_data)
5376 if (!wifi_technology)
5382 connman_technology_regdom_notify(wifi_technology, alpha2);
5385 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5387 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5390 static struct connman_technology_driver tech_driver = {
5392 .type = CONNMAN_SERVICE_TYPE_WIFI,
5393 .probe = tech_probe,
5394 .remove = tech_remove,
5395 .set_tethering = tech_set_tethering,
5396 .set_regdom = tech_set_regdom,
5399 static int wifi_init(void)
5403 err = connman_network_driver_register(&network_driver);
5407 err = g_supplicant_register(&callbacks);
5409 connman_network_driver_unregister(&network_driver);
5413 err = connman_technology_driver_register(&tech_driver);
5415 g_supplicant_unregister(&callbacks);
5416 connman_network_driver_unregister(&network_driver);
5420 #if defined TIZEN_EXT
5421 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5426 static void wifi_exit(void)
5430 connman_technology_driver_unregister(&tech_driver);
5432 g_supplicant_unregister(&callbacks);
5434 connman_network_driver_unregister(&network_driver);
5436 #if defined TIZEN_EXT
5437 g_hash_table_unref(failed_bssids);
5441 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5442 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)