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
75 #define LOAD_SHAPING_MAX_RETRIES 3
78 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
81 static struct connman_technology *wifi_technology = NULL;
82 static struct connman_technology *p2p_technology = NULL;
84 enum wifi_ap_capability{
86 WIFI_AP_SUPPORTED = 1,
87 WIFI_AP_NOT_SUPPORTED = 2,
90 struct hidden_params {
92 unsigned int ssid_len;
94 char *anonymous_identity;
96 char *altsubject_match;
97 char *domain_suffix_match;
101 GSupplicantScanParams *scan_params;
106 * Used for autoscan "emulation".
107 * Should be removed when wpa_s autoscan support will be by default.
109 struct autoscan_params {
113 unsigned int timeout;
116 struct wifi_tethering_info {
117 struct wifi_data *wifi;
118 struct connman_technology *technology;
120 GSupplicantSSID *ssid;
125 struct connman_device *device;
126 struct connman_network *network;
127 struct connman_network *pending_network;
129 GSupplicantInterface *interface;
130 GSupplicantState state;
134 enum wifi_ap_capability ap_supported;
136 bool interface_ready;
142 int load_shaping_retries;
143 struct hidden_params *hidden;
144 bool postpone_hidden;
145 struct wifi_tethering_info *tethering_param;
147 * autoscan "emulation".
149 struct autoscan_params *autoscan;
151 GSupplicantScanParams *scan_params;
152 unsigned int p2p_find_timeout;
153 unsigned int p2p_connection_timeout;
154 struct connman_peer *pending_peer;
159 #if defined TIZEN_EXT
160 int assoc_retry_count;
161 struct connman_network *scan_pending_network;
162 bool allow_full_scan;
163 unsigned int automaxspeed_timeout;
167 #if defined TIZEN_EXT_WIFI_MESH
169 struct wifi_mesh_info *mesh_info;
173 #if defined TIZEN_EXT
177 #define TIZEN_ASSOC_RETRY_COUNT 4
179 static gboolean wifi_first_scan = false;
180 static gboolean found_with_first_scan = false;
181 static gboolean is_wifi_notifier_registered = false;
185 static GList *iface_list = NULL;
187 static GList *pending_wifi_device = NULL;
188 static GList *p2p_iface_list = NULL;
189 bool wfd_service_registered = false;
191 static void start_autoscan(struct connman_device *device);
193 static int tech_set_tethering(struct connman_technology *technology,
194 const char *identifier, const char *passphrase,
195 const char *bridge, bool enabled);
197 #if defined TIZEN_EXT
198 #define NETCONFIG_SERVICE "net.netconfig"
199 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
200 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
202 struct enc_method_call_data {
203 DBusConnection *connection;
204 struct connman_network *network;
207 static struct enc_method_call_data encrypt_request_data;
209 static void encryption_request_reply(DBusPendingCall *call,
214 DBusMessageIter args;
216 struct connman_service *service;
217 gchar* encrypted_value = NULL;
218 struct connman_network *network = encrypt_request_data.network;
222 reply = dbus_pending_call_steal_reply(call);
224 dbus_error_init(&error);
225 if (dbus_set_error_from_message(&error, reply)) {
226 DBG("send_encryption_request() %s %s", error.name, error.message);
227 dbus_error_free(&error);
231 if (dbus_message_iter_init(reply, &args) == FALSE)
234 dbus_message_iter_get_basic(&args, &out_data);
236 encrypted_value = g_strdup((const gchar *)out_data);
237 service = connman_service_lookup_from_network(network);
240 DBG("encryption result: no service");
244 if (connman_service_get_favorite(service)) {
245 __connman_service_set_passphrase(service, encrypted_value);
246 __connman_service_save(service);
248 connman_network_set_string(network, "WiFi.Passphrase",
251 DBG("encryption result: succeeded");
254 dbus_message_unref(reply);
255 dbus_pending_call_unref(call);
256 dbus_connection_unref(encrypt_request_data.connection);
257 g_free(encrypted_value);
259 encrypt_request_data.connection = NULL;
260 encrypt_request_data.network = NULL;
263 static int send_encryption_request(const char *passphrase,
264 struct connman_network *network)
266 DBusConnection *connection = NULL;
267 DBusMessage *msg = NULL;
268 DBusPendingCall *call;
271 DBG("Invalid parameter");
275 connection = connman_dbus_get_connection();
277 DBG("dbus connection does not exist");
281 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
282 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
284 dbus_connection_unref(connection);
288 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
291 if (!dbus_connection_send_with_reply(connection, msg,
292 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
293 dbus_message_unref(msg);
294 dbus_connection_unref(connection);
299 dbus_message_unref(msg);
300 dbus_connection_unref(connection);
304 encrypt_request_data.connection = connection;
305 encrypt_request_data.network = network;
307 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
308 dbus_message_unref(msg);
314 static int p2p_tech_probe(struct connman_technology *technology)
316 p2p_technology = technology;
321 static void p2p_tech_remove(struct connman_technology *technology)
323 p2p_technology = NULL;
326 static struct connman_technology_driver p2p_tech_driver = {
328 .type = CONNMAN_SERVICE_TYPE_P2P,
329 .probe = p2p_tech_probe,
330 .remove = p2p_tech_remove,
333 static bool is_p2p_connecting(void)
337 for (list = iface_list; list; list = list->next) {
338 struct wifi_data *wifi = list->data;
340 if (wifi->p2p_connecting)
347 static void add_pending_wifi_device(struct wifi_data *wifi)
349 if (g_list_find(pending_wifi_device, wifi))
352 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
355 #if defined TIZEN_EXT_WIFI_MESH
356 struct wifi_mesh_info {
357 struct wifi_data *wifi;
358 GSupplicantInterface *interface;
359 struct connman_mesh *mesh;
366 struct mesh_change_peer_status_info {
368 enum connman_mesh_peer_status peer_status;
369 mesh_change_peer_status_cb_t callback;
373 static struct connman_technology_driver mesh_tech_driver = {
375 .type = CONNMAN_SERVICE_TYPE_MESH,
378 static void mesh_interface_create_callback(int result,
379 GSupplicantInterface *interface,
382 struct wifi_mesh_info *mesh_info = user_data;
383 struct wifi_data *wifi;
384 bool success = false;
386 DBG("result %d ifname %s, mesh_info %p", result,
387 g_supplicant_interface_get_ifname(interface),
390 if (result < 0 || !mesh_info)
393 wifi = mesh_info->wifi;
395 mesh_info->interface = interface;
396 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
397 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
398 DBG("Mesh Interface identifier %s", mesh_info->identifier);
399 wifi->mesh_interface = true;
400 wifi->mesh_info = mesh_info;
401 g_supplicant_interface_set_data(interface, wifi);
405 connman_mesh_notify_interface_create(success);
408 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
411 struct wifi_data *wifi;
412 struct wifi_mesh_info *mesh_info;
413 const char *wifi_ifname;
414 bool parent_found = false;
415 const char *driver = "nl80211";
417 for (list = iface_list; list; list = list->next) {
420 if (!g_supplicant_interface_has_mesh(wifi->interface))
423 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
427 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
434 DBG("Parent interface %s doesn't exist", parent_ifname);
438 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
442 mesh_info->wifi = wifi;
443 mesh_info->ifname = g_strdup(ifname);
444 mesh_info->parent_ifname = g_strdup(parent_ifname);
446 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
447 mesh_interface_create_callback, mesh_info);
451 static void mesh_interface_remove_callback(int result,
452 GSupplicantInterface *interface,
455 struct wifi_data *wifi = user_data;
456 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
457 bool success = false;
459 DBG("result %d mesh_info %p", result, mesh_info);
461 if (result < 0 || !mesh_info)
464 mesh_info->interface = NULL;
465 g_free(mesh_info->parent_ifname);
466 g_free(mesh_info->ifname);
467 g_free(mesh_info->identifier);
469 wifi->mesh_interface = false;
470 wifi->mesh_info = NULL;
474 connman_mesh_notify_interface_remove(success);
477 static int remove_mesh_interface(const char *ifname)
480 struct wifi_data *wifi;
481 struct wifi_mesh_info *mesh_info;
482 bool mesh_if_found = false;
485 for (list = iface_list; list; list = list->next) {
488 if (wifi->mesh_interface) {
489 mesh_if_found = true;
494 if (!mesh_if_found) {
495 DBG("Mesh interface %s doesn't exist", ifname);
499 mesh_info = wifi->mesh_info;
500 ret = g_supplicant_interface_remove(mesh_info->interface,
501 mesh_interface_remove_callback, wifi);
508 static void mesh_disconnect_callback(int result,
509 GSupplicantInterface *interface, void *user_data)
511 struct connman_mesh *mesh = user_data;
513 DBG("result %d interface %p mesh %p", result, interface, mesh);
516 static int mesh_peer_disconnect(struct connman_mesh *mesh)
519 struct wifi_data *wifi;
520 struct wifi_mesh_info *mesh_info;
521 bool mesh_if_found = false;
522 GSupplicantInterface *interface;
524 for (list = iface_list; list; list = list->next) {
527 if (wifi->mesh_interface) {
528 mesh_if_found = true;
533 if (!mesh_if_found) {
534 DBG("Mesh interface is not created");
538 mesh_info = wifi->mesh_info;
540 interface = mesh_info->interface;
541 return g_supplicant_interface_disconnect(interface,
542 mesh_disconnect_callback, mesh);
545 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
548 struct connman_mesh *mesh = user_data;
549 DBG("mesh %p result %d", mesh, result);
552 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
554 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
557 static GSupplicantSecurity mesh_network_security(const char *security)
559 if (g_str_equal(security, "none"))
560 return G_SUPPLICANT_SECURITY_NONE;
561 else if (g_str_equal(security, "sae"))
562 return G_SUPPLICANT_SECURITY_SAE;
564 return G_SUPPLICANT_SECURITY_UNKNOWN;
567 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
570 const char *security;
575 memset(ssid, 0, sizeof(*ssid));
576 ssid->mode = G_SUPPLICANT_MODE_MESH;
578 security = connman_mesh_get_security(mesh);
579 ssid->security = mesh_network_security(security);
581 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
582 ssid->passphrase = connman_mesh_get_passphrase(mesh);
584 ssid->freq = connman_mesh_get_frequency(mesh);
585 name = connman_mesh_get_name(mesh);
587 ssid->ssid_len = strlen(name);
588 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
589 memcpy(ssid->ssid, name, ssid->ssid_len);
594 static int mesh_peer_connect(struct connman_mesh *mesh)
597 struct wifi_data *wifi;
598 struct wifi_mesh_info *mesh_info;
599 bool mesh_if_found = false;
600 GSupplicantInterface *interface;
601 GSupplicantSSID *ssid;
603 for (list = iface_list; list; list = list->next) {
606 if (wifi->mesh_interface) {
607 mesh_if_found = true;
612 if (!mesh_if_found) {
613 DBG("Mesh interface is not created");
617 mesh_info = wifi->mesh_info;
619 interface = mesh_info->interface;
621 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
625 mesh_info->mesh = mesh;
627 mesh_ssid_init(ssid, mesh);
628 return g_supplicant_interface_connect(interface, ssid,
629 mesh_connect_callback, mesh);
632 static void mesh_peer_change_status_callback(int result,
633 GSupplicantInterface *interface,
636 struct mesh_change_peer_status_info *data = user_data;
638 DBG("result %d Peer Status %d", result, data->peer_status);
640 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
641 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
642 connman_mesh_remove_connected_peer(data->peer_address, 52);
646 data->callback(result, data->user_data);
648 g_free(data->peer_address);
653 static int mesh_change_peer_status(const char *peer_address,
654 enum connman_mesh_peer_status status,
655 mesh_change_peer_status_cb_t callback, void *user_data)
658 struct wifi_data *wifi;
659 struct wifi_mesh_info *mesh_info;
660 bool mesh_if_found = false;
661 GSupplicantInterface *interface;
662 struct mesh_change_peer_status_info *data;
665 for (list = iface_list; list; list = list->next) {
668 if (wifi->mesh_interface) {
669 mesh_if_found = true;
674 if (!mesh_if_found) {
675 DBG("Mesh interface is not created");
679 mesh_info = wifi->mesh_info;
681 interface = mesh_info->interface;
684 case CONNMAN_MESH_PEER_ADD:
685 method = "MeshPeerAdd";
687 case CONNMAN_MESH_PEER_REMOVE:
688 method = "MeshPeerRemove";
691 DBG("Invalid method");
695 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
697 DBG("Memory allocation failed");
701 data->peer_address = g_strdup(peer_address);
702 data->peer_status = status;
703 data->callback = callback;
704 data->user_data = user_data;
706 return g_supplicant_interface_mesh_peer_change_status(interface,
707 mesh_peer_change_status_callback, peer_address, method,
711 static struct connman_mesh_driver mesh_driver = {
712 .add_interface = add_mesh_interface,
713 .remove_interface = remove_mesh_interface,
714 .connect = mesh_peer_connect,
715 .disconnect = mesh_peer_disconnect,
716 .change_peer_status = mesh_change_peer_status,
719 static void mesh_support(GSupplicantInterface *interface)
723 if (!g_supplicant_interface_has_mesh(interface))
726 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
727 DBG("Could not register Mesh technology driver");
731 connman_mesh_driver_register(&mesh_driver);
734 static void check_mesh_technology(void)
736 bool mesh_exists = false;
739 for (list = iface_list; list; list = list->next) {
740 struct wifi_data *w = list->data;
743 g_supplicant_interface_has_mesh(w->interface))
748 connman_technology_driver_unregister(&mesh_tech_driver);
749 connman_mesh_driver_unregister(&mesh_driver);
753 static void mesh_group_started(GSupplicantInterface *interface)
755 struct wifi_data *wifi;
756 struct wifi_mesh_info *mesh_info;
757 struct connman_mesh *mesh;
758 const unsigned char *ssid;
759 unsigned int ssid_len;
762 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
763 memcpy(name, ssid, ssid_len);
764 name[ssid_len] = '\0';
765 DBG("name %s", name);
766 wifi = g_supplicant_interface_get_data(interface);
767 DBG("wifi %p", wifi);
772 mesh_info = wifi->mesh_info;
776 mesh = mesh_info->mesh;
780 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
783 static void mesh_group_removed(GSupplicantInterface *interface)
785 struct wifi_data *wifi;
786 struct wifi_mesh_info *mesh_info;
787 struct connman_mesh *mesh;
788 const unsigned char *ssid;
789 unsigned int ssid_len;
790 int disconnect_reason;
793 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
794 memcpy(name, ssid, ssid_len);
795 name[ssid_len] = '\0';
796 DBG("name %s", name);
798 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
799 DBG("Disconnect Reason %d", disconnect_reason);
801 wifi = g_supplicant_interface_get_data(interface);
802 DBG("wifi %p", wifi);
807 mesh_info = wifi->mesh_info;
811 mesh = connman_get_connected_mesh_from_name(name);
813 DBG("%s is not connected", name);
814 mesh = connman_get_connecting_mesh_from_name(name);
816 DBG("%s is not connecting", name);
821 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
822 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
825 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
827 const char *peer_address;
829 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
834 DBG("Peer %s connected", peer_address);
835 connman_mesh_add_connected_peer(peer_address);
838 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
840 const char *peer_address;
843 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
848 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
850 DBG("Peer %s disconnected with reason %d", peer_address, reason);
851 connman_mesh_remove_connected_peer(peer_address, reason);
855 static struct wifi_data *get_pending_wifi_data(const char *ifname)
859 for (list = pending_wifi_device; list; list = list->next) {
860 struct wifi_data *wifi;
861 const char *dev_name;
864 if (!wifi || !wifi->device)
867 dev_name = connman_device_get_string(wifi->device, "Interface");
868 if (!g_strcmp0(ifname, dev_name)) {
869 pending_wifi_device = g_list_delete_link(
870 pending_wifi_device, list);
878 static void remove_pending_wifi_device(struct wifi_data *wifi)
882 link = g_list_find(pending_wifi_device, wifi);
887 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
890 static void peer_cancel_timeout(struct wifi_data *wifi)
892 if (wifi->p2p_connection_timeout > 0)
893 g_source_remove(wifi->p2p_connection_timeout);
895 wifi->p2p_connection_timeout = 0;
896 wifi->p2p_connecting = false;
898 if (wifi->pending_peer) {
899 connman_peer_unref(wifi->pending_peer);
900 wifi->pending_peer = NULL;
904 static gboolean peer_connect_timeout(gpointer data)
906 struct wifi_data *wifi = data;
910 if (wifi->p2p_connecting) {
911 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
912 GSupplicantPeer *gs_peer =
913 g_supplicant_interface_peer_lookup(wifi->interface,
914 connman_peer_get_identifier(wifi->pending_peer));
916 if (g_supplicant_peer_has_requested_connection(gs_peer))
917 state = CONNMAN_PEER_STATE_IDLE;
919 connman_peer_set_state(wifi->pending_peer, state);
922 peer_cancel_timeout(wifi);
927 static void peer_connect_callback(int result, GSupplicantInterface *interface,
930 struct wifi_data *wifi = user_data;
931 struct connman_peer *peer = wifi->pending_peer;
933 DBG("peer %p - %d", peer, result);
939 peer_connect_timeout(wifi);
943 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
945 wifi->p2p_connection_timeout = g_timeout_add_seconds(
946 P2P_CONNECTION_TIMEOUT,
947 peer_connect_timeout, wifi);
950 static int peer_connect(struct connman_peer *peer,
951 enum connman_peer_wps_method wps_method,
954 struct connman_device *device = connman_peer_get_device(peer);
955 GSupplicantPeerParams *peer_params;
956 GSupplicantPeer *gs_peer;
957 struct wifi_data *wifi;
961 DBG("peer %p", peer);
966 wifi = connman_device_get_data(device);
967 if (!wifi || !wifi->interface)
970 if (wifi->p2p_connecting)
973 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
974 connman_peer_get_identifier(peer));
978 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
979 pin = g_supplicant_peer_is_wps_pin(gs_peer);
981 switch (wps_method) {
982 case CONNMAN_PEER_WPS_UNKNOWN:
983 if ((pbc && pin) || pin)
986 case CONNMAN_PEER_WPS_PBC:
991 case CONNMAN_PEER_WPS_PIN:
992 if (!pin || !wps_pin)
997 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1001 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1003 peer_params->wps_pin = g_strdup(wps_pin);
1005 peer_params->master = connman_peer_service_is_master();
1007 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1008 peer_connect_callback, wifi);
1009 if (ret == -EINPROGRESS) {
1010 wifi->pending_peer = connman_peer_ref(peer);
1011 wifi->p2p_connecting = true;
1012 } else if (ret < 0) {
1013 g_free(peer_params->path);
1014 g_free(peer_params->wps_pin);
1015 g_free(peer_params);
1021 static int peer_disconnect(struct connman_peer *peer)
1023 struct connman_device *device = connman_peer_get_device(peer);
1024 GSupplicantPeerParams peer_params = {};
1025 GSupplicantPeer *gs_peer;
1026 struct wifi_data *wifi;
1029 DBG("peer %p", peer);
1034 wifi = connman_device_get_data(device);
1038 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1039 connman_peer_get_identifier(peer));
1043 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1045 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1047 g_free(peer_params.path);
1049 if (ret == -EINPROGRESS) {
1050 peer_cancel_timeout(wifi);
1051 wifi->p2p_device = false;
1057 struct peer_service_registration {
1058 peer_service_registration_cb_t callback;
1062 static bool is_service_wfd(const unsigned char *specs, int length)
1064 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1070 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1072 struct wifi_data *wifi = data;
1074 if (!wifi->interface ||
1075 !g_supplicant_interface_has_p2p(wifi->interface))
1078 if (!wifi->servicing) {
1079 g_supplicant_interface_p2p_listen(wifi->interface,
1080 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1086 static void register_wfd_service_cb(int result,
1087 GSupplicantInterface *iface, void *user_data)
1089 struct peer_service_registration *reg_data = user_data;
1094 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1096 if (reg_data && reg_data->callback) {
1097 reg_data->callback(result, reg_data->user_data);
1102 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1103 const unsigned char *spec,
1104 int spec_length, const unsigned char *query,
1105 int query_length, int version)
1107 GSupplicantP2PServiceParams *params;
1109 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1114 params->version = version;
1115 params->service = g_memdup(spec, spec_length);
1116 } else if (query_length > 0 && spec_length > 0) {
1117 params->query = g_memdup(query, query_length);
1118 params->query_length = query_length;
1120 params->response = g_memdup(spec, spec_length);
1121 params->response_length = spec_length;
1123 params->wfd_ies = g_memdup(spec, spec_length);
1124 params->wfd_ies_length = spec_length;
1130 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1135 g_free(params->service);
1136 g_free(params->query);
1137 g_free(params->response);
1138 g_free(params->wfd_ies);
1143 static int peer_register_wfd_service(const unsigned char *specification,
1144 int specification_length,
1145 peer_service_registration_cb_t callback,
1148 struct peer_service_registration *reg_data = NULL;
1149 static GSupplicantP2PServiceParams *params;
1154 if (wfd_service_registered)
1157 params = fill_in_peer_service_params(specification,
1158 specification_length, NULL, 0, 0);
1162 reg_data = g_try_malloc0(sizeof(*reg_data));
1168 reg_data->callback = callback;
1169 reg_data->user_data = user_data;
1171 ret = g_supplicant_set_widi_ies(params,
1172 register_wfd_service_cb, reg_data);
1173 if (ret < 0 && ret != -EINPROGRESS)
1176 wfd_service_registered = true;
1180 free_peer_service_params(params);
1186 static void register_peer_service_cb(int result,
1187 GSupplicantInterface *iface, void *user_data)
1189 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1190 struct peer_service_registration *reg_data = user_data;
1192 #if defined TIZEN_EXT
1200 apply_p2p_listen_on_iface(wifi, NULL);
1202 if (reg_data->callback)
1203 reg_data->callback(result, reg_data->user_data);
1208 static int peer_register_service(const unsigned char *specification,
1209 int specification_length,
1210 const unsigned char *query,
1211 int query_length, int version,
1212 peer_service_registration_cb_t callback,
1215 struct peer_service_registration *reg_data;
1216 GSupplicantP2PServiceParams *params;
1223 if (specification && !version && !query &&
1224 is_service_wfd(specification, specification_length)) {
1225 return peer_register_wfd_service(specification,
1226 specification_length, callback, user_data);
1229 reg_data = g_try_malloc0(sizeof(*reg_data));
1233 reg_data->callback = callback;
1234 reg_data->user_data = user_data;
1236 ret_f = -EOPNOTSUPP;
1238 for (list = iface_list; list; list = list->next) {
1239 struct wifi_data *wifi = list->data;
1240 GSupplicantInterface *iface = wifi->interface;
1242 if (!g_supplicant_interface_has_p2p(iface))
1245 params = fill_in_peer_service_params(specification,
1246 specification_length, query,
1247 query_length, version);
1254 ret_f = g_supplicant_interface_p2p_add_service(iface,
1255 register_peer_service_cb, params, reg_data);
1256 if (ret_f == 0 || ret_f == -EINPROGRESS)
1260 ret = g_supplicant_interface_p2p_add_service(iface,
1261 register_peer_service_cb, params, NULL);
1262 if (ret != 0 && ret != -EINPROGRESS)
1263 free_peer_service_params(params);
1266 if (ret_f != 0 && ret_f != -EINPROGRESS)
1272 static int peer_unregister_wfd_service(void)
1274 GSupplicantP2PServiceParams *params;
1277 if (!wfd_service_registered)
1280 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1284 wfd_service_registered = false;
1286 g_supplicant_set_widi_ies(params, NULL, NULL);
1288 for (list = iface_list; list; list = list->next) {
1289 struct wifi_data *wifi = list->data;
1291 if (!g_supplicant_interface_has_p2p(wifi->interface))
1295 if (!wifi->servicing || wifi->servicing < 0) {
1296 g_supplicant_interface_p2p_listen(wifi->interface,
1298 wifi->servicing = 0;
1305 static int peer_unregister_service(const unsigned char *specification,
1306 int specification_length,
1307 const unsigned char *query,
1308 int query_length, int version)
1310 GSupplicantP2PServiceParams *params;
1315 if (specification && !version && !query &&
1316 is_service_wfd(specification, specification_length)) {
1317 ret = peer_unregister_wfd_service();
1318 if (ret != 0 && ret != -EINPROGRESS)
1323 for (list = iface_list; list; list = list->next) {
1324 struct wifi_data *wifi = list->data;
1325 GSupplicantInterface *iface = wifi->interface;
1328 goto stop_listening;
1330 if (!g_supplicant_interface_has_p2p(iface))
1333 params = fill_in_peer_service_params(specification,
1334 specification_length, query,
1335 query_length, version);
1341 ret = g_supplicant_interface_p2p_del_service(iface, params);
1342 if (ret != 0 && ret != -EINPROGRESS)
1343 free_peer_service_params(params);
1346 if (!wifi->servicing || wifi->servicing < 0) {
1347 g_supplicant_interface_p2p_listen(iface, 0, 0);
1348 wifi->servicing = 0;
1355 static struct connman_peer_driver peer_driver = {
1356 .connect = peer_connect,
1357 .disconnect = peer_disconnect,
1358 .register_service = peer_register_service,
1359 .unregister_service = peer_unregister_service,
1362 static void handle_tethering(struct wifi_data *wifi)
1364 if (!wifi->tethering)
1373 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1375 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1378 wifi->bridged = true;
1381 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1383 struct connman_device *device = user_data;
1384 struct wifi_data *wifi = connman_device_get_data(device);
1389 DBG("index %d flags %d change %d", wifi->index, flags, change);
1391 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1393 DBG("interface up");
1395 DBG("interface down");
1398 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1399 if (flags & IFF_LOWER_UP) {
1402 handle_tethering(wifi);
1407 wifi->flags = flags;
1410 static int wifi_probe(struct connman_device *device)
1412 struct wifi_data *wifi;
1414 DBG("device %p", device);
1416 wifi = g_try_new0(struct wifi_data, 1);
1420 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1421 wifi->ap_supported = WIFI_AP_UNKNOWN;
1422 wifi->tethering_param = NULL;
1424 connman_device_set_data(device, wifi);
1425 wifi->device = connman_device_ref(device);
1427 wifi->index = connman_device_get_index(device);
1430 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1431 wifi_newlink, device);
1432 if (is_p2p_connecting())
1433 add_pending_wifi_device(wifi);
1435 iface_list = g_list_append(iface_list, wifi);
1440 static void remove_networks(struct connman_device *device,
1441 struct wifi_data *wifi)
1445 for (list = wifi->networks; list; list = list->next) {
1446 struct connman_network *network = list->data;
1448 connman_device_remove_network(device, network);
1449 connman_network_unref(network);
1452 g_slist_free(wifi->networks);
1453 wifi->networks = NULL;
1456 static void remove_peers(struct wifi_data *wifi)
1460 for (list = wifi->peers; list; list = list->next) {
1461 struct connman_peer *peer = list->data;
1463 connman_peer_unregister(peer);
1464 connman_peer_unref(peer);
1467 g_slist_free(wifi->peers);
1471 static void reset_autoscan(struct connman_device *device)
1473 struct wifi_data *wifi = connman_device_get_data(device);
1474 struct autoscan_params *autoscan;
1478 if (!wifi || !wifi->autoscan)
1481 autoscan = wifi->autoscan;
1483 if (autoscan->timeout == 0 && autoscan->interval == 0)
1486 g_source_remove(autoscan->timeout);
1488 autoscan->timeout = 0;
1489 autoscan->interval = 0;
1491 connman_device_unref(device);
1494 static void stop_autoscan(struct connman_device *device)
1496 const struct wifi_data *wifi = connman_device_get_data(device);
1498 if (!wifi || !wifi->autoscan)
1501 reset_autoscan(device);
1503 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1506 static void check_p2p_technology(void)
1508 bool p2p_exists = false;
1511 for (list = iface_list; list; list = list->next) {
1512 struct wifi_data *w = list->data;
1515 g_supplicant_interface_has_p2p(w->interface))
1520 connman_technology_driver_unregister(&p2p_tech_driver);
1521 connman_peer_driver_unregister(&peer_driver);
1525 static void wifi_remove(struct connman_device *device)
1527 struct wifi_data *wifi = connman_device_get_data(device);
1529 DBG("device %p wifi %p", device, wifi);
1534 stop_autoscan(device);
1536 if (wifi->p2p_device)
1537 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1539 iface_list = g_list_remove(iface_list, wifi);
1541 check_p2p_technology();
1542 #if defined TIZEN_EXT_WIFI_MESH
1543 check_mesh_technology();
1546 remove_pending_wifi_device(wifi);
1548 if (wifi->p2p_find_timeout) {
1549 g_source_remove(wifi->p2p_find_timeout);
1550 connman_device_unref(wifi->device);
1553 if (wifi->p2p_connection_timeout)
1554 g_source_remove(wifi->p2p_connection_timeout);
1556 #if defined TIZEN_EXT
1557 if (wifi->automaxspeed_timeout != 0) {
1558 g_source_remove(wifi->automaxspeed_timeout);
1559 wifi->automaxspeed_timeout = 0;
1563 remove_networks(device, wifi);
1566 connman_device_set_powered(device, false);
1567 connman_device_set_data(device, NULL);
1568 connman_device_unref(wifi->device);
1569 connman_rtnl_remove_watch(wifi->watch);
1571 g_supplicant_interface_set_data(wifi->interface, NULL);
1573 g_supplicant_interface_cancel(wifi->interface);
1575 if (wifi->scan_params)
1576 g_supplicant_free_scan_params(wifi->scan_params);
1578 g_free(wifi->autoscan);
1579 g_free(wifi->identifier);
1583 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1587 for (iter = list; iter; iter = g_slist_next(iter)) {
1588 struct scan_ssid *scan_ssid = iter->data;
1590 if (ssid_len == scan_ssid->ssid_len &&
1591 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1598 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1599 int freq, GSupplicantScanParams *scan_data,
1600 int driver_max_scan_ssids, char *ssid_name)
1603 struct scan_ssid *scan_ssid;
1605 if ((driver_max_scan_ssids == 0 ||
1606 driver_max_scan_ssids > scan_data->num_ssids) &&
1607 (hex_ssid || raw_ssid)) {
1609 unsigned int j = 0, hex;
1612 size_t hex_ssid_len = strlen(hex_ssid);
1614 ssid = g_try_malloc0(hex_ssid_len / 2);
1618 for (i = 0; i < hex_ssid_len; i += 2) {
1619 sscanf(hex_ssid + i, "%02x", &hex);
1628 * If we have already added hidden AP to the list,
1629 * then do not do it again. This might happen if you have
1630 * used or are using multiple wifi cards, so in that case
1631 * you might have multiple service files for same AP.
1633 if (is_duplicate(scan_data->ssids, ssid, j)) {
1639 scan_ssid = g_try_new(struct scan_ssid, 1);
1646 memcpy(scan_ssid->ssid, ssid, j);
1647 scan_ssid->ssid_len = j;
1648 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1651 scan_data->num_ssids++;
1653 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1654 scan_data->num_ssids);
1661 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1663 if (!scan_data->freqs) {
1664 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1665 if (!scan_data->freqs) {
1666 g_slist_free_full(scan_data->ssids, g_free);
1670 scan_data->num_freqs = 1;
1671 scan_data->freqs[0] = freq;
1673 bool duplicate = false;
1675 /* Don't add duplicate entries */
1676 for (i = 0; i < scan_data->num_freqs; i++) {
1677 if (scan_data->freqs[i] == freq) {
1684 scan_data->num_freqs++;
1685 scan_data->freqs = g_try_realloc(scan_data->freqs,
1686 sizeof(uint16_t) * scan_data->num_freqs);
1687 if (!scan_data->freqs) {
1688 g_slist_free_full(scan_data->ssids, g_free);
1691 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1698 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1700 struct connman_config_entry **entries;
1706 int num_ssids = 0, add_param_failed = 0;
1708 services = connman_storage_get_services();
1709 for (i = 0; services && services[i]; i++) {
1710 if (strncmp(services[i], "wifi_", 5) != 0)
1713 keyfile = connman_storage_load_service(services[i]);
1717 value = g_key_file_get_boolean(keyfile,
1718 services[i], "Hidden", NULL);
1720 g_key_file_free(keyfile);
1724 value = g_key_file_get_boolean(keyfile,
1725 services[i], "Favorite", NULL);
1727 g_key_file_free(keyfile);
1731 #if defined TIZEN_EXT
1732 value = g_key_file_get_boolean(keyfile,
1733 services[i], "AutoConnect", NULL);
1735 g_key_file_free(keyfile);
1740 ssid = g_key_file_get_string(keyfile,
1741 services[i], "SSID", NULL);
1743 name = g_key_file_get_string(keyfile, services[i], "Name",
1746 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1754 g_key_file_free(keyfile);
1758 * Check if there are any hidden AP that needs to be provisioned.
1760 entries = connman_config_get_entries("wifi");
1761 for (i = 0; entries && entries[i]; i++) {
1764 if (!entries[i]->hidden)
1767 if (!entries[i]->ssid) {
1768 ssid = entries[i]->name;
1771 ssid = entries[i]->ssid;
1772 len = entries[i]->ssid_len;
1778 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1785 connman_config_free_entries(entries);
1787 if (add_param_failed > 0)
1788 DBG("Unable to scan %d out of %d SSIDs",
1789 add_param_failed, num_ssids);
1791 g_strfreev(services);
1796 static int get_hidden_connections_params(struct wifi_data *wifi,
1797 GSupplicantScanParams *scan_params)
1799 int driver_max_ssids, i;
1800 GSupplicantScanParams *orig_params;
1803 * Scan hidden networks so that we can autoconnect to them.
1804 * We will assume 1 as a default number of ssid to scan.
1806 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1808 if (driver_max_ssids == 0)
1809 driver_max_ssids = 1;
1811 DBG("max ssids %d", driver_max_ssids);
1813 if (!wifi->scan_params) {
1814 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1815 if (!wifi->scan_params)
1818 if (get_hidden_connections(wifi->scan_params) == 0) {
1819 g_supplicant_free_scan_params(wifi->scan_params);
1820 wifi->scan_params = NULL;
1826 orig_params = wifi->scan_params;
1828 /* Let's transfer driver_max_ssids params */
1829 for (i = 0; i < driver_max_ssids; i++) {
1830 struct scan_ssid *ssid;
1832 if (!wifi->scan_params->ssids)
1835 ssid = orig_params->ssids->data;
1836 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1837 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1841 scan_params->num_ssids = i;
1842 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1844 scan_params->freqs = g_memdup(orig_params->freqs,
1845 sizeof(uint16_t) * orig_params->num_freqs);
1846 if (!scan_params->freqs)
1849 scan_params->num_freqs = orig_params->num_freqs;
1854 orig_params->num_ssids -= scan_params->num_ssids;
1856 return scan_params->num_ssids;
1859 g_slist_free_full(scan_params->ssids, g_free);
1860 g_supplicant_free_scan_params(wifi->scan_params);
1861 wifi->scan_params = NULL;
1866 static int throw_wifi_scan(struct connman_device *device,
1867 GSupplicantInterfaceCallback callback)
1869 struct wifi_data *wifi = connman_device_get_data(device);
1875 DBG("device %p %p", device, wifi->interface);
1877 if (wifi->tethering)
1879 #if defined TIZEN_EXT
1880 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1882 if (connman_device_get_scanning(device))
1886 connman_device_ref(device);
1888 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1891 connman_device_set_scanning(device,
1892 CONNMAN_SERVICE_TYPE_WIFI, true);
1894 connman_device_unref(device);
1899 static void hidden_free(struct hidden_params *hidden)
1904 if (hidden->scan_params)
1905 g_supplicant_free_scan_params(hidden->scan_params);
1906 g_free(hidden->identity);
1907 g_free(hidden->passphrase);
1908 g_free(hidden->security);
1912 #if defined TIZEN_EXT
1913 static void service_state_changed(struct connman_service *service,
1914 enum connman_service_state state);
1916 static int network_connect(struct connman_network *network);
1918 static struct connman_notifier notifier = {
1920 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1921 .service_state_changed = service_state_changed,
1924 static void service_state_changed(struct connman_service *service,
1925 enum connman_service_state state)
1927 enum connman_service_type type;
1929 type = connman_service_get_type(service);
1930 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1933 DBG("service %p state %d", service, state);
1936 case CONNMAN_SERVICE_STATE_READY:
1937 case CONNMAN_SERVICE_STATE_ONLINE:
1938 case CONNMAN_SERVICE_STATE_FAILURE:
1939 connman_notifier_unregister(¬ifier);
1940 is_wifi_notifier_registered = FALSE;
1942 __connman_device_request_scan(type);
1951 static void scan_callback(int result, GSupplicantInterface *interface,
1954 struct connman_device *device = user_data;
1955 struct wifi_data *wifi = connman_device_get_data(device);
1958 DBG("result %d wifi %p", result, wifi);
1961 if (wifi->hidden && !wifi->postpone_hidden) {
1962 connman_network_clear_hidden(wifi->hidden->user_data);
1963 hidden_free(wifi->hidden);
1964 wifi->hidden = NULL;
1967 if (wifi->scan_params) {
1968 g_supplicant_free_scan_params(wifi->scan_params);
1969 wifi->scan_params = NULL;
1974 connman_device_reset_scanning(device);
1976 /* User is connecting to a hidden AP, let's wait for finished event */
1977 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1978 GSupplicantScanParams *scan_params;
1981 wifi->postpone_hidden = false;
1982 scan_params = wifi->hidden->scan_params;
1983 wifi->hidden->scan_params = NULL;
1985 reset_autoscan(device);
1987 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1988 scan_callback, device);
1992 /* On error, let's recall scan_callback, which will cleanup */
1993 return scan_callback(ret, interface, user_data);
1996 #if defined TIZEN_EXT
1997 if (wifi && wifi->allow_full_scan) {
1999 DBG("Trigger Full Channel Scan");
2000 wifi->allow_full_scan = FALSE;
2002 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2003 scan_callback, device);
2007 /* On error, let's recall scan_callback, which will cleanup */
2008 return scan_callback(ret, interface, user_data);
2012 scanning = connman_device_get_scanning(device);
2014 connman_device_set_scanning(device,
2015 CONNMAN_SERVICE_TYPE_WIFI, false);
2017 if (result != -ENOLINK)
2018 #if defined TIZEN_EXT
2021 start_autoscan(device);
2024 * If we are here then we were scanning; however, if we are
2025 * also mid-flight disabling the interface, then wifi_disable
2026 * has already cleared the device scanning state and
2027 * unreferenced the device, obviating the need to do it here.
2031 connman_device_unref(device);
2033 #if defined TIZEN_EXT
2034 if (wifi && wifi->scan_pending_network && result != -EIO) {
2035 network_connect(wifi->scan_pending_network);
2036 wifi->scan_pending_network = NULL;
2037 connman_network_set_connecting(wifi->network);
2040 if (is_wifi_notifier_registered != true &&
2041 wifi_first_scan == true && found_with_first_scan == true) {
2042 wifi_first_scan = false;
2043 found_with_first_scan = false;
2045 connman_notifier_register(¬ifier);
2046 is_wifi_notifier_registered = true;
2051 static void scan_callback_hidden(int result,
2052 GSupplicantInterface *interface, void *user_data)
2054 struct connman_device *device = user_data;
2055 struct wifi_data *wifi = connman_device_get_data(device);
2056 GSupplicantScanParams *scan_params;
2059 DBG("result %d wifi %p", result, wifi);
2064 /* User is trying to connect to a hidden AP */
2065 if (wifi->hidden && wifi->postpone_hidden)
2068 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2072 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2073 ret = g_supplicant_interface_scan(wifi->interface,
2075 scan_callback_hidden,
2081 g_supplicant_free_scan_params(scan_params);
2084 scan_callback(result, interface, user_data);
2087 static gboolean autoscan_timeout(gpointer data)
2089 struct connman_device *device = data;
2090 struct wifi_data *wifi = connman_device_get_data(device);
2091 struct autoscan_params *autoscan;
2097 autoscan = wifi->autoscan;
2099 if (autoscan->interval <= 0) {
2100 interval = autoscan->base;
2103 interval = autoscan->interval * autoscan->base;
2105 #if defined TIZEN_EXT
2106 if (autoscan->interval >= autoscan->limit)
2108 if (interval > autoscan->limit)
2110 interval = autoscan->limit;
2112 throw_wifi_scan(wifi->device, scan_callback_hidden);
2115 DBG("interval %d", interval);
2117 autoscan->interval = interval;
2119 autoscan->timeout = g_timeout_add_seconds(interval,
2120 autoscan_timeout, device);
2125 static void start_autoscan(struct connman_device *device)
2127 struct wifi_data *wifi = connman_device_get_data(device);
2128 struct autoscan_params *autoscan;
2135 if (wifi->p2p_device)
2138 if (wifi->connected)
2141 autoscan = wifi->autoscan;
2145 if (autoscan->timeout > 0 || autoscan->interval > 0)
2148 connman_device_ref(device);
2150 autoscan_timeout(device);
2153 static struct autoscan_params *parse_autoscan_params(const char *params)
2155 struct autoscan_params *autoscan;
2160 DBG("Emulating autoscan");
2162 list_params = g_strsplit(params, ":", 0);
2163 if (list_params == 0)
2166 if (g_strv_length(list_params) < 3) {
2167 g_strfreev(list_params);
2171 base = atoi(list_params[1]);
2172 limit = atoi(list_params[2]);
2174 g_strfreev(list_params);
2176 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2178 DBG("Could not allocate memory for autoscan");
2182 DBG("base %d - limit %d", base, limit);
2183 autoscan->base = base;
2184 autoscan->limit = limit;
2189 static void setup_autoscan(struct wifi_data *wifi)
2191 if (!wifi->autoscan)
2192 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2194 start_autoscan(wifi->device);
2197 static void finalize_interface_creation(struct wifi_data *wifi)
2199 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2201 if (!wifi->device) {
2202 connman_error("WiFi device not set");
2206 connman_device_set_powered(wifi->device, true);
2208 if (!connman_setting_get_bool("BackgroundScanning"))
2211 if (wifi->p2p_device)
2214 setup_autoscan(wifi);
2217 static void interface_create_callback(int result,
2218 GSupplicantInterface *interface,
2221 struct wifi_data *wifi = user_data;
2223 DBG("result %d ifname %s, wifi %p", result,
2224 g_supplicant_interface_get_ifname(interface),
2227 if (result < 0 || !wifi)
2230 wifi->interface = interface;
2231 g_supplicant_interface_set_data(interface, wifi);
2233 if (g_supplicant_interface_get_ready(interface)) {
2234 wifi->interface_ready = true;
2235 finalize_interface_creation(wifi);
2239 static int wifi_enable(struct connman_device *device)
2241 struct wifi_data *wifi = connman_device_get_data(device);
2244 const char *driver = connman_option_get_string("wifi");
2247 DBG("device %p %p", device, wifi);
2249 index = connman_device_get_index(device);
2250 if (!wifi || index < 0)
2253 if (is_p2p_connecting())
2254 return -EINPROGRESS;
2256 interface = connman_inet_ifname(index);
2257 ret = g_supplicant_interface_create(interface, driver, NULL,
2258 interface_create_callback,
2265 return -EINPROGRESS;
2268 static int wifi_disable(struct connman_device *device)
2270 struct wifi_data *wifi = connman_device_get_data(device);
2273 DBG("device %p wifi %p", device, wifi);
2278 wifi->connected = false;
2279 wifi->disconnecting = false;
2281 if (wifi->pending_network)
2282 wifi->pending_network = NULL;
2284 stop_autoscan(device);
2286 if (wifi->p2p_find_timeout) {
2287 g_source_remove(wifi->p2p_find_timeout);
2288 wifi->p2p_find_timeout = 0;
2289 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2290 connman_device_unref(wifi->device);
2293 #if defined TIZEN_EXT
2294 if (wifi->automaxspeed_timeout != 0) {
2295 g_source_remove(wifi->automaxspeed_timeout);
2296 wifi->automaxspeed_timeout = 0;
2300 /* In case of a user scan, device is still referenced */
2301 if (connman_device_get_scanning(device)) {
2302 connman_device_set_scanning(device,
2303 CONNMAN_SERVICE_TYPE_WIFI, false);
2304 connman_device_unref(wifi->device);
2307 remove_networks(device, wifi);
2310 #if defined TIZEN_EXT
2311 wifi->scan_pending_network = NULL;
2313 if (is_wifi_notifier_registered == true) {
2314 connman_notifier_unregister(¬ifier);
2315 is_wifi_notifier_registered = false;
2319 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2323 return -EINPROGRESS;
2326 struct last_connected {
2332 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
2334 GTimeVal *aval = (GTimeVal *)a;
2335 GTimeVal *bval = (GTimeVal *)b;
2337 /* Note that the sort order is descending */
2338 if (aval->tv_sec < bval->tv_sec)
2341 if (aval->tv_sec > bval->tv_sec)
2347 static void free_entry(gpointer data)
2349 struct last_connected *entry = data;
2351 g_free(entry->ssid);
2355 static int get_latest_connections(int max_ssids,
2356 GSupplicantScanParams *scan_data)
2358 GSequenceIter *iter;
2359 GSequence *latest_list;
2360 struct last_connected *entry;
2369 latest_list = g_sequence_new(free_entry);
2373 services = connman_storage_get_services();
2374 for (i = 0; services && services[i]; i++) {
2375 if (strncmp(services[i], "wifi_", 5) != 0)
2378 keyfile = connman_storage_load_service(services[i]);
2382 str = g_key_file_get_string(keyfile,
2383 services[i], "Favorite", NULL);
2384 if (!str || g_strcmp0(str, "true")) {
2386 g_key_file_free(keyfile);
2391 str = g_key_file_get_string(keyfile,
2392 services[i], "AutoConnect", NULL);
2393 if (!str || g_strcmp0(str, "true")) {
2395 g_key_file_free(keyfile);
2400 str = g_key_file_get_string(keyfile,
2401 services[i], "Modified", NULL);
2403 g_key_file_free(keyfile);
2406 g_time_val_from_iso8601(str, &modified);
2409 ssid = g_key_file_get_string(keyfile,
2410 services[i], "SSID", NULL);
2412 freq = g_key_file_get_integer(keyfile, services[i],
2415 entry = g_try_new(struct last_connected, 1);
2417 g_sequence_free(latest_list);
2418 g_key_file_free(keyfile);
2424 entry->modified = modified;
2427 g_sequence_insert_sorted(latest_list, entry,
2433 g_key_file_free(keyfile);
2436 g_strfreev(services);
2438 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2440 iter = g_sequence_get_begin_iter(latest_list);
2442 for (i = 0; i < num_ssids; i++) {
2443 entry = g_sequence_get(iter);
2445 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2446 entry->modified.tv_sec);
2448 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2449 max_ssids, entry->ssid);
2451 iter = g_sequence_iter_next(iter);
2454 g_sequence_free(latest_list);
2458 static int wifi_scan_simple(struct connman_device *device)
2460 reset_autoscan(device);
2462 return throw_wifi_scan(device, scan_callback_hidden);
2465 static gboolean p2p_find_stop(gpointer data)
2467 struct connman_device *device = data;
2468 struct wifi_data *wifi = connman_device_get_data(device);
2473 wifi->p2p_find_timeout = 0;
2475 g_supplicant_interface_p2p_stop_find(wifi->interface);
2478 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2480 connman_device_unref(device);
2481 reset_autoscan(device);
2486 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2489 struct connman_device *device = user_data;
2490 struct wifi_data *wifi = connman_device_get_data(device);
2492 DBG("result %d wifi %p", result, wifi);
2497 if (wifi->p2p_find_timeout) {
2498 g_source_remove(wifi->p2p_find_timeout);
2499 wifi->p2p_find_timeout = 0;
2505 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2506 p2p_find_stop, device);
2507 if (!wifi->p2p_find_timeout)
2512 p2p_find_stop(device);
2515 static int p2p_find(struct connman_device *device)
2517 struct wifi_data *wifi;
2522 if (!p2p_technology)
2525 wifi = connman_device_get_data(device);
2527 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2530 reset_autoscan(device);
2531 connman_device_ref(device);
2533 ret = g_supplicant_interface_p2p_find(wifi->interface,
2534 p2p_find_callback, device);
2536 connman_device_unref(device);
2537 start_autoscan(device);
2539 connman_device_set_scanning(device,
2540 CONNMAN_SERVICE_TYPE_P2P, true);
2546 #if defined TIZEN_EXT
2547 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2550 struct connman_device *device = user_data;
2551 struct wifi_data *wifi = connman_device_get_data(device);
2554 DBG("result %d wifi %p", result, wifi);
2556 if (wifi && wifi->scan_params) {
2557 g_supplicant_free_scan_params(wifi->scan_params);
2558 wifi->scan_params = NULL;
2561 scanning = connman_device_get_scanning(device);
2563 connman_device_set_scanning(device,
2564 CONNMAN_SERVICE_TYPE_WIFI, false);
2565 connman_device_unref(device);
2569 static int wifi_specific_scan(enum connman_service_type type,
2570 struct connman_device *device, int scan_type,
2571 GSList *specific_scan_list, void *user_data)
2573 GSList *list = NULL;
2575 struct wifi_data *wifi = connman_device_get_data(device);
2576 GSupplicantScanParams *scan_params = NULL;
2577 struct scan_ssid *scan_ssid = NULL;
2586 if (wifi->p2p_device)
2589 if (type == CONNMAN_SERVICE_TYPE_P2P)
2590 return p2p_find(device);
2592 if (wifi->tethering)
2595 scanning = connman_device_get_scanning(device);
2599 DBG("scan_type: %d", scan_type);
2600 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2601 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2603 DBG("Failed to allocate memory.");
2607 for (list = specific_scan_list; list; list = list->next) {
2608 ssid = (char *)list->data;
2609 int ssid_len = strlen(ssid);
2611 scan_ssid = g_try_new0(struct scan_ssid, 1);
2613 DBG("Failed to allocate memory.");
2614 g_supplicant_free_scan_params(scan_params);
2618 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2619 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2620 scan_ssid->ssid_len = ssid_len;
2621 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2624 scan_params->num_ssids = count;
2626 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2628 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2630 DBG("Failed to allocate memory.");
2634 guint num_freqs = g_slist_length(specific_scan_list);
2635 DBG("num_freqs: %d", num_freqs);
2637 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2638 if (!scan_params->freqs) {
2639 DBG("Failed to allocate memory.");
2640 g_free(scan_params);
2645 for (list = specific_scan_list; list; list = list->next) {
2646 freq = (int)list->data;
2648 scan_params->freqs[count] = freq;
2649 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2652 scan_params->num_freqs = count;
2654 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2655 int freq_count, ap_count;
2656 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2658 DBG("Failed to allocate memory.");
2662 guint size = g_slist_length(specific_scan_list);
2664 scan_params->freqs = g_try_new0(uint16_t, size/2);
2665 if (!scan_params->freqs) {
2666 DBG("Failed to allocate memory.");
2667 g_free(scan_params);
2671 ap_count = freq_count = 0;
2672 for (list = specific_scan_list; list; list = list->next) {
2673 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2674 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2675 int ssid_len = strlen(ssid);
2677 scan_ssid = g_try_new0(struct scan_ssid, 1);
2679 DBG("Failed to allocate memory.");
2680 g_supplicant_free_scan_params(scan_params);
2684 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2685 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2686 scan_ssid->ssid_len = ssid_len;
2687 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2691 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2692 scan_params->freqs[freq_count] = freq;
2693 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2697 scan_params->num_ssids = ap_count;
2698 scan_params->num_freqs = freq_count;
2700 DBG("Invalid scan");
2704 reset_autoscan(device);
2705 connman_device_ref(device);
2707 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2708 specific_scan_callback, device);
2711 connman_device_set_scanning(device,
2712 CONNMAN_SERVICE_TYPE_WIFI, true);
2714 g_supplicant_free_scan_params(scan_params);
2715 connman_device_unref(device);
2722 #if defined TIZEN_EXT_WIFI_MESH
2723 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2726 struct connman_device *device = user_data;
2727 struct wifi_data *wifi = connman_device_get_data(device);
2730 DBG("result %d wifi %p", result, wifi);
2732 scanning = connman_device_get_scanning(device);
2734 connman_device_set_scanning(device,
2735 CONNMAN_SERVICE_TYPE_MESH, false);
2738 connman_device_unref(device);
2741 static int mesh_scan(struct connman_device *device)
2743 struct wifi_data *wifi;
2744 struct wifi_mesh_info *mesh_info;
2749 wifi = connman_device_get_data(device);
2751 if (!wifi->mesh_interface)
2754 mesh_info = wifi->mesh_info;
2755 reset_autoscan(device);
2756 connman_device_ref(device);
2758 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2759 mesh_scan_callback, device);
2761 connman_device_unref(device);
2763 connman_device_set_scanning(device,
2764 CONNMAN_SERVICE_TYPE_MESH, true);
2769 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2772 struct connman_device *device = user_data;
2773 struct wifi_data *wifi = connman_device_get_data(device);
2775 DBG("result %d wifi %p", result, wifi);
2777 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2780 static int mesh_abort_scan(enum connman_service_type type,
2781 struct connman_device *device)
2783 struct wifi_data *wifi = connman_device_get_data(device);
2784 struct wifi_mesh_info *mesh_info;
2788 if (!wifi || !wifi->mesh_interface)
2791 if (type != CONNMAN_SERVICE_TYPE_MESH)
2794 mesh_info = wifi->mesh_info;
2796 scanning = connman_device_get_scanning(device);
2800 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2801 abort_scan_callback, device);
2806 static int mesh_specific_scan(enum connman_service_type type,
2807 struct connman_device *device, const char *ssid,
2808 unsigned int freq, void *user_data)
2810 struct wifi_data *wifi = connman_device_get_data(device);
2811 GSupplicantScanParams *scan_params = NULL;
2812 struct wifi_mesh_info *mesh_info;
2813 struct scan_ssid *scan_ssid;
2817 if (!wifi || !wifi->mesh_interface)
2820 if (type != CONNMAN_SERVICE_TYPE_MESH)
2823 if (wifi->p2p_device)
2826 mesh_info = wifi->mesh_info;
2828 scanning = connman_device_get_scanning(device);
2832 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2836 scan_ssid = g_try_new(struct scan_ssid, 1);
2838 g_free(scan_params);
2842 scan_ssid->ssid_len = strlen(ssid);
2843 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2844 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2845 scan_params->num_ssids = 1;
2847 scan_params->freqs = g_try_new(uint16_t, 1);
2848 if (!scan_params->freqs) {
2849 g_slist_free_full(scan_params->ssids, g_free);
2850 g_free(scan_params);
2854 scan_params->freqs[0] = freq;
2855 scan_params->num_freqs = 1;
2857 reset_autoscan(device);
2858 connman_device_ref(device);
2860 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2861 mesh_scan_callback, device);
2864 connman_device_set_scanning(device,
2865 CONNMAN_SERVICE_TYPE_MESH, true);
2867 g_supplicant_free_scan_params(scan_params);
2868 connman_device_unref(device);
2876 * Note that the hidden scan is only used when connecting to this specific
2877 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2879 static int wifi_scan(enum connman_service_type type,
2880 struct connman_device *device,
2881 const char *ssid, unsigned int ssid_len,
2882 const char *identity, const char* passphrase,
2883 const char *security, void *user_data)
2885 struct wifi_data *wifi = connman_device_get_data(device);
2886 GSupplicantScanParams *scan_params = NULL;
2887 struct scan_ssid *scan_ssid;
2888 struct hidden_params *hidden;
2890 int driver_max_ssids = 0;
2897 if (wifi->p2p_device)
2900 if (wifi->tethering)
2903 if (type == CONNMAN_SERVICE_TYPE_P2P)
2904 return p2p_find(device);
2906 #if defined TIZEN_EXT_WIFI_MESH
2907 if (type == CONNMAN_SERVICE_TYPE_MESH)
2908 return mesh_scan(device);
2911 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2913 scanning = connman_device_get_scanning(device);
2915 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2919 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2921 DBG("max ssids %d", driver_max_ssids);
2922 if (driver_max_ssids == 0)
2923 return wifi_scan_simple(device);
2927 if (scanning && wifi->hidden && wifi->postpone_hidden)
2933 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2938 scan_ssid = g_try_new(struct scan_ssid, 1);
2940 g_free(scan_params);
2944 memcpy(scan_ssid->ssid, ssid, ssid_len);
2945 scan_ssid->ssid_len = ssid_len;
2946 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2948 scan_params->num_ssids = 1;
2950 hidden = g_try_new0(struct hidden_params, 1);
2952 g_supplicant_free_scan_params(scan_params);
2957 hidden_free(wifi->hidden);
2958 wifi->hidden = NULL;
2961 memcpy(hidden->ssid, ssid, ssid_len);
2962 hidden->ssid_len = ssid_len;
2963 hidden->identity = g_strdup(identity);
2964 hidden->passphrase = g_strdup(passphrase);
2965 hidden->security = g_strdup(security);
2966 hidden->user_data = user_data;
2967 wifi->hidden = hidden;
2970 /* Let's keep this active scan for later,
2971 * when current scan will be over. */
2972 wifi->postpone_hidden = TRUE;
2973 hidden->scan_params = scan_params;
2977 } else if (wifi->connected) {
2978 g_supplicant_free_scan_params(scan_params);
2979 return wifi_scan_simple(device);
2981 ret = get_latest_connections(driver_max_ssids, scan_params);
2983 g_supplicant_free_scan_params(scan_params);
2984 return wifi_scan_simple(device);
2988 connman_device_ref(device);
2990 reset_autoscan(device);
2992 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2993 scan_callback, device);
2996 connman_device_set_scanning(device,
2997 CONNMAN_SERVICE_TYPE_WIFI, true);
2998 #if defined TIZEN_EXT
2999 /*To allow the Full Scan after ssid based scan, set the flag here
3000 It is required because Tizen does not use the ConnMan specific
3001 backgroung Scan feature.Tizen has added the BG Scan feature in
3002 net-config. To sync with up ConnMan, we need to issue the Full Scan
3003 after SSID specific scan.*/
3004 wifi->allow_full_scan = TRUE;
3007 g_supplicant_free_scan_params(scan_params);
3008 connman_device_unref(device);
3011 hidden_free(wifi->hidden);
3012 wifi->hidden = NULL;
3019 static void wifi_regdom_callback(int result,
3023 struct connman_device *device = user_data;
3025 connman_device_regdom_notify(device, result, alpha2);
3027 connman_device_unref(device);
3030 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3032 struct wifi_data *wifi = connman_device_get_data(device);
3038 connman_device_ref(device);
3040 ret = g_supplicant_interface_set_country(wifi->interface,
3041 wifi_regdom_callback,
3044 connman_device_unref(device);
3049 static struct connman_device_driver wifi_ng_driver = {
3051 .type = CONNMAN_DEVICE_TYPE_WIFI,
3052 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3053 .probe = wifi_probe,
3054 .remove = wifi_remove,
3055 .enable = wifi_enable,
3056 .disable = wifi_disable,
3058 .set_regdom = wifi_set_regdom,
3059 #if defined TIZEN_EXT
3060 .specific_scan = wifi_specific_scan,
3062 #if defined TIZEN_EXT_WIFI_MESH
3063 .abort_scan = mesh_abort_scan,
3064 .mesh_specific_scan = mesh_specific_scan,
3068 static void system_ready(void)
3072 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3073 connman_error("Failed to register WiFi driver");
3076 static void system_killed(void)
3080 connman_device_driver_unregister(&wifi_ng_driver);
3083 static int network_probe(struct connman_network *network)
3085 DBG("network %p", network);
3090 static void network_remove(struct connman_network *network)
3092 struct connman_device *device = connman_network_get_device(network);
3093 struct wifi_data *wifi;
3095 DBG("network %p", network);
3097 wifi = connman_device_get_data(device);
3101 if (wifi->network != network)
3104 wifi->network = NULL;
3106 #if defined TIZEN_EXT
3107 wifi->disconnecting = false;
3109 if (wifi->pending_network == network)
3110 wifi->pending_network = NULL;
3112 if (wifi->scan_pending_network == network)
3113 wifi->scan_pending_network = NULL;
3117 static void connect_callback(int result, GSupplicantInterface *interface,
3120 #if defined TIZEN_EXT
3122 struct wifi_data *wifi;
3124 struct connman_network *network = user_data;
3126 DBG("network %p result %d", network, result);
3128 #if defined TIZEN_EXT
3129 set_connman_bssid(RESET_BSSID, NULL);
3131 for (list = iface_list; list; list = list->next) {
3134 if (wifi && wifi->network == network)
3138 /* wifi_data may be invalid because wifi is already disabled */
3143 if (result == -ENOKEY) {
3144 connman_network_set_error(network,
3145 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3146 } else if (result < 0) {
3147 connman_network_set_error(network,
3148 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3151 connman_network_unref(network);
3154 static GSupplicantSecurity network_security(const char *security)
3156 if (g_str_equal(security, "none"))
3157 return G_SUPPLICANT_SECURITY_NONE;
3158 else if (g_str_equal(security, "wep"))
3159 return G_SUPPLICANT_SECURITY_WEP;
3160 else if (g_str_equal(security, "psk"))
3161 return G_SUPPLICANT_SECURITY_PSK;
3162 else if (g_str_equal(security, "wpa"))
3163 return G_SUPPLICANT_SECURITY_PSK;
3164 else if (g_str_equal(security, "rsn"))
3165 return G_SUPPLICANT_SECURITY_PSK;
3166 else if (g_str_equal(security, "ieee8021x"))
3167 return G_SUPPLICANT_SECURITY_IEEE8021X;
3168 #if defined TIZEN_EXT
3169 else if (g_str_equal(security, "ft_psk") == TRUE)
3170 return G_SUPPLICANT_SECURITY_FT_PSK;
3171 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3172 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3175 return G_SUPPLICANT_SECURITY_UNKNOWN;
3178 #if defined TIZEN_EXT
3179 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3181 if (security == NULL)
3182 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3184 if (g_str_equal(security, "FT") == TRUE)
3185 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3186 else if (g_str_equal(security, "CCKM") == TRUE)
3187 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3189 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3193 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3195 const char *security;
3196 #if defined TIZEN_EXT
3197 const void *ssid_data;
3200 memset(ssid, 0, sizeof(*ssid));
3201 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3202 #if defined TIZEN_EXT
3203 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3205 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3210 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3212 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3215 ssid->scan_ssid = 1;
3216 security = connman_network_get_string(network, "WiFi.Security");
3217 ssid->security = network_security(security);
3218 ssid->passphrase = connman_network_get_string(network,
3220 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3223 * If our private key password is unset,
3224 * we use the supplied passphrase. That is needed
3225 * for PEAP where 2 passphrases (identity and client
3226 * cert may have to be provided.
3228 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3229 connman_network_set_string(network,
3230 "WiFi.PrivateKeyPassphrase",
3232 /* We must have an identity for both PEAP and TLS */
3233 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3235 /* Use agent provided identity as a fallback */
3236 if (!ssid->identity || strlen(ssid->identity) == 0)
3237 ssid->identity = connman_network_get_string(network,
3238 "WiFi.AgentIdentity");
3240 ssid->anonymous_identity = connman_network_get_string(network,
3241 "WiFi.AnonymousIdentity");
3242 ssid->ca_cert_path = connman_network_get_string(network,
3244 ssid->subject_match = connman_network_get_string(network,
3245 "WiFi.SubjectMatch");
3246 ssid->altsubject_match = connman_network_get_string(network,
3247 "WiFi.AltSubjectMatch");
3248 ssid->domain_suffix_match = connman_network_get_string(network,
3249 "WiFi.DomainSuffixMatch");
3250 ssid->domain_match = connman_network_get_string(network,
3251 "WiFi.DomainMatch");
3252 ssid->client_cert_path = connman_network_get_string(network,
3253 "WiFi.ClientCertFile");
3254 ssid->private_key_path = connman_network_get_string(network,
3255 "WiFi.PrivateKeyFile");
3256 ssid->private_key_passphrase = connman_network_get_string(network,
3257 "WiFi.PrivateKeyPassphrase");
3258 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3260 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3261 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3263 #if defined TIZEN_EXT
3264 ssid->bssid = connman_network_get_bssid(network);
3266 ssid->eap_keymgmt = network_eap_keymgmt(
3267 connman_network_get_string(network, "WiFi.KeymgmtType"));
3268 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3270 if(g_strcmp0(ssid->eap, "fast") == 0)
3271 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3273 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3274 ssid->bssid_for_connect_len = 6;
3275 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3276 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3277 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3278 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3279 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3281 ssid->freq = connman_network_get_frequency(network);
3285 if (connman_setting_get_bool("BackgroundScanning"))
3286 ssid->bgscan = BGSCAN_DEFAULT;
3289 static int network_connect(struct connman_network *network)
3291 struct connman_device *device = connman_network_get_device(network);
3292 struct wifi_data *wifi;
3293 GSupplicantInterface *interface;
3294 GSupplicantSSID *ssid;
3296 DBG("network %p", network);
3301 wifi = connman_device_get_data(device);
3305 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3309 interface = wifi->interface;
3311 ssid_init(ssid, network);
3313 if (wifi->disconnecting) {
3314 wifi->pending_network = network;
3315 #if defined TIZEN_EXT
3320 wifi->network = connman_network_ref(network);
3322 #if defined TIZEN_EXT
3323 wifi->scan_pending_network = NULL;
3326 return g_supplicant_interface_connect(interface, ssid,
3327 connect_callback, network);
3330 return -EINPROGRESS;
3333 static void disconnect_callback(int result, GSupplicantInterface *interface,
3336 #if defined TIZEN_EXT
3338 struct wifi_data *wifi;
3339 struct connman_network *network = user_data;
3341 DBG("network %p result %d", network, result);
3343 for (list = iface_list; list; list = list->next) {
3346 if (wifi->network == NULL && wifi->disconnecting == true)
3347 wifi->disconnecting = false;
3349 if (wifi->network == network)
3353 /* wifi_data may be invalid because wifi is already disabled */
3358 struct wifi_data *wifi = user_data;
3361 DBG("result %d supplicant interface %p wifi %p",
3362 result, interface, wifi);
3364 if (result == -ECONNABORTED) {
3365 DBG("wifi interface no longer available");
3369 if (wifi->network) {
3370 connman_network_set_connected(wifi->network, false);
3371 wifi->network = NULL;
3374 wifi->disconnecting = false;
3375 wifi->connected = false;
3377 if (wifi->pending_network) {
3378 network_connect(wifi->pending_network);
3379 wifi->pending_network = NULL;
3382 start_autoscan(wifi->device);
3385 static int network_disconnect(struct connman_network *network)
3387 struct connman_device *device = connman_network_get_device(network);
3388 struct wifi_data *wifi;
3390 #if defined TIZEN_EXT
3391 struct connman_service *service;
3394 DBG("network %p", network);
3396 wifi = connman_device_get_data(device);
3397 if (!wifi || !wifi->interface)
3400 #if defined TIZEN_EXT
3401 if (connman_network_get_associating(network) == true) {
3402 connman_network_clear_associating(network);
3403 connman_network_set_bool(network, "WiFi.UseWPS", false);
3405 service = connman_service_lookup_from_network(network);
3407 if (service != NULL &&
3408 (__connman_service_is_connected_state(service,
3409 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3410 __connman_service_is_connected_state(service,
3411 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3412 (connman_service_get_favorite(service) == false))
3413 __connman_service_set_passphrase(service, NULL);
3416 if (wifi->pending_network == network)
3417 wifi->pending_network = NULL;
3419 if (wifi->scan_pending_network == network)
3420 wifi->scan_pending_network = NULL;
3423 connman_network_set_associating(network, false);
3425 if (wifi->disconnecting)
3428 wifi->disconnecting = true;
3430 #if defined TIZEN_EXT
3431 err = g_supplicant_interface_disconnect(wifi->interface,
3432 disconnect_callback, network);
3434 err = g_supplicant_interface_disconnect(wifi->interface,
3435 disconnect_callback, wifi);
3439 wifi->disconnecting = false;
3444 #if defined TIZEN_EXT
3445 static void set_connection_mode(struct connman_network *network,
3448 ieee80211_modes_e phy_mode;
3449 connection_mode_e conn_mode;
3451 phy_mode = connman_network_get_phy_mode(network);
3453 case IEEE80211_MODE_B:
3454 if (linkspeed > 0 && linkspeed <= 11)
3455 conn_mode = CONNECTION_MODE_IEEE80211B;
3457 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3460 case IEEE80211_MODE_BG:
3461 if (linkspeed > 0 && linkspeed <= 11)
3462 conn_mode = CONNECTION_MODE_IEEE80211B;
3463 else if (linkspeed > 11 && linkspeed <= 54)
3464 conn_mode = CONNECTION_MODE_IEEE80211G;
3466 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3469 case IEEE80211_MODE_BGN:
3470 if (linkspeed > 0 && linkspeed <= 11)
3471 conn_mode = CONNECTION_MODE_IEEE80211B;
3472 else if (linkspeed > 11 && linkspeed <= 54)
3473 conn_mode = CONNECTION_MODE_IEEE80211G;
3474 else if (linkspeed > 54 && linkspeed <= 450)
3475 conn_mode = CONNECTION_MODE_IEEE80211N;
3477 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3480 case IEEE80211_MODE_A:
3481 if (linkspeed > 0 && linkspeed <= 54)
3482 conn_mode = CONNECTION_MODE_IEEE80211A;
3484 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3487 case IEEE80211_MODE_AN:
3488 if (linkspeed > 0 && linkspeed <= 54)
3489 conn_mode = CONNECTION_MODE_IEEE80211A;
3490 else if (linkspeed > 54 && linkspeed <= 450)
3491 conn_mode = CONNECTION_MODE_IEEE80211N;
3493 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3496 case IEEE80211_MODE_ANAC:
3497 if (linkspeed > 0 && linkspeed <= 54)
3498 conn_mode = CONNECTION_MODE_IEEE80211A;
3499 else if (linkspeed > 54 && linkspeed <= 450)
3500 conn_mode = CONNECTION_MODE_IEEE80211N;
3501 else if (linkspeed > 450 && linkspeed <= 1300)
3502 conn_mode = CONNECTION_MODE_IEEE80211AC;
3504 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3508 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3512 DBG("connection mode(%d)", conn_mode);
3513 connman_network_set_connection_mode(network, conn_mode);
3516 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3518 struct connman_network *network = user_data;
3521 DBG("Failed to get maxspeed from signalpoll !");
3525 DBG("maxspeed = %d", maxspeed);
3527 connman_network_set_maxspeed(network, maxspeed);
3528 set_connection_mode(network, maxspeed);
3532 static int network_signalpoll(struct wifi_data *wifi)
3534 GSupplicantInterface *interface;
3535 struct connman_network *network;
3537 if (!wifi || !wifi->network)
3540 interface = wifi->interface;
3541 network = wifi->network;
3543 DBG("network %p", network);
3545 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3548 static gboolean autosignalpoll_timeout(gpointer data)
3550 struct wifi_data *wifi = data;
3552 if (!wifi || !wifi->automaxspeed_timeout) {
3553 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3557 int ret = network_signalpoll(wifi);
3559 DBG("Fail to get max speed !!");
3560 wifi->automaxspeed_timeout = 0;
3568 static struct connman_network_driver network_driver = {
3570 .type = CONNMAN_NETWORK_TYPE_WIFI,
3571 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3572 .probe = network_probe,
3573 .remove = network_remove,
3574 .connect = network_connect,
3575 .disconnect = network_disconnect,
3578 static void interface_added(GSupplicantInterface *interface)
3580 const char *ifname = g_supplicant_interface_get_ifname(interface);
3581 const char *driver = g_supplicant_interface_get_driver(interface);
3582 #if defined TIZEN_EXT
3583 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3586 struct wifi_data *wifi;
3588 wifi = g_supplicant_interface_get_data(interface);
3590 wifi = get_pending_wifi_data(ifname);
3594 wifi->interface = interface;
3595 g_supplicant_interface_set_data(interface, wifi);
3596 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3597 wifi->p2p_device = true;
3600 DBG("ifname %s driver %s wifi %p tethering %d",
3601 ifname, driver, wifi, wifi->tethering);
3603 if (!wifi->device) {
3604 connman_error("WiFi device not set");
3608 connman_device_set_powered(wifi->device, true);
3609 #if defined TIZEN_EXT
3610 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3614 static bool is_idle(struct wifi_data *wifi)
3616 DBG("state %d", wifi->state);
3618 switch (wifi->state) {
3619 case G_SUPPLICANT_STATE_UNKNOWN:
3620 case G_SUPPLICANT_STATE_DISABLED:
3621 case G_SUPPLICANT_STATE_DISCONNECTED:
3622 case G_SUPPLICANT_STATE_INACTIVE:
3623 case G_SUPPLICANT_STATE_SCANNING:
3626 case G_SUPPLICANT_STATE_AUTHENTICATING:
3627 case G_SUPPLICANT_STATE_ASSOCIATING:
3628 case G_SUPPLICANT_STATE_ASSOCIATED:
3629 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3630 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3631 case G_SUPPLICANT_STATE_COMPLETED:
3638 static bool is_idle_wps(GSupplicantInterface *interface,
3639 struct wifi_data *wifi)
3641 /* First, let's check if WPS processing did not went wrong */
3642 if (g_supplicant_interface_get_wps_state(interface) ==
3643 G_SUPPLICANT_WPS_STATE_FAIL)
3646 /* Unlike normal connection, being associated while processing wps
3647 * actually means that we are idling. */
3648 switch (wifi->state) {
3649 case G_SUPPLICANT_STATE_UNKNOWN:
3650 case G_SUPPLICANT_STATE_DISABLED:
3651 case G_SUPPLICANT_STATE_DISCONNECTED:
3652 case G_SUPPLICANT_STATE_INACTIVE:
3653 case G_SUPPLICANT_STATE_SCANNING:
3654 case G_SUPPLICANT_STATE_ASSOCIATED:
3656 case G_SUPPLICANT_STATE_AUTHENTICATING:
3657 case G_SUPPLICANT_STATE_ASSOCIATING:
3658 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3659 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3660 case G_SUPPLICANT_STATE_COMPLETED:
3667 static bool handle_wps_completion(GSupplicantInterface *interface,
3668 struct connman_network *network,
3669 struct connman_device *device,
3670 struct wifi_data *wifi)
3674 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3676 const unsigned char *ssid, *wps_ssid;
3677 unsigned int ssid_len, wps_ssid_len;
3678 const char *wps_key;
3680 /* Checking if we got associated with requested
3682 ssid = connman_network_get_blob(network, "WiFi.SSID",
3685 wps_ssid = g_supplicant_interface_get_wps_ssid(
3686 interface, &wps_ssid_len);
3688 if (!wps_ssid || wps_ssid_len != ssid_len ||
3689 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3690 connman_network_set_associating(network, false);
3691 #if defined TIZEN_EXT
3692 g_supplicant_interface_disconnect(wifi->interface,
3693 disconnect_callback, wifi->network);
3695 connman_network_set_bool(network, "WiFi.UseWPS", false);
3696 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3698 g_supplicant_interface_disconnect(wifi->interface,
3699 disconnect_callback, wifi);
3704 wps_key = g_supplicant_interface_get_wps_key(interface);
3705 #if defined TIZEN_EXT
3706 /* Check the passphrase and encrypt it
3709 gchar *passphrase = g_strdup(wps_key);
3711 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3713 if (check_passphrase_ext(network, passphrase) < 0) {
3714 DBG("[WPS] Invalid passphrase");
3719 ret = send_encryption_request(passphrase, network);
3724 DBG("[WPS] Encryption request succeeded");
3726 DBG("[WPS] Encryption request failed %d", ret);
3729 connman_network_set_string(network, "WiFi.Passphrase",
3732 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3739 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3740 struct wifi_data *wifi)
3742 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3743 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3744 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3745 wifi->load_shaping_retries ++;
3748 wifi->load_shaping_retries = 0;
3752 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3753 struct connman_network *network,
3754 struct wifi_data *wifi)
3756 #if defined TIZEN_EXT
3757 const char *security;
3758 struct connman_service *service;
3760 if (wifi->connected)
3763 security = connman_network_get_string(network, "WiFi.Security");
3765 if (security && g_str_equal(security, "ieee8021x") == true &&
3766 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3768 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3773 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3776 struct connman_service *service;
3778 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3781 if (wifi->connected)
3785 service = connman_service_lookup_from_network(network);
3791 if (connman_service_get_favorite(service)) {
3792 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3797 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3802 #if defined TIZEN_EXT
3803 static bool handle_wifi_assoc_retry(struct connman_network *network,
3804 struct wifi_data *wifi)
3806 const char *security;
3808 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3809 connman_network_get_connecting(network) != true) {
3810 wifi->assoc_retry_count = 0;
3814 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3815 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3816 wifi->assoc_retry_count = 0;
3820 security = connman_network_get_string(network, "WiFi.Security");
3821 if (security && g_str_equal(security, "ieee8021x") == true &&
3822 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3823 wifi->assoc_retry_count = 0;
3827 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3828 wifi->assoc_retry_count = 0;
3830 /* Honestly it's not an invalid-key error,
3831 * however QA team recommends that the invalid-key error
3832 * might be better to display for user experience.
3834 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3843 static void interface_state(GSupplicantInterface *interface)
3845 struct connman_network *network;
3846 struct connman_device *device;
3847 struct wifi_data *wifi;
3848 GSupplicantState state = g_supplicant_interface_get_state(interface);
3852 wifi = g_supplicant_interface_get_data(interface);
3854 DBG("wifi %p interface state %d", wifi, state);
3859 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3860 if (wifi->tethering_param) {
3861 g_free(wifi->tethering_param->ssid);
3862 g_free(wifi->tethering_param);
3863 wifi->tethering_param = NULL;
3867 device = wifi->device;
3871 if (g_supplicant_interface_get_ready(interface) &&
3872 !wifi->interface_ready) {
3873 wifi->interface_ready = true;
3874 finalize_interface_creation(wifi);
3877 network = wifi->network;
3882 case G_SUPPLICANT_STATE_SCANNING:
3883 if (wifi->connected)
3884 connman_network_set_connected(network, false);
3888 case G_SUPPLICANT_STATE_AUTHENTICATING:
3889 case G_SUPPLICANT_STATE_ASSOCIATING:
3890 #if defined TIZEN_EXT
3891 reset_autoscan(device);
3893 stop_autoscan(device);
3896 if (!wifi->connected)
3897 connman_network_set_associating(network, true);
3901 case G_SUPPLICANT_STATE_COMPLETED:
3902 #if defined TIZEN_EXT
3903 /* though it should be already reset: */
3904 reset_autoscan(device);
3906 wifi->assoc_retry_count = 0;
3908 wifi->scan_pending_network = NULL;
3910 /* should be cleared scanning flag */
3911 bool scanning = connman_device_get_scanning(device);
3913 connman_device_set_scanning(device,
3914 CONNMAN_SERVICE_TYPE_WIFI, false);
3915 connman_device_unref(device);
3918 if (!wifi->automaxspeed_timeout) {
3919 DBG("Going to start signalpoll timer!!");
3920 int ret = network_signalpoll(wifi);
3922 DBG("Fail to get max speed !!");
3924 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
3927 /* though it should be already stopped: */
3928 stop_autoscan(device);
3931 if (!handle_wps_completion(interface, network, device, wifi))
3934 connman_network_set_connected(network, true);
3936 wifi->disconnect_code = 0;
3937 wifi->assoc_code = 0;
3938 wifi->load_shaping_retries = 0;
3941 case G_SUPPLICANT_STATE_DISCONNECTED:
3942 #if defined TIZEN_EXT
3943 connman_network_set_maxspeed(network, 0);
3945 if (wifi->automaxspeed_timeout != 0) {
3946 g_source_remove(wifi->automaxspeed_timeout);
3947 wifi->automaxspeed_timeout = 0;
3948 DBG("Remove signalpoll timer!!");
3952 * If we're in one of the idle modes, we have
3953 * not started association yet and thus setting
3954 * those ones to FALSE could cancel an association
3957 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3959 if (is_idle_wps(interface, wifi))
3965 if (handle_assoc_status_code(interface, wifi))
3968 /* If previous state was 4way-handshake, then
3969 * it's either: psk was incorrect and thus we retry
3970 * or if we reach the maximum retries we declare the
3972 if (handle_4way_handshake_failure(interface,
3976 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3977 switch (wifi->disconnect_code) {
3978 case 1: /* Unspecified reason */
3979 /* Let's assume it's because we got blocked */
3981 case 6: /* Class 2 frame received from nonauthenticated STA */
3982 connman_network_set_error(network,
3983 CONNMAN_NETWORK_ERROR_BLOCKED);
3990 #if defined TIZEN_EXT
3991 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3992 * Retry association until its retry count is expired */
3993 if (handle_wifi_assoc_retry(network, wifi) == true) {
3994 throw_wifi_scan(wifi->device, scan_callback);
3995 wifi->scan_pending_network = wifi->network;
3999 if(wifi->disconnect_code > 0){
4000 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4001 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4005 connman_network_set_connected(network, false);
4006 connman_network_set_associating(network, false);
4007 wifi->disconnecting = false;
4009 start_autoscan(device);
4013 case G_SUPPLICANT_STATE_INACTIVE:
4014 #if defined TIZEN_EXT
4015 if (handle_wps_completion(interface, network, device, wifi) == false)
4018 connman_network_set_associating(network, false);
4019 start_autoscan(device);
4023 case G_SUPPLICANT_STATE_UNKNOWN:
4024 case G_SUPPLICANT_STATE_DISABLED:
4025 case G_SUPPLICANT_STATE_ASSOCIATED:
4026 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4027 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4031 old_connected = wifi->connected;
4032 wifi->state = state;
4034 /* Saving wpa_s state policy:
4035 * If connected and if the state changes are roaming related:
4036 * --> We stay connected
4038 * --> We are connected
4040 * --> We are not connected
4043 case G_SUPPLICANT_STATE_AUTHENTICATING:
4044 case G_SUPPLICANT_STATE_ASSOCIATING:
4045 case G_SUPPLICANT_STATE_ASSOCIATED:
4046 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4047 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4048 if (wifi->connected)
4049 connman_warn("Probably roaming right now!"
4050 " Staying connected...");
4052 case G_SUPPLICANT_STATE_SCANNING:
4053 wifi->connected = false;
4056 start_autoscan(device);
4058 case G_SUPPLICANT_STATE_COMPLETED:
4059 wifi->connected = true;
4062 wifi->connected = false;
4069 static void interface_removed(GSupplicantInterface *interface)
4071 const char *ifname = g_supplicant_interface_get_ifname(interface);
4072 struct wifi_data *wifi;
4074 DBG("ifname %s", ifname);
4076 wifi = g_supplicant_interface_get_data(interface);
4078 #if defined TIZEN_EXT_WIFI_MESH
4079 if (wifi && wifi->mesh_interface) {
4080 DBG("Notify mesh interface remove");
4081 connman_mesh_notify_interface_remove(true);
4082 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4083 g_free(mesh_info->parent_ifname);
4084 g_free(mesh_info->ifname);
4085 g_free(mesh_info->identifier);
4087 wifi->mesh_interface = false;
4088 wifi->mesh_info = NULL;
4094 wifi->interface = NULL;
4096 if (wifi && wifi->tethering)
4099 if (!wifi || !wifi->device) {
4100 DBG("wifi interface already removed");
4104 connman_device_set_powered(wifi->device, false);
4106 check_p2p_technology();
4107 #if defined TIZEN_EXT_WIFI_MESH
4108 check_mesh_technology();
4112 static void set_device_type(const char *type, char dev_type[17])
4114 const char *oui = "0050F204";
4115 const char *category = "0001";
4116 const char *sub_category = "0000";
4118 if (!g_strcmp0(type, "handset")) {
4120 sub_category = "0005";
4121 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4122 sub_category = "0001";
4123 else if (!g_strcmp0(type, "server"))
4124 sub_category = "0002";
4125 else if (!g_strcmp0(type, "laptop"))
4126 sub_category = "0005";
4127 else if (!g_strcmp0(type, "desktop"))
4128 sub_category = "0006";
4129 else if (!g_strcmp0(type, "tablet"))
4130 sub_category = "0009";
4131 else if (!g_strcmp0(type, "watch"))
4134 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4137 static void p2p_support(GSupplicantInterface *interface)
4139 char dev_type[17] = {};
4140 const char *hostname;
4147 if (!g_supplicant_interface_has_p2p(interface))
4150 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4151 DBG("Could not register P2P technology driver");
4155 hostname = connman_utsname_get_hostname();
4157 hostname = "ConnMan";
4159 set_device_type(connman_machine_get_type(), dev_type);
4160 g_supplicant_interface_set_p2p_device_config(interface,
4161 hostname, dev_type);
4162 connman_peer_driver_register(&peer_driver);
4165 static void scan_started(GSupplicantInterface *interface)
4170 static void scan_finished(GSupplicantInterface *interface)
4172 #if defined TIZEN_EXT
4173 struct wifi_data *wifi;
4174 bool is_associating = false;
4175 static bool is_scanning = true;
4180 #if defined TIZEN_EXT
4181 wifi = g_supplicant_interface_get_data(interface);
4182 if (wifi && wifi->scan_pending_network) {
4183 network_connect(wifi->scan_pending_network);
4184 wifi->scan_pending_network = NULL;
4187 //service state - associating
4188 if(!wifi || !wifi->network)
4191 is_associating = connman_network_get_associating(wifi->network);
4192 if(is_associating && is_scanning){
4193 is_scanning = false;
4194 DBG("send scan for connecting");
4195 throw_wifi_scan(wifi->device, scan_callback);
4206 static void ap_create_fail(GSupplicantInterface *interface)
4208 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4211 if ((wifi->tethering) && (wifi->tethering_param)) {
4212 DBG("%s create AP fail \n",
4213 g_supplicant_interface_get_ifname(wifi->interface));
4215 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4216 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4217 wifi->tethering = false;
4219 ret = tech_set_tethering(wifi->tethering_param->technology,
4220 wifi->tethering_param->ssid->ssid,
4221 wifi->tethering_param->ssid->passphrase,
4222 wifi->bridge, true);
4224 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4225 connman_technology_tethering_notify(wifi_technology,false);
4228 g_free(wifi->tethering_param->ssid);
4229 g_free(wifi->tethering_param);
4230 wifi->tethering_param = NULL;
4236 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4238 unsigned char strength;
4240 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4242 #if !defined TIZEN_EXT
4249 #if defined TIZEN_EXT_WIFI_MESH
4250 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4252 GSupplicantInterface *interface;
4253 struct wifi_data *wifi;
4254 const char *name, *security;
4255 struct connman_mesh *connman_mesh;
4256 struct wifi_mesh_info *mesh_info;
4257 const unsigned char *bssid;
4258 const char *identifier;
4263 interface = g_supplicant_network_get_interface(supplicant_network);
4264 wifi = g_supplicant_interface_get_data(interface);
4265 if (!wifi || !wifi->mesh_interface) {
4266 DBG("Virtual Mesh interface not created");
4270 bssid = g_supplicant_network_get_bssid(supplicant_network);
4271 address = g_malloc0(19);
4272 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4273 bssid[2], bssid[3], bssid[4], bssid[5]);
4275 identifier = g_supplicant_network_get_identifier(supplicant_network);
4276 name = g_supplicant_network_get_name(supplicant_network);
4277 security = g_supplicant_network_get_security(supplicant_network);
4278 frequency = g_supplicant_network_get_frequency(supplicant_network);
4280 mesh_info = wifi->mesh_info;
4281 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4285 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4287 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4288 connman_mesh_set_name(connman_mesh, name);
4289 connman_mesh_set_security(connman_mesh, security);
4290 connman_mesh_set_frequency(connman_mesh, frequency);
4291 connman_mesh_set_address(connman_mesh, address);
4292 connman_mesh_set_index(connman_mesh, mesh_info->index);
4293 connman_mesh_set_strength(connman_mesh,
4294 calculate_strength(supplicant_network));
4295 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4297 ret = connman_mesh_register(connman_mesh);
4298 if (ret == -EALREADY)
4299 DBG("Mesh Peer is already registered");
4305 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4307 GSupplicantInterface *interface;
4308 struct wifi_data *wifi;
4309 struct connman_mesh *connman_mesh;
4310 struct wifi_mesh_info *mesh_info;
4311 const char *identifier;
4313 interface = g_supplicant_network_get_interface(supplicant_network);
4314 wifi = g_supplicant_interface_get_data(interface);
4315 if (!wifi || !wifi->mesh_interface) {
4316 DBG("Virtual Mesh interface not created");
4320 identifier = g_supplicant_network_get_identifier(supplicant_network);
4322 DBG("Failed to get Mesh Peer identifier");
4326 mesh_info = wifi->mesh_info;
4327 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4329 /* Do not unregister connected mesh peer */
4330 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4331 DBG("Mesh Peer %s is connected", identifier);
4334 DBG("Mesh Peer identifier %s removed", identifier);
4335 connman_mesh_unregister(connman_mesh);
4340 static void network_added(GSupplicantNetwork *supplicant_network)
4342 struct connman_network *network;
4343 GSupplicantInterface *interface;
4344 struct wifi_data *wifi;
4345 const char *name, *identifier, *security, *group, *mode;
4346 const unsigned char *ssid;
4347 unsigned int ssid_len;
4351 bool wps_advertizing;
4353 #if defined TIZEN_EXT
4354 GSList *vsie_list = NULL;
4355 const unsigned char *country_code;
4356 ieee80211_modes_e phy_mode;
4359 mode = g_supplicant_network_get_mode(supplicant_network);
4360 identifier = g_supplicant_network_get_identifier(supplicant_network);
4362 DBG("%s", identifier);
4364 if (!g_strcmp0(mode, "adhoc"))
4367 #if defined TIZEN_EXT_WIFI_MESH
4368 if (!g_strcmp0(mode, "mesh")) {
4369 mesh_peer_added(supplicant_network);
4374 interface = g_supplicant_network_get_interface(supplicant_network);
4375 wifi = g_supplicant_interface_get_data(interface);
4376 name = g_supplicant_network_get_name(supplicant_network);
4377 security = g_supplicant_network_get_security(supplicant_network);
4378 group = g_supplicant_network_get_identifier(supplicant_network);
4379 wps = g_supplicant_network_get_wps(supplicant_network);
4380 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4381 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4382 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4383 supplicant_network);
4388 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4390 network = connman_device_get_network(wifi->device, identifier);
4393 network = connman_network_create(identifier,
4394 CONNMAN_NETWORK_TYPE_WIFI);
4398 connman_network_set_index(network, wifi->index);
4400 if (connman_device_add_network(wifi->device, network) < 0) {
4401 connman_network_unref(network);
4405 wifi->networks = g_slist_prepend(wifi->networks, network);
4408 if (name && name[0] != '\0')
4409 connman_network_set_name(network, name);
4411 connman_network_set_blob(network, "WiFi.SSID",
4413 #if defined TIZEN_EXT
4414 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4416 connman_network_set_vsie_list(network, vsie_list);
4418 DBG("vsie_list is NULL");
4419 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4420 connman_network_set_countrycode(network, country_code);
4421 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4422 connman_network_set_phy_mode(network, phy_mode);
4424 connman_network_set_string(network, "WiFi.Security", security);
4425 connman_network_set_strength(network,
4426 calculate_strength(supplicant_network));
4427 connman_network_set_bool(network, "WiFi.WPS", wps);
4430 /* Is AP advertizing for WPS association?
4431 * If so, we decide to use WPS by default */
4432 if (wps_ready && wps_pbc &&
4434 #if !defined TIZEN_EXT
4435 connman_network_set_bool(network, "WiFi.UseWPS", true);
4437 DBG("wps is activating by ap but ignore it.");
4442 connman_network_set_frequency(network,
4443 g_supplicant_network_get_frequency(supplicant_network));
4444 #if defined TIZEN_EXT
4445 connman_network_set_bssid(network,
4446 g_supplicant_network_get_bssid(supplicant_network));
4447 connman_network_set_maxrate(network,
4448 g_supplicant_network_get_maxrate(supplicant_network));
4449 connman_network_set_enc_mode(network,
4450 g_supplicant_network_get_enc_mode(supplicant_network));
4451 connman_network_set_rsn_mode(network,
4452 g_supplicant_network_get_rsn_mode(supplicant_network));
4453 connman_network_set_keymgmt(network,
4454 g_supplicant_network_get_keymgmt(supplicant_network));
4455 connman_network_set_bool(network, "WiFi.HS20AP",
4456 g_supplicant_network_is_hs20AP(supplicant_network));
4457 connman_network_set_bssid_list(network,
4458 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4460 connman_network_set_available(network, true);
4461 connman_network_set_string(network, "WiFi.Mode", mode);
4463 #if defined TIZEN_EXT
4468 connman_network_set_group(network, group);
4470 #if defined TIZEN_EXT
4471 if (wifi_first_scan == true)
4472 found_with_first_scan = true;
4475 if (wifi->hidden && ssid) {
4476 #if defined TIZEN_EXT
4477 if (network_security(wifi->hidden->security) ==
4478 network_security(security) &&
4480 if (!g_strcmp0(wifi->hidden->security, security) &&
4482 wifi->hidden->ssid_len == ssid_len &&
4483 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4484 connman_network_connect_hidden(network,
4485 wifi->hidden->identity,
4486 wifi->hidden->passphrase,
4487 wifi->hidden->user_data);
4488 wifi->hidden->user_data = NULL;
4489 hidden_free(wifi->hidden);
4490 wifi->hidden = NULL;
4495 static void network_removed(GSupplicantNetwork *network)
4497 GSupplicantInterface *interface;
4498 struct wifi_data *wifi;
4499 const char *name, *identifier;
4500 struct connman_network *connman_network;
4502 #if defined TIZEN_EXT_WIFI_MESH
4504 mode = g_supplicant_network_get_mode(network);
4505 if (!g_strcmp0(mode, "mesh")) {
4506 mesh_peer_removed(network);
4511 interface = g_supplicant_network_get_interface(network);
4512 wifi = g_supplicant_interface_get_data(interface);
4513 identifier = g_supplicant_network_get_identifier(network);
4514 name = g_supplicant_network_get_name(network);
4516 DBG("name %s", name);
4521 connman_network = connman_device_get_network(wifi->device, identifier);
4522 if (!connman_network)
4525 #if defined TIZEN_EXT
4526 if (connman_network == wifi->scan_pending_network)
4527 wifi->scan_pending_network = NULL;
4529 if (connman_network == wifi->pending_network)
4530 wifi->pending_network = NULL;
4532 if(connman_network_get_connecting(connman_network) == true){
4533 connman_network_set_connected(connman_network, false);
4537 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4539 connman_device_remove_network(wifi->device, connman_network);
4540 connman_network_unref(connman_network);
4543 static void network_changed(GSupplicantNetwork *network, const char *property)
4545 GSupplicantInterface *interface;
4546 struct wifi_data *wifi;
4547 const char *name, *identifier;
4548 struct connman_network *connman_network;
4550 #if defined TIZEN_EXT
4551 const unsigned char *bssid;
4552 unsigned int maxrate;
4555 const unsigned char *country_code;
4556 ieee80211_modes_e phy_mode;
4560 interface = g_supplicant_network_get_interface(network);
4561 wifi = g_supplicant_interface_get_data(interface);
4562 identifier = g_supplicant_network_get_identifier(network);
4563 name = g_supplicant_network_get_name(network);
4565 DBG("name %s", name);
4570 connman_network = connman_device_get_network(wifi->device, identifier);
4571 if (!connman_network)
4574 if (g_str_equal(property, "Signal")) {
4575 connman_network_set_strength(connman_network,
4576 calculate_strength(network));
4577 connman_network_update(connman_network);
4580 #if defined TIZEN_EXT
4581 bssid = g_supplicant_network_get_bssid(network);
4582 maxrate = g_supplicant_network_get_maxrate(network);
4583 frequency = g_supplicant_network_get_frequency(network);
4584 wps = g_supplicant_network_get_wps(network);
4585 phy_mode = g_supplicant_network_get_phy_mode(network);
4587 connman_network_set_bssid(connman_network, bssid);
4588 connman_network_set_maxrate(connman_network, maxrate);
4589 connman_network_set_frequency(connman_network, frequency);
4590 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4591 country_code = g_supplicant_network_get_countrycode(network);
4592 connman_network_set_countrycode(connman_network, country_code);
4593 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4594 connman_network_set_bssid_list(connman_network, bssid_list);
4595 connman_network_set_phy_mode(connman_network, phy_mode);
4599 static void network_associated(GSupplicantNetwork *network)
4601 GSupplicantInterface *interface;
4602 struct wifi_data *wifi;
4603 struct connman_network *connman_network;
4604 const char *identifier;
4608 interface = g_supplicant_network_get_interface(network);
4612 wifi = g_supplicant_interface_get_data(interface);
4616 identifier = g_supplicant_network_get_identifier(network);
4618 connman_network = connman_device_get_network(wifi->device, identifier);
4619 if (!connman_network)
4622 if (wifi->network) {
4623 if (wifi->network == connman_network)
4627 * This should never happen, we got associated with
4628 * a network different than the one we were expecting.
4630 DBG("Associated to %p while expecting %p",
4631 connman_network, wifi->network);
4633 connman_network_set_associating(wifi->network, false);
4636 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4638 wifi->network = connman_network_ref(connman_network);
4642 * Interface state changes callback (interface_state) is always
4643 * called before network_associated callback thus we need to call
4644 * interface_state again in order to process the new state now that
4645 * we have the network properly set.
4647 interface_state(interface);
4650 static void apply_peer_services(GSupplicantPeer *peer,
4651 struct connman_peer *connman_peer)
4653 const unsigned char *data;
4658 connman_peer_reset_services(connman_peer);
4660 data = g_supplicant_peer_get_widi_ies(peer, &length);
4662 connman_peer_add_service(connman_peer,
4663 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4667 static void add_station(const char *mac)
4669 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4673 static void remove_station(const char *mac)
4675 connman_technology_tethering_remove_station(mac);
4678 static void peer_found(GSupplicantPeer *peer)
4680 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4681 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4682 struct connman_peer *connman_peer;
4683 const char *identifier, *name;
4685 #if defined TIZEN_EXT
4689 identifier = g_supplicant_peer_get_identifier(peer);
4690 name = g_supplicant_peer_get_name(peer);
4692 DBG("ident: %s", identifier);
4694 connman_peer = connman_peer_get(wifi->device, identifier);
4698 connman_peer = connman_peer_create(identifier);
4699 connman_peer_set_name(connman_peer, name);
4700 connman_peer_set_device(connman_peer, wifi->device);
4701 apply_peer_services(peer, connman_peer);
4703 ret = connman_peer_register(connman_peer);
4704 if (ret < 0 && ret != -EALREADY)
4705 connman_peer_unref(connman_peer);
4707 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4710 static void peer_lost(GSupplicantPeer *peer)
4712 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4713 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4714 struct connman_peer *connman_peer;
4715 const char *identifier;
4720 identifier = g_supplicant_peer_get_identifier(peer);
4722 DBG("ident: %s", identifier);
4724 connman_peer = connman_peer_get(wifi->device, identifier);
4726 if (wifi->p2p_connecting &&
4727 wifi->pending_peer == connman_peer) {
4728 peer_connect_timeout(wifi);
4730 connman_peer_unregister(connman_peer);
4731 connman_peer_unref(connman_peer);
4734 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4737 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4739 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4740 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4741 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4742 struct connman_peer *connman_peer;
4743 const char *identifier;
4745 identifier = g_supplicant_peer_get_identifier(peer);
4747 DBG("ident: %s", identifier);
4752 connman_peer = connman_peer_get(wifi->device, identifier);
4757 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4758 apply_peer_services(peer, connman_peer);
4759 connman_peer_services_changed(connman_peer);
4761 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4762 if (!g_supplicant_peer_is_in_a_group(peer))
4763 p_state = CONNMAN_PEER_STATE_IDLE;
4765 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4767 case G_SUPPLICANT_PEER_GROUP_STARTED:
4769 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4770 p_state = CONNMAN_PEER_STATE_IDLE;
4772 case G_SUPPLICANT_PEER_GROUP_JOINED:
4773 connman_peer_set_iface_address(connman_peer,
4774 g_supplicant_peer_get_iface_address(peer));
4776 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4777 p_state = CONNMAN_PEER_STATE_IDLE;
4779 case G_SUPPLICANT_PEER_GROUP_FAILED:
4780 if (g_supplicant_peer_has_requested_connection(peer))
4781 p_state = CONNMAN_PEER_STATE_IDLE;
4783 p_state = CONNMAN_PEER_STATE_FAILURE;
4787 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4788 p_state == CONNMAN_PEER_STATE_FAILURE) {
4789 if (wifi->p2p_connecting
4790 && connman_peer == wifi->pending_peer)
4791 peer_cancel_timeout(wifi);
4793 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4796 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4799 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4800 GSupplicantInterface *g_iface;
4801 struct wifi_data *g_wifi;
4803 g_iface = g_supplicant_peer_get_group_interface(peer);
4807 g_wifi = g_supplicant_interface_get_data(g_iface);
4811 connman_peer_set_as_master(connman_peer,
4812 !g_supplicant_peer_is_client(peer));
4813 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4816 * If wpa_supplicant didn't create a dedicated p2p-group
4817 * interface then mark this interface as p2p_device to avoid
4818 * scan and auto-scan are launched on it while P2P is connected.
4820 if (!g_list_find(p2p_iface_list, g_wifi))
4821 wifi->p2p_device = true;
4824 connman_peer_set_state(connman_peer, p_state);
4827 static void peer_request(GSupplicantPeer *peer)
4829 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4830 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4831 struct connman_peer *connman_peer;
4832 const char *identifier;
4834 #if defined TIZEN_EXT
4839 identifier = g_supplicant_peer_get_identifier(peer);
4841 DBG("ident: %s", identifier);
4843 connman_peer = connman_peer_get(wifi->device, identifier);
4847 connman_peer_request_connection(connman_peer);
4850 #if defined TIZEN_EXT
4851 static void system_power_off(void)
4854 struct wifi_data *wifi;
4855 struct connman_service *service;
4856 struct connman_ipconfig *ipconfig_ipv4;
4858 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4859 for (list = iface_list; list; list = list->next) {
4862 if (wifi->network != NULL) {
4863 service = connman_service_lookup_from_network(wifi->network);
4864 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4865 __connman_dhcp_stop(ipconfig_ipv4);
4871 static void network_merged(GSupplicantNetwork *network)
4873 GSupplicantInterface *interface;
4874 GSupplicantState state;
4875 struct wifi_data *wifi;
4876 const char *identifier;
4877 struct connman_network *connman_network;
4881 interface = g_supplicant_network_get_interface(network);
4885 state = g_supplicant_interface_get_state(interface);
4886 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4889 wifi = g_supplicant_interface_get_data(interface);
4893 identifier = g_supplicant_network_get_identifier(network);
4895 connman_network = connman_device_get_network(wifi->device, identifier);
4896 if (!connman_network)
4899 DBG("merged identifier %s", identifier);
4901 if (wifi->connected == FALSE) {
4903 case G_SUPPLICANT_STATE_AUTHENTICATING:
4904 case G_SUPPLICANT_STATE_ASSOCIATING:
4905 case G_SUPPLICANT_STATE_ASSOCIATED:
4906 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4907 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4908 connman_network_set_associating(connman_network, TRUE);
4910 case G_SUPPLICANT_STATE_COMPLETED:
4911 connman_network_set_connected(connman_network, TRUE);
4914 DBG("Not handled the state : %d", state);
4919 ishs20AP = g_supplicant_network_is_hs20AP(network);
4922 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
4923 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
4924 connman_network_set_string(connman_network, "WiFi.EAP",
4926 connman_network_set_string(connman_network, "WiFi.Identity",
4927 g_supplicant_network_get_identity(network));
4928 connman_network_set_string(connman_network, "WiFi.Phase2",
4929 g_supplicant_network_get_phase2(network));
4934 wifi->network = connman_network;
4937 static void assoc_failed(void *user_data)
4939 struct connman_network *network = user_data;
4940 connman_network_set_associating(network, false);
4944 static void debug(const char *str)
4946 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
4947 connman_debug("%s", str);
4950 static void disconnect_reasoncode(GSupplicantInterface *interface,
4953 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4956 wifi->disconnect_code = reasoncode;
4960 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
4962 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4965 wifi->assoc_code = status_code;
4969 static const GSupplicantCallbacks callbacks = {
4970 .system_ready = system_ready,
4971 .system_killed = system_killed,
4972 .interface_added = interface_added,
4973 .interface_state = interface_state,
4974 .interface_removed = interface_removed,
4975 .p2p_support = p2p_support,
4976 .scan_started = scan_started,
4977 .scan_finished = scan_finished,
4978 .ap_create_fail = ap_create_fail,
4979 .network_added = network_added,
4980 .network_removed = network_removed,
4981 .network_changed = network_changed,
4982 .network_associated = network_associated,
4983 .add_station = add_station,
4984 .remove_station = remove_station,
4985 .peer_found = peer_found,
4986 .peer_lost = peer_lost,
4987 .peer_changed = peer_changed,
4988 .peer_request = peer_request,
4989 #if defined TIZEN_EXT
4990 .system_power_off = system_power_off,
4991 .network_merged = network_merged,
4992 .assoc_failed = assoc_failed,
4995 .disconnect_reasoncode = disconnect_reasoncode,
4996 .assoc_status_code = assoc_status_code,
4997 #if defined TIZEN_EXT_WIFI_MESH
4998 .mesh_support = mesh_support,
4999 .mesh_group_started = mesh_group_started,
5000 .mesh_group_removed = mesh_group_removed,
5001 .mesh_peer_connected = mesh_peer_connected,
5002 .mesh_peer_disconnected = mesh_peer_disconnected,
5007 static int tech_probe(struct connman_technology *technology)
5009 wifi_technology = technology;
5014 static void tech_remove(struct connman_technology *technology)
5016 wifi_technology = NULL;
5019 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5020 const char *passphrase)
5022 GSupplicantSSID *ap;
5024 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5028 ap->mode = G_SUPPLICANT_MODE_MASTER;
5029 #if defined TIZEN_EXT
5030 ap->ssid = (void *) ssid;
5034 ap->ssid_len = strlen(ssid);
5038 if (!passphrase || strlen(passphrase) == 0) {
5039 ap->security = G_SUPPLICANT_SECURITY_NONE;
5040 ap->passphrase = NULL;
5042 ap->security = G_SUPPLICANT_SECURITY_PSK;
5043 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5044 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5045 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5046 ap->passphrase = passphrase;
5052 static void ap_start_callback(int result, GSupplicantInterface *interface,
5055 struct wifi_tethering_info *info = user_data;
5057 DBG("result %d index %d bridge %s",
5058 result, info->wifi->index, info->wifi->bridge);
5060 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5061 connman_inet_remove_from_bridge(info->wifi->index,
5062 info->wifi->bridge);
5064 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5065 connman_technology_tethering_notify(info->technology, false);
5066 g_free(info->wifi->tethering_param->ssid);
5067 g_free(info->wifi->tethering_param);
5068 info->wifi->tethering_param = NULL;
5072 g_free(info->ifname);
5076 static void ap_create_callback(int result,
5077 GSupplicantInterface *interface,
5080 struct wifi_tethering_info *info = user_data;
5082 DBG("result %d ifname %s", result,
5083 g_supplicant_interface_get_ifname(interface));
5085 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5086 connman_inet_remove_from_bridge(info->wifi->index,
5087 info->wifi->bridge);
5089 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5090 connman_technology_tethering_notify(info->technology, false);
5091 g_free(info->wifi->tethering_param->ssid);
5092 g_free(info->wifi->tethering_param);
5093 info->wifi->tethering_param = NULL;
5097 g_free(info->ifname);
5103 info->wifi->interface = interface;
5104 g_supplicant_interface_set_data(interface, info->wifi);
5106 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5107 connman_error("Failed to set interface ap_scan property");
5109 g_supplicant_interface_connect(interface, info->ssid,
5110 ap_start_callback, info);
5113 static void sta_remove_callback(int result,
5114 GSupplicantInterface *interface,
5117 struct wifi_tethering_info *info = user_data;
5118 const char *driver = connman_option_get_string("wifi");
5120 DBG("ifname %s result %d ", info->ifname, result);
5122 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5123 info->wifi->tethering = false;
5124 connman_technology_tethering_notify(info->technology, false);
5126 g_free(info->ifname);
5130 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5131 g_free(info->wifi->tethering_param->ssid);
5132 g_free(info->wifi->tethering_param);
5133 info->wifi->tethering_param = NULL;
5138 info->wifi->interface = NULL;
5140 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5145 static int enable_wifi_tethering(struct connman_technology *technology,
5146 const char *bridge, const char *identifier,
5147 const char *passphrase, bool available)
5150 GSupplicantInterface *interface;
5151 struct wifi_data *wifi;
5152 struct wifi_tethering_info *info;
5157 for (list = iface_list; list; list = list->next) {
5160 DBG("wifi %p network %p pending_network %p", wifi,
5161 wifi->network, wifi->pending_network);
5163 interface = wifi->interface;
5168 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5171 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5173 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5174 DBG("%s does not support AP mode (detected)", ifname);
5178 mode = g_supplicant_interface_get_mode(interface);
5179 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5180 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5181 DBG("%s does not support AP mode (capability)", ifname);
5185 if (wifi->network && available)
5188 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5192 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5193 if (!wifi->tethering_param) {
5199 info->technology = technology;
5200 info->wifi->bridge = bridge;
5201 info->ssid = ssid_ap_init(identifier, passphrase);
5205 info->ifname = g_strdup(ifname);
5209 wifi->tethering_param->technology = technology;
5210 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5211 if (!wifi->tethering_param->ssid)
5214 info->wifi->tethering = true;
5215 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5217 berr = connman_technology_tethering_notify(technology, true);
5221 err = g_supplicant_interface_remove(interface,
5222 sta_remove_callback,
5225 DBG("tethering wifi %p ifname %s", wifi, ifname);
5230 g_free(info->ifname);
5233 g_free(wifi->tethering_param);
5234 wifi->tethering_param = NULL;
5237 * Remove bridge if it was correctly created but remove
5238 * operation failed. Instead, if bridge creation failed then
5239 * break out and do not try again on another interface,
5240 * bridge set-up does not depend on it.
5243 connman_technology_tethering_notify(technology, false);
5251 static int tech_set_tethering(struct connman_technology *technology,
5252 const char *identifier, const char *passphrase,
5253 const char *bridge, bool enabled)
5256 struct wifi_data *wifi;
5262 for (list = iface_list; list; list = list->next) {
5265 if (wifi->tethering) {
5266 wifi->tethering = false;
5268 connman_inet_remove_from_bridge(wifi->index,
5270 wifi->bridged = false;
5274 connman_technology_tethering_notify(technology, false);
5279 DBG("trying tethering for available devices");
5280 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5284 DBG("trying tethering for any device");
5285 err = enable_wifi_tethering(technology, bridge, identifier,
5292 static void regdom_callback(int result, const char *alpha2, void *user_data)
5296 if (!wifi_technology)
5302 connman_technology_regdom_notify(wifi_technology, alpha2);
5305 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5307 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5310 static struct connman_technology_driver tech_driver = {
5312 .type = CONNMAN_SERVICE_TYPE_WIFI,
5313 .probe = tech_probe,
5314 .remove = tech_remove,
5315 .set_tethering = tech_set_tethering,
5316 .set_regdom = tech_set_regdom,
5319 static int wifi_init(void)
5323 err = connman_network_driver_register(&network_driver);
5327 err = g_supplicant_register(&callbacks);
5329 connman_network_driver_unregister(&network_driver);
5333 err = connman_technology_driver_register(&tech_driver);
5335 g_supplicant_unregister(&callbacks);
5336 connman_network_driver_unregister(&network_driver);
5343 static void wifi_exit(void)
5347 connman_technology_driver_unregister(&tech_driver);
5349 g_supplicant_unregister(&callbacks);
5351 connman_network_driver_unregister(&network_driver);
5354 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5355 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)