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 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3265 if (bssid_list && g_slist_length(bssid_list) > 1) {
3267 char buff[MAC_ADDRESS_LENGTH];
3268 for (list = bssid_list; list; list = list->next) {
3269 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3271 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3272 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3273 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3274 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3276 char *last_bssid = connman_network_get_last_bssid(network);
3278 if (strcmp(last_bssid, buff) == 0) {
3279 DBG("last_bssid match, try next bssid");
3282 connman_network_set_last_bssid(network, buff);
3284 ssid->bssid = &(bssids->bssid[0]);
3289 ssid->bssid = connman_network_get_bssid(network);
3291 ssid->eap_keymgmt = network_eap_keymgmt(
3292 connman_network_get_string(network, "WiFi.KeymgmtType"));
3293 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3295 if(g_strcmp0(ssid->eap, "fast") == 0)
3296 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3298 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3299 ssid->bssid_for_connect_len = 6;
3300 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3301 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3302 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3303 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3304 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3306 ssid->freq = connman_network_get_frequency(network);
3310 if (connman_setting_get_bool("BackgroundScanning"))
3311 ssid->bgscan = BGSCAN_DEFAULT;
3314 static int network_connect(struct connman_network *network)
3316 struct connman_device *device = connman_network_get_device(network);
3317 struct wifi_data *wifi;
3318 GSupplicantInterface *interface;
3319 GSupplicantSSID *ssid;
3321 DBG("network %p", network);
3326 wifi = connman_device_get_data(device);
3330 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3334 interface = wifi->interface;
3336 ssid_init(ssid, network);
3338 if (wifi->disconnecting) {
3339 wifi->pending_network = network;
3340 #if defined TIZEN_EXT
3345 wifi->network = connman_network_ref(network);
3347 #if defined TIZEN_EXT
3348 wifi->scan_pending_network = NULL;
3351 return g_supplicant_interface_connect(interface, ssid,
3352 connect_callback, network);
3355 return -EINPROGRESS;
3358 static void disconnect_callback(int result, GSupplicantInterface *interface,
3361 #if defined TIZEN_EXT
3363 struct wifi_data *wifi;
3364 struct connman_network *network = user_data;
3366 DBG("network %p result %d", network, result);
3368 for (list = iface_list; list; list = list->next) {
3371 if (wifi->network == NULL && wifi->disconnecting == true)
3372 wifi->disconnecting = false;
3374 if (wifi->network == network)
3378 /* wifi_data may be invalid because wifi is already disabled */
3383 struct wifi_data *wifi = user_data;
3386 DBG("result %d supplicant interface %p wifi %p",
3387 result, interface, wifi);
3389 if (result == -ECONNABORTED) {
3390 DBG("wifi interface no longer available");
3394 if (wifi->network) {
3395 connman_network_set_connected(wifi->network, false);
3396 wifi->network = NULL;
3399 wifi->disconnecting = false;
3400 wifi->connected = false;
3402 if (wifi->pending_network) {
3403 network_connect(wifi->pending_network);
3404 wifi->pending_network = NULL;
3407 start_autoscan(wifi->device);
3410 static int network_disconnect(struct connman_network *network)
3412 struct connman_device *device = connman_network_get_device(network);
3413 struct wifi_data *wifi;
3415 #if defined TIZEN_EXT
3416 struct connman_service *service;
3419 DBG("network %p", network);
3421 wifi = connman_device_get_data(device);
3422 if (!wifi || !wifi->interface)
3425 #if defined TIZEN_EXT
3426 if (connman_network_get_associating(network) == true) {
3427 connman_network_clear_associating(network);
3428 connman_network_set_bool(network, "WiFi.UseWPS", false);
3430 service = connman_service_lookup_from_network(network);
3432 if (service != NULL &&
3433 (__connman_service_is_connected_state(service,
3434 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3435 __connman_service_is_connected_state(service,
3436 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3437 (connman_service_get_favorite(service) == false))
3438 __connman_service_set_passphrase(service, NULL);
3441 if (wifi->pending_network == network)
3442 wifi->pending_network = NULL;
3444 if (wifi->scan_pending_network == network)
3445 wifi->scan_pending_network = NULL;
3448 connman_network_set_associating(network, false);
3450 if (wifi->disconnecting)
3453 wifi->disconnecting = true;
3455 #if defined TIZEN_EXT
3456 err = g_supplicant_interface_disconnect(wifi->interface,
3457 disconnect_callback, network);
3459 err = g_supplicant_interface_disconnect(wifi->interface,
3460 disconnect_callback, wifi);
3464 wifi->disconnecting = false;
3469 #if defined TIZEN_EXT
3470 static void set_connection_mode(struct connman_network *network,
3473 ieee80211_modes_e phy_mode;
3474 connection_mode_e conn_mode;
3476 phy_mode = connman_network_get_phy_mode(network);
3478 case IEEE80211_MODE_B:
3479 if (linkspeed > 0 && linkspeed <= 11)
3480 conn_mode = CONNECTION_MODE_IEEE80211B;
3482 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3485 case IEEE80211_MODE_BG:
3486 if (linkspeed > 0 && linkspeed <= 11)
3487 conn_mode = CONNECTION_MODE_IEEE80211B;
3488 else if (linkspeed > 11 && linkspeed <= 54)
3489 conn_mode = CONNECTION_MODE_IEEE80211G;
3491 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3494 case IEEE80211_MODE_BGN:
3495 if (linkspeed > 0 && linkspeed <= 11)
3496 conn_mode = CONNECTION_MODE_IEEE80211B;
3497 else if (linkspeed > 11 && linkspeed <= 54)
3498 conn_mode = CONNECTION_MODE_IEEE80211G;
3499 else if (linkspeed > 54 && linkspeed <= 450)
3500 conn_mode = CONNECTION_MODE_IEEE80211N;
3502 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3505 case IEEE80211_MODE_A:
3506 if (linkspeed > 0 && linkspeed <= 54)
3507 conn_mode = CONNECTION_MODE_IEEE80211A;
3509 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3512 case IEEE80211_MODE_AN:
3513 if (linkspeed > 0 && linkspeed <= 54)
3514 conn_mode = CONNECTION_MODE_IEEE80211A;
3515 else if (linkspeed > 54 && linkspeed <= 450)
3516 conn_mode = CONNECTION_MODE_IEEE80211N;
3518 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3521 case IEEE80211_MODE_ANAC:
3522 if (linkspeed > 0 && linkspeed <= 54)
3523 conn_mode = CONNECTION_MODE_IEEE80211A;
3524 else if (linkspeed > 54 && linkspeed <= 450)
3525 conn_mode = CONNECTION_MODE_IEEE80211N;
3526 else if (linkspeed > 450 && linkspeed <= 1300)
3527 conn_mode = CONNECTION_MODE_IEEE80211AC;
3529 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3533 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3537 DBG("connection mode(%d)", conn_mode);
3538 connman_network_set_connection_mode(network, conn_mode);
3541 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3543 struct connman_network *network = user_data;
3546 DBG("Failed to get maxspeed from signalpoll !");
3550 DBG("maxspeed = %d", maxspeed);
3552 connman_network_set_maxspeed(network, maxspeed);
3553 set_connection_mode(network, maxspeed);
3557 static int network_signalpoll(struct wifi_data *wifi)
3559 GSupplicantInterface *interface;
3560 struct connman_network *network;
3562 if (!wifi || !wifi->network)
3565 interface = wifi->interface;
3566 network = wifi->network;
3568 DBG("network %p", network);
3570 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3573 static gboolean autosignalpoll_timeout(gpointer data)
3575 struct wifi_data *wifi = data;
3577 if (!wifi || !wifi->automaxspeed_timeout) {
3578 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3582 int ret = network_signalpoll(wifi);
3584 DBG("Fail to get max speed !!");
3585 wifi->automaxspeed_timeout = 0;
3593 static struct connman_network_driver network_driver = {
3595 .type = CONNMAN_NETWORK_TYPE_WIFI,
3596 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3597 .probe = network_probe,
3598 .remove = network_remove,
3599 .connect = network_connect,
3600 .disconnect = network_disconnect,
3603 static void interface_added(GSupplicantInterface *interface)
3605 const char *ifname = g_supplicant_interface_get_ifname(interface);
3606 const char *driver = g_supplicant_interface_get_driver(interface);
3607 #if defined TIZEN_EXT
3608 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3611 struct wifi_data *wifi;
3613 wifi = g_supplicant_interface_get_data(interface);
3615 wifi = get_pending_wifi_data(ifname);
3619 wifi->interface = interface;
3620 g_supplicant_interface_set_data(interface, wifi);
3621 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3622 wifi->p2p_device = true;
3625 DBG("ifname %s driver %s wifi %p tethering %d",
3626 ifname, driver, wifi, wifi->tethering);
3628 if (!wifi->device) {
3629 connman_error("WiFi device not set");
3633 connman_device_set_powered(wifi->device, true);
3634 #if defined TIZEN_EXT
3635 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3639 static bool is_idle(struct wifi_data *wifi)
3641 DBG("state %d", wifi->state);
3643 switch (wifi->state) {
3644 case G_SUPPLICANT_STATE_UNKNOWN:
3645 case G_SUPPLICANT_STATE_DISABLED:
3646 case G_SUPPLICANT_STATE_DISCONNECTED:
3647 case G_SUPPLICANT_STATE_INACTIVE:
3648 case G_SUPPLICANT_STATE_SCANNING:
3651 case G_SUPPLICANT_STATE_AUTHENTICATING:
3652 case G_SUPPLICANT_STATE_ASSOCIATING:
3653 case G_SUPPLICANT_STATE_ASSOCIATED:
3654 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3655 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3656 case G_SUPPLICANT_STATE_COMPLETED:
3663 static bool is_idle_wps(GSupplicantInterface *interface,
3664 struct wifi_data *wifi)
3666 /* First, let's check if WPS processing did not went wrong */
3667 if (g_supplicant_interface_get_wps_state(interface) ==
3668 G_SUPPLICANT_WPS_STATE_FAIL)
3671 /* Unlike normal connection, being associated while processing wps
3672 * actually means that we are idling. */
3673 switch (wifi->state) {
3674 case G_SUPPLICANT_STATE_UNKNOWN:
3675 case G_SUPPLICANT_STATE_DISABLED:
3676 case G_SUPPLICANT_STATE_DISCONNECTED:
3677 case G_SUPPLICANT_STATE_INACTIVE:
3678 case G_SUPPLICANT_STATE_SCANNING:
3679 case G_SUPPLICANT_STATE_ASSOCIATED:
3681 case G_SUPPLICANT_STATE_AUTHENTICATING:
3682 case G_SUPPLICANT_STATE_ASSOCIATING:
3683 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3684 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3685 case G_SUPPLICANT_STATE_COMPLETED:
3692 static bool handle_wps_completion(GSupplicantInterface *interface,
3693 struct connman_network *network,
3694 struct connman_device *device,
3695 struct wifi_data *wifi)
3699 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3701 const unsigned char *ssid, *wps_ssid;
3702 unsigned int ssid_len, wps_ssid_len;
3703 const char *wps_key;
3705 /* Checking if we got associated with requested
3707 ssid = connman_network_get_blob(network, "WiFi.SSID",
3710 wps_ssid = g_supplicant_interface_get_wps_ssid(
3711 interface, &wps_ssid_len);
3713 if (!wps_ssid || wps_ssid_len != ssid_len ||
3714 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3715 connman_network_set_associating(network, false);
3716 #if defined TIZEN_EXT
3717 g_supplicant_interface_disconnect(wifi->interface,
3718 disconnect_callback, wifi->network);
3720 connman_network_set_bool(network, "WiFi.UseWPS", false);
3721 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3723 g_supplicant_interface_disconnect(wifi->interface,
3724 disconnect_callback, wifi);
3729 wps_key = g_supplicant_interface_get_wps_key(interface);
3730 #if defined TIZEN_EXT
3731 /* Check the passphrase and encrypt it
3734 gchar *passphrase = g_strdup(wps_key);
3736 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3738 if (check_passphrase_ext(network, passphrase) < 0) {
3739 DBG("[WPS] Invalid passphrase");
3744 ret = send_encryption_request(passphrase, network);
3749 DBG("[WPS] Encryption request succeeded");
3751 DBG("[WPS] Encryption request failed %d", ret);
3754 connman_network_set_string(network, "WiFi.Passphrase",
3757 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3764 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3765 struct wifi_data *wifi)
3767 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3768 #if defined TIZEN_EXT
3769 wifi->assoc_code > 0 &&
3771 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3773 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3774 wifi->load_shaping_retries ++;
3777 wifi->load_shaping_retries = 0;
3781 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3782 struct connman_network *network,
3783 struct wifi_data *wifi)
3785 #if defined TIZEN_EXT
3786 const char *security;
3787 struct connman_service *service;
3789 if (wifi->connected)
3792 security = connman_network_get_string(network, "WiFi.Security");
3794 if (security && g_str_equal(security, "ieee8021x") == true &&
3795 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3797 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3802 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3805 struct connman_service *service;
3807 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3810 if (wifi->connected)
3814 service = connman_service_lookup_from_network(network);
3820 if (connman_service_get_favorite(service)) {
3821 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3826 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3831 #if defined TIZEN_EXT
3832 static bool handle_wifi_assoc_retry(struct connman_network *network,
3833 struct wifi_data *wifi)
3835 const char *security;
3837 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3838 connman_network_get_connecting(network) != true) {
3839 wifi->assoc_retry_count = 0;
3843 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3844 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3845 wifi->assoc_retry_count = 0;
3849 security = connman_network_get_string(network, "WiFi.Security");
3850 if (security && g_str_equal(security, "ieee8021x") == true &&
3851 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3852 wifi->assoc_retry_count = 0;
3856 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3857 wifi->assoc_retry_count = 0;
3859 /* Honestly it's not an invalid-key error,
3860 * however QA team recommends that the invalid-key error
3861 * might be better to display for user experience.
3863 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3872 static void interface_state(GSupplicantInterface *interface)
3874 struct connman_network *network;
3875 struct connman_device *device;
3876 struct wifi_data *wifi;
3877 GSupplicantState state = g_supplicant_interface_get_state(interface);
3881 wifi = g_supplicant_interface_get_data(interface);
3883 DBG("wifi %p interface state %d", wifi, state);
3888 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3889 if (wifi->tethering_param) {
3890 g_free(wifi->tethering_param->ssid);
3891 g_free(wifi->tethering_param);
3892 wifi->tethering_param = NULL;
3896 device = wifi->device;
3900 if (g_supplicant_interface_get_ready(interface) &&
3901 !wifi->interface_ready) {
3902 wifi->interface_ready = true;
3903 finalize_interface_creation(wifi);
3906 network = wifi->network;
3911 case G_SUPPLICANT_STATE_SCANNING:
3912 if (wifi->connected)
3913 connman_network_set_connected(network, false);
3917 case G_SUPPLICANT_STATE_AUTHENTICATING:
3918 case G_SUPPLICANT_STATE_ASSOCIATING:
3919 #if defined TIZEN_EXT
3920 reset_autoscan(device);
3922 stop_autoscan(device);
3925 if (!wifi->connected)
3926 connman_network_set_associating(network, true);
3930 case G_SUPPLICANT_STATE_COMPLETED:
3931 #if defined TIZEN_EXT
3932 /* though it should be already reset: */
3933 reset_autoscan(device);
3935 wifi->assoc_retry_count = 0;
3937 wifi->scan_pending_network = NULL;
3939 /* should be cleared scanning flag */
3940 bool scanning = connman_device_get_scanning(device);
3942 connman_device_set_scanning(device,
3943 CONNMAN_SERVICE_TYPE_WIFI, false);
3944 connman_device_unref(device);
3947 if (!wifi->automaxspeed_timeout) {
3948 DBG("Going to start signalpoll timer!!");
3949 int ret = network_signalpoll(wifi);
3951 DBG("Fail to get max speed !!");
3953 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
3956 /* though it should be already stopped: */
3957 stop_autoscan(device);
3960 if (!handle_wps_completion(interface, network, device, wifi))
3963 connman_network_set_connected(network, true);
3965 wifi->disconnect_code = 0;
3966 wifi->assoc_code = 0;
3967 wifi->load_shaping_retries = 0;
3970 case G_SUPPLICANT_STATE_DISCONNECTED:
3971 #if defined TIZEN_EXT
3972 connman_network_set_maxspeed(network, 0);
3974 if (wifi->automaxspeed_timeout != 0) {
3975 g_source_remove(wifi->automaxspeed_timeout);
3976 wifi->automaxspeed_timeout = 0;
3977 DBG("Remove signalpoll timer!!");
3981 * If we're in one of the idle modes, we have
3982 * not started association yet and thus setting
3983 * those ones to FALSE could cancel an association
3986 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3988 if (is_idle_wps(interface, wifi))
3994 #if defined TIZEN_EXT
3995 if (handle_assoc_status_code(interface, wifi)) {
3996 network_connect(network);
4000 if (handle_assoc_status_code(interface, wifi))
4004 /* If previous state was 4way-handshake, then
4005 * it's either: psk was incorrect and thus we retry
4006 * or if we reach the maximum retries we declare the
4008 if (handle_4way_handshake_failure(interface,
4012 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4013 switch (wifi->disconnect_code) {
4014 case 1: /* Unspecified reason */
4015 /* Let's assume it's because we got blocked */
4017 case 6: /* Class 2 frame received from nonauthenticated STA */
4018 connman_network_set_error(network,
4019 CONNMAN_NETWORK_ERROR_BLOCKED);
4026 #if defined TIZEN_EXT
4027 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4028 * Retry association until its retry count is expired */
4029 if (handle_wifi_assoc_retry(network, wifi) == true) {
4030 throw_wifi_scan(wifi->device, scan_callback);
4031 wifi->scan_pending_network = wifi->network;
4035 if(wifi->disconnect_code > 0){
4036 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4037 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4041 connman_network_set_connected(network, false);
4042 connman_network_set_associating(network, false);
4043 wifi->disconnecting = false;
4045 start_autoscan(device);
4049 case G_SUPPLICANT_STATE_INACTIVE:
4050 #if defined TIZEN_EXT
4051 if (handle_wps_completion(interface, network, device, wifi) == false)
4054 connman_network_set_associating(network, false);
4055 start_autoscan(device);
4059 case G_SUPPLICANT_STATE_UNKNOWN:
4060 case G_SUPPLICANT_STATE_DISABLED:
4061 case G_SUPPLICANT_STATE_ASSOCIATED:
4062 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4063 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4067 old_connected = wifi->connected;
4068 wifi->state = state;
4070 /* Saving wpa_s state policy:
4071 * If connected and if the state changes are roaming related:
4072 * --> We stay connected
4074 * --> We are connected
4076 * --> We are not connected
4079 case G_SUPPLICANT_STATE_AUTHENTICATING:
4080 case G_SUPPLICANT_STATE_ASSOCIATING:
4081 case G_SUPPLICANT_STATE_ASSOCIATED:
4082 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4083 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4084 if (wifi->connected)
4085 connman_warn("Probably roaming right now!"
4086 " Staying connected...");
4088 case G_SUPPLICANT_STATE_SCANNING:
4089 wifi->connected = false;
4092 start_autoscan(device);
4094 case G_SUPPLICANT_STATE_COMPLETED:
4095 wifi->connected = true;
4098 wifi->connected = false;
4105 static void interface_removed(GSupplicantInterface *interface)
4107 const char *ifname = g_supplicant_interface_get_ifname(interface);
4108 struct wifi_data *wifi;
4110 DBG("ifname %s", ifname);
4112 wifi = g_supplicant_interface_get_data(interface);
4114 #if defined TIZEN_EXT_WIFI_MESH
4115 if (wifi && wifi->mesh_interface) {
4116 DBG("Notify mesh interface remove");
4117 connman_mesh_notify_interface_remove(true);
4118 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4119 g_free(mesh_info->parent_ifname);
4120 g_free(mesh_info->ifname);
4121 g_free(mesh_info->identifier);
4123 wifi->mesh_interface = false;
4124 wifi->mesh_info = NULL;
4130 wifi->interface = NULL;
4132 if (wifi && wifi->tethering)
4135 if (!wifi || !wifi->device) {
4136 DBG("wifi interface already removed");
4140 connman_device_set_powered(wifi->device, false);
4142 check_p2p_technology();
4143 #if defined TIZEN_EXT_WIFI_MESH
4144 check_mesh_technology();
4148 static void set_device_type(const char *type, char dev_type[17])
4150 const char *oui = "0050F204";
4151 const char *category = "0001";
4152 const char *sub_category = "0000";
4154 if (!g_strcmp0(type, "handset")) {
4156 sub_category = "0005";
4157 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4158 sub_category = "0001";
4159 else if (!g_strcmp0(type, "server"))
4160 sub_category = "0002";
4161 else if (!g_strcmp0(type, "laptop"))
4162 sub_category = "0005";
4163 else if (!g_strcmp0(type, "desktop"))
4164 sub_category = "0006";
4165 else if (!g_strcmp0(type, "tablet"))
4166 sub_category = "0009";
4167 else if (!g_strcmp0(type, "watch"))
4170 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4173 static void p2p_support(GSupplicantInterface *interface)
4175 char dev_type[17] = {};
4176 const char *hostname;
4183 if (!g_supplicant_interface_has_p2p(interface))
4186 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4187 DBG("Could not register P2P technology driver");
4191 hostname = connman_utsname_get_hostname();
4193 hostname = "ConnMan";
4195 set_device_type(connman_machine_get_type(), dev_type);
4196 g_supplicant_interface_set_p2p_device_config(interface,
4197 hostname, dev_type);
4198 connman_peer_driver_register(&peer_driver);
4201 static void scan_started(GSupplicantInterface *interface)
4206 static void scan_finished(GSupplicantInterface *interface)
4208 #if defined TIZEN_EXT
4209 struct wifi_data *wifi;
4210 bool is_associating = false;
4211 static bool is_scanning = true;
4216 #if defined TIZEN_EXT
4217 wifi = g_supplicant_interface_get_data(interface);
4218 if (wifi && wifi->scan_pending_network) {
4219 network_connect(wifi->scan_pending_network);
4220 wifi->scan_pending_network = NULL;
4223 //service state - associating
4224 if(!wifi || !wifi->network)
4227 is_associating = connman_network_get_associating(wifi->network);
4228 if(is_associating && is_scanning){
4229 is_scanning = false;
4230 DBG("send scan for connecting");
4231 throw_wifi_scan(wifi->device, scan_callback);
4242 static void ap_create_fail(GSupplicantInterface *interface)
4244 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4247 if ((wifi->tethering) && (wifi->tethering_param)) {
4248 DBG("%s create AP fail \n",
4249 g_supplicant_interface_get_ifname(wifi->interface));
4251 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4252 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4253 wifi->tethering = false;
4255 ret = tech_set_tethering(wifi->tethering_param->technology,
4256 wifi->tethering_param->ssid->ssid,
4257 wifi->tethering_param->ssid->passphrase,
4258 wifi->bridge, true);
4260 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4261 connman_technology_tethering_notify(wifi_technology,false);
4264 g_free(wifi->tethering_param->ssid);
4265 g_free(wifi->tethering_param);
4266 wifi->tethering_param = NULL;
4272 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4274 unsigned char strength;
4276 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4278 #if !defined TIZEN_EXT
4285 #if defined TIZEN_EXT_WIFI_MESH
4286 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4288 GSupplicantInterface *interface;
4289 struct wifi_data *wifi;
4290 const char *name, *security;
4291 struct connman_mesh *connman_mesh;
4292 struct wifi_mesh_info *mesh_info;
4293 const unsigned char *bssid;
4294 const char *identifier;
4299 interface = g_supplicant_network_get_interface(supplicant_network);
4300 wifi = g_supplicant_interface_get_data(interface);
4301 if (!wifi || !wifi->mesh_interface) {
4302 DBG("Virtual Mesh interface not created");
4306 bssid = g_supplicant_network_get_bssid(supplicant_network);
4307 address = g_malloc0(19);
4308 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4309 bssid[2], bssid[3], bssid[4], bssid[5]);
4311 identifier = g_supplicant_network_get_identifier(supplicant_network);
4312 name = g_supplicant_network_get_name(supplicant_network);
4313 security = g_supplicant_network_get_security(supplicant_network);
4314 frequency = g_supplicant_network_get_frequency(supplicant_network);
4316 mesh_info = wifi->mesh_info;
4317 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4321 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4323 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4324 connman_mesh_set_name(connman_mesh, name);
4325 connman_mesh_set_security(connman_mesh, security);
4326 connman_mesh_set_frequency(connman_mesh, frequency);
4327 connman_mesh_set_address(connman_mesh, address);
4328 connman_mesh_set_index(connman_mesh, mesh_info->index);
4329 connman_mesh_set_strength(connman_mesh,
4330 calculate_strength(supplicant_network));
4331 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4333 ret = connman_mesh_register(connman_mesh);
4334 if (ret == -EALREADY)
4335 DBG("Mesh Peer is already registered");
4341 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4343 GSupplicantInterface *interface;
4344 struct wifi_data *wifi;
4345 struct connman_mesh *connman_mesh;
4346 struct wifi_mesh_info *mesh_info;
4347 const char *identifier;
4349 interface = g_supplicant_network_get_interface(supplicant_network);
4350 wifi = g_supplicant_interface_get_data(interface);
4351 if (!wifi || !wifi->mesh_interface) {
4352 DBG("Virtual Mesh interface not created");
4356 identifier = g_supplicant_network_get_identifier(supplicant_network);
4358 DBG("Failed to get Mesh Peer identifier");
4362 mesh_info = wifi->mesh_info;
4363 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4365 /* Do not unregister connected mesh peer */
4366 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4367 DBG("Mesh Peer %s is connected", identifier);
4370 DBG("Mesh Peer identifier %s removed", identifier);
4371 connman_mesh_unregister(connman_mesh);
4376 static void network_added(GSupplicantNetwork *supplicant_network)
4378 struct connman_network *network;
4379 GSupplicantInterface *interface;
4380 struct wifi_data *wifi;
4381 const char *name, *identifier, *security, *group, *mode;
4382 const unsigned char *ssid;
4383 unsigned int ssid_len;
4387 bool wps_advertizing;
4389 #if defined TIZEN_EXT
4390 GSList *vsie_list = NULL;
4391 const unsigned char *country_code;
4392 ieee80211_modes_e phy_mode;
4395 mode = g_supplicant_network_get_mode(supplicant_network);
4396 identifier = g_supplicant_network_get_identifier(supplicant_network);
4398 DBG("%s", identifier);
4400 if (!g_strcmp0(mode, "adhoc"))
4403 #if defined TIZEN_EXT_WIFI_MESH
4404 if (!g_strcmp0(mode, "mesh")) {
4405 mesh_peer_added(supplicant_network);
4410 interface = g_supplicant_network_get_interface(supplicant_network);
4411 wifi = g_supplicant_interface_get_data(interface);
4412 name = g_supplicant_network_get_name(supplicant_network);
4413 security = g_supplicant_network_get_security(supplicant_network);
4414 group = g_supplicant_network_get_identifier(supplicant_network);
4415 wps = g_supplicant_network_get_wps(supplicant_network);
4416 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4417 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4418 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4419 supplicant_network);
4424 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4426 network = connman_device_get_network(wifi->device, identifier);
4429 network = connman_network_create(identifier,
4430 CONNMAN_NETWORK_TYPE_WIFI);
4434 connman_network_set_index(network, wifi->index);
4436 if (connman_device_add_network(wifi->device, network) < 0) {
4437 connman_network_unref(network);
4441 wifi->networks = g_slist_prepend(wifi->networks, network);
4444 if (name && name[0] != '\0')
4445 connman_network_set_name(network, name);
4447 connman_network_set_blob(network, "WiFi.SSID",
4449 #if defined TIZEN_EXT
4450 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4452 connman_network_set_vsie_list(network, vsie_list);
4454 DBG("vsie_list is NULL");
4455 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4456 connman_network_set_countrycode(network, country_code);
4457 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4458 connman_network_set_phy_mode(network, phy_mode);
4460 connman_network_set_string(network, "WiFi.Security", security);
4461 connman_network_set_strength(network,
4462 calculate_strength(supplicant_network));
4463 connman_network_set_bool(network, "WiFi.WPS", wps);
4466 /* Is AP advertizing for WPS association?
4467 * If so, we decide to use WPS by default */
4468 if (wps_ready && wps_pbc &&
4470 #if !defined TIZEN_EXT
4471 connman_network_set_bool(network, "WiFi.UseWPS", true);
4473 DBG("wps is activating by ap but ignore it.");
4478 connman_network_set_frequency(network,
4479 g_supplicant_network_get_frequency(supplicant_network));
4480 #if defined TIZEN_EXT
4481 connman_network_set_bssid(network,
4482 g_supplicant_network_get_bssid(supplicant_network));
4483 connman_network_set_maxrate(network,
4484 g_supplicant_network_get_maxrate(supplicant_network));
4485 connman_network_set_enc_mode(network,
4486 g_supplicant_network_get_enc_mode(supplicant_network));
4487 connman_network_set_rsn_mode(network,
4488 g_supplicant_network_get_rsn_mode(supplicant_network));
4489 connman_network_set_keymgmt(network,
4490 g_supplicant_network_get_keymgmt(supplicant_network));
4491 connman_network_set_bool(network, "WiFi.HS20AP",
4492 g_supplicant_network_is_hs20AP(supplicant_network));
4493 connman_network_set_bssid_list(network,
4494 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4496 connman_network_set_available(network, true);
4497 connman_network_set_string(network, "WiFi.Mode", mode);
4499 #if defined TIZEN_EXT
4504 connman_network_set_group(network, group);
4506 #if defined TIZEN_EXT
4507 if (wifi_first_scan == true)
4508 found_with_first_scan = true;
4511 if (wifi->hidden && ssid) {
4512 #if defined TIZEN_EXT
4513 if (network_security(wifi->hidden->security) ==
4514 network_security(security) &&
4516 if (!g_strcmp0(wifi->hidden->security, security) &&
4518 wifi->hidden->ssid_len == ssid_len &&
4519 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4520 connman_network_connect_hidden(network,
4521 wifi->hidden->identity,
4522 wifi->hidden->passphrase,
4523 wifi->hidden->user_data);
4524 wifi->hidden->user_data = NULL;
4525 hidden_free(wifi->hidden);
4526 wifi->hidden = NULL;
4531 static void network_removed(GSupplicantNetwork *network)
4533 GSupplicantInterface *interface;
4534 struct wifi_data *wifi;
4535 const char *name, *identifier;
4536 struct connman_network *connman_network;
4538 #if defined TIZEN_EXT_WIFI_MESH
4540 mode = g_supplicant_network_get_mode(network);
4541 if (!g_strcmp0(mode, "mesh")) {
4542 mesh_peer_removed(network);
4547 interface = g_supplicant_network_get_interface(network);
4548 wifi = g_supplicant_interface_get_data(interface);
4549 identifier = g_supplicant_network_get_identifier(network);
4550 name = g_supplicant_network_get_name(network);
4552 DBG("name %s", name);
4557 connman_network = connman_device_get_network(wifi->device, identifier);
4558 if (!connman_network)
4561 #if defined TIZEN_EXT
4562 if (connman_network == wifi->scan_pending_network)
4563 wifi->scan_pending_network = NULL;
4565 if (connman_network == wifi->pending_network)
4566 wifi->pending_network = NULL;
4568 if(connman_network_get_connecting(connman_network) == true){
4569 connman_network_set_connected(connman_network, false);
4573 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4575 connman_device_remove_network(wifi->device, connman_network);
4576 connman_network_unref(connman_network);
4579 static void network_changed(GSupplicantNetwork *network, const char *property)
4581 GSupplicantInterface *interface;
4582 struct wifi_data *wifi;
4583 const char *name, *identifier;
4584 struct connman_network *connman_network;
4586 #if defined TIZEN_EXT
4587 const unsigned char *bssid;
4588 unsigned int maxrate;
4591 const unsigned char *country_code;
4592 ieee80211_modes_e phy_mode;
4596 interface = g_supplicant_network_get_interface(network);
4597 wifi = g_supplicant_interface_get_data(interface);
4598 identifier = g_supplicant_network_get_identifier(network);
4599 name = g_supplicant_network_get_name(network);
4601 DBG("name %s", name);
4606 connman_network = connman_device_get_network(wifi->device, identifier);
4607 if (!connman_network)
4610 if (g_str_equal(property, "Signal")) {
4611 connman_network_set_strength(connman_network,
4612 calculate_strength(network));
4613 connman_network_update(connman_network);
4616 #if defined TIZEN_EXT
4617 bssid = g_supplicant_network_get_bssid(network);
4618 maxrate = g_supplicant_network_get_maxrate(network);
4619 frequency = g_supplicant_network_get_frequency(network);
4620 wps = g_supplicant_network_get_wps(network);
4621 phy_mode = g_supplicant_network_get_phy_mode(network);
4623 connman_network_set_bssid(connman_network, bssid);
4624 connman_network_set_maxrate(connman_network, maxrate);
4625 connman_network_set_frequency(connman_network, frequency);
4626 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4627 country_code = g_supplicant_network_get_countrycode(network);
4628 connman_network_set_countrycode(connman_network, country_code);
4629 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4630 connman_network_set_bssid_list(connman_network, bssid_list);
4631 connman_network_set_phy_mode(connman_network, phy_mode);
4633 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4634 connman_network_get_associating(connman_network))
4635 network_connect(connman_network);
4639 static void network_associated(GSupplicantNetwork *network)
4641 GSupplicantInterface *interface;
4642 struct wifi_data *wifi;
4643 struct connman_network *connman_network;
4644 const char *identifier;
4648 interface = g_supplicant_network_get_interface(network);
4652 wifi = g_supplicant_interface_get_data(interface);
4656 identifier = g_supplicant_network_get_identifier(network);
4658 connman_network = connman_device_get_network(wifi->device, identifier);
4659 if (!connman_network)
4662 if (wifi->network) {
4663 if (wifi->network == connman_network)
4667 * This should never happen, we got associated with
4668 * a network different than the one we were expecting.
4670 DBG("Associated to %p while expecting %p",
4671 connman_network, wifi->network);
4673 connman_network_set_associating(wifi->network, false);
4676 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4678 wifi->network = connman_network_ref(connman_network);
4682 * Interface state changes callback (interface_state) is always
4683 * called before network_associated callback thus we need to call
4684 * interface_state again in order to process the new state now that
4685 * we have the network properly set.
4687 interface_state(interface);
4690 static void apply_peer_services(GSupplicantPeer *peer,
4691 struct connman_peer *connman_peer)
4693 const unsigned char *data;
4698 connman_peer_reset_services(connman_peer);
4700 data = g_supplicant_peer_get_widi_ies(peer, &length);
4702 connman_peer_add_service(connman_peer,
4703 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4707 static void add_station(const char *mac)
4709 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4713 static void remove_station(const char *mac)
4715 connman_technology_tethering_remove_station(mac);
4718 static void peer_found(GSupplicantPeer *peer)
4720 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4721 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4722 struct connman_peer *connman_peer;
4723 const char *identifier, *name;
4725 #if defined TIZEN_EXT
4729 identifier = g_supplicant_peer_get_identifier(peer);
4730 name = g_supplicant_peer_get_name(peer);
4732 DBG("ident: %s", identifier);
4734 connman_peer = connman_peer_get(wifi->device, identifier);
4738 connman_peer = connman_peer_create(identifier);
4739 connman_peer_set_name(connman_peer, name);
4740 connman_peer_set_device(connman_peer, wifi->device);
4741 apply_peer_services(peer, connman_peer);
4743 ret = connman_peer_register(connman_peer);
4744 if (ret < 0 && ret != -EALREADY)
4745 connman_peer_unref(connman_peer);
4747 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4750 static void peer_lost(GSupplicantPeer *peer)
4752 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4753 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4754 struct connman_peer *connman_peer;
4755 const char *identifier;
4760 identifier = g_supplicant_peer_get_identifier(peer);
4762 DBG("ident: %s", identifier);
4764 connman_peer = connman_peer_get(wifi->device, identifier);
4766 if (wifi->p2p_connecting &&
4767 wifi->pending_peer == connman_peer) {
4768 peer_connect_timeout(wifi);
4770 connman_peer_unregister(connman_peer);
4771 connman_peer_unref(connman_peer);
4774 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4777 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4779 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4780 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4781 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4782 struct connman_peer *connman_peer;
4783 const char *identifier;
4785 identifier = g_supplicant_peer_get_identifier(peer);
4787 DBG("ident: %s", identifier);
4792 connman_peer = connman_peer_get(wifi->device, identifier);
4797 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4798 apply_peer_services(peer, connman_peer);
4799 connman_peer_services_changed(connman_peer);
4801 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4802 if (!g_supplicant_peer_is_in_a_group(peer))
4803 p_state = CONNMAN_PEER_STATE_IDLE;
4805 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4807 case G_SUPPLICANT_PEER_GROUP_STARTED:
4809 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4810 p_state = CONNMAN_PEER_STATE_IDLE;
4812 case G_SUPPLICANT_PEER_GROUP_JOINED:
4813 connman_peer_set_iface_address(connman_peer,
4814 g_supplicant_peer_get_iface_address(peer));
4816 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4817 p_state = CONNMAN_PEER_STATE_IDLE;
4819 case G_SUPPLICANT_PEER_GROUP_FAILED:
4820 if (g_supplicant_peer_has_requested_connection(peer))
4821 p_state = CONNMAN_PEER_STATE_IDLE;
4823 p_state = CONNMAN_PEER_STATE_FAILURE;
4827 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4828 p_state == CONNMAN_PEER_STATE_FAILURE) {
4829 if (wifi->p2p_connecting
4830 && connman_peer == wifi->pending_peer)
4831 peer_cancel_timeout(wifi);
4833 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4836 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4839 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4840 GSupplicantInterface *g_iface;
4841 struct wifi_data *g_wifi;
4843 g_iface = g_supplicant_peer_get_group_interface(peer);
4847 g_wifi = g_supplicant_interface_get_data(g_iface);
4851 connman_peer_set_as_master(connman_peer,
4852 !g_supplicant_peer_is_client(peer));
4853 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4856 * If wpa_supplicant didn't create a dedicated p2p-group
4857 * interface then mark this interface as p2p_device to avoid
4858 * scan and auto-scan are launched on it while P2P is connected.
4860 if (!g_list_find(p2p_iface_list, g_wifi))
4861 wifi->p2p_device = true;
4864 connman_peer_set_state(connman_peer, p_state);
4867 static void peer_request(GSupplicantPeer *peer)
4869 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4870 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4871 struct connman_peer *connman_peer;
4872 const char *identifier;
4874 #if defined TIZEN_EXT
4879 identifier = g_supplicant_peer_get_identifier(peer);
4881 DBG("ident: %s", identifier);
4883 connman_peer = connman_peer_get(wifi->device, identifier);
4887 connman_peer_request_connection(connman_peer);
4890 #if defined TIZEN_EXT
4891 static void system_power_off(void)
4894 struct wifi_data *wifi;
4895 struct connman_service *service;
4896 struct connman_ipconfig *ipconfig_ipv4;
4898 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4899 for (list = iface_list; list; list = list->next) {
4902 if (wifi->network != NULL) {
4903 service = connman_service_lookup_from_network(wifi->network);
4904 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4905 __connman_dhcp_stop(ipconfig_ipv4);
4911 static void network_merged(GSupplicantNetwork *network)
4913 GSupplicantInterface *interface;
4914 GSupplicantState state;
4915 struct wifi_data *wifi;
4916 const char *identifier;
4917 struct connman_network *connman_network;
4921 interface = g_supplicant_network_get_interface(network);
4925 state = g_supplicant_interface_get_state(interface);
4926 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4929 wifi = g_supplicant_interface_get_data(interface);
4933 identifier = g_supplicant_network_get_identifier(network);
4935 connman_network = connman_device_get_network(wifi->device, identifier);
4936 if (!connman_network)
4939 DBG("merged identifier %s", identifier);
4941 if (wifi->connected == FALSE) {
4943 case G_SUPPLICANT_STATE_AUTHENTICATING:
4944 case G_SUPPLICANT_STATE_ASSOCIATING:
4945 case G_SUPPLICANT_STATE_ASSOCIATED:
4946 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4947 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4948 connman_network_set_associating(connman_network, TRUE);
4950 case G_SUPPLICANT_STATE_COMPLETED:
4951 connman_network_set_connected(connman_network, TRUE);
4954 DBG("Not handled the state : %d", state);
4959 ishs20AP = g_supplicant_network_is_hs20AP(network);
4962 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
4963 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
4964 connman_network_set_string(connman_network, "WiFi.EAP",
4966 connman_network_set_string(connman_network, "WiFi.Identity",
4967 g_supplicant_network_get_identity(network));
4968 connman_network_set_string(connman_network, "WiFi.Phase2",
4969 g_supplicant_network_get_phase2(network));
4974 wifi->network = connman_network;
4977 static void assoc_failed(void *user_data)
4979 struct connman_network *network = user_data;
4980 connman_network_set_associating(network, false);
4984 static void debug(const char *str)
4986 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
4987 connman_debug("%s", str);
4990 static void disconnect_reasoncode(GSupplicantInterface *interface,
4993 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4996 wifi->disconnect_code = reasoncode;
5000 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5002 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5005 wifi->assoc_code = status_code;
5009 static const GSupplicantCallbacks callbacks = {
5010 .system_ready = system_ready,
5011 .system_killed = system_killed,
5012 .interface_added = interface_added,
5013 .interface_state = interface_state,
5014 .interface_removed = interface_removed,
5015 .p2p_support = p2p_support,
5016 .scan_started = scan_started,
5017 .scan_finished = scan_finished,
5018 .ap_create_fail = ap_create_fail,
5019 .network_added = network_added,
5020 .network_removed = network_removed,
5021 .network_changed = network_changed,
5022 .network_associated = network_associated,
5023 .add_station = add_station,
5024 .remove_station = remove_station,
5025 .peer_found = peer_found,
5026 .peer_lost = peer_lost,
5027 .peer_changed = peer_changed,
5028 .peer_request = peer_request,
5029 #if defined TIZEN_EXT
5030 .system_power_off = system_power_off,
5031 .network_merged = network_merged,
5032 .assoc_failed = assoc_failed,
5035 .disconnect_reasoncode = disconnect_reasoncode,
5036 .assoc_status_code = assoc_status_code,
5037 #if defined TIZEN_EXT_WIFI_MESH
5038 .mesh_support = mesh_support,
5039 .mesh_group_started = mesh_group_started,
5040 .mesh_group_removed = mesh_group_removed,
5041 .mesh_peer_connected = mesh_peer_connected,
5042 .mesh_peer_disconnected = mesh_peer_disconnected,
5047 static int tech_probe(struct connman_technology *technology)
5049 wifi_technology = technology;
5054 static void tech_remove(struct connman_technology *technology)
5056 wifi_technology = NULL;
5059 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5060 const char *passphrase)
5062 GSupplicantSSID *ap;
5064 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5068 ap->mode = G_SUPPLICANT_MODE_MASTER;
5069 #if defined TIZEN_EXT
5070 ap->ssid = (void *) ssid;
5074 ap->ssid_len = strlen(ssid);
5078 if (!passphrase || strlen(passphrase) == 0) {
5079 ap->security = G_SUPPLICANT_SECURITY_NONE;
5080 ap->passphrase = NULL;
5082 ap->security = G_SUPPLICANT_SECURITY_PSK;
5083 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5084 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5085 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5086 ap->passphrase = passphrase;
5092 static void ap_start_callback(int result, GSupplicantInterface *interface,
5095 struct wifi_tethering_info *info = user_data;
5097 DBG("result %d index %d bridge %s",
5098 result, info->wifi->index, info->wifi->bridge);
5100 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5101 connman_inet_remove_from_bridge(info->wifi->index,
5102 info->wifi->bridge);
5104 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5105 connman_technology_tethering_notify(info->technology, false);
5106 g_free(info->wifi->tethering_param->ssid);
5107 g_free(info->wifi->tethering_param);
5108 info->wifi->tethering_param = NULL;
5112 g_free(info->ifname);
5116 static void ap_create_callback(int result,
5117 GSupplicantInterface *interface,
5120 struct wifi_tethering_info *info = user_data;
5122 DBG("result %d ifname %s", result,
5123 g_supplicant_interface_get_ifname(interface));
5125 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5126 connman_inet_remove_from_bridge(info->wifi->index,
5127 info->wifi->bridge);
5129 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5130 connman_technology_tethering_notify(info->technology, false);
5131 g_free(info->wifi->tethering_param->ssid);
5132 g_free(info->wifi->tethering_param);
5133 info->wifi->tethering_param = NULL;
5137 g_free(info->ifname);
5143 info->wifi->interface = interface;
5144 g_supplicant_interface_set_data(interface, info->wifi);
5146 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5147 connman_error("Failed to set interface ap_scan property");
5149 g_supplicant_interface_connect(interface, info->ssid,
5150 ap_start_callback, info);
5153 static void sta_remove_callback(int result,
5154 GSupplicantInterface *interface,
5157 struct wifi_tethering_info *info = user_data;
5158 const char *driver = connman_option_get_string("wifi");
5160 DBG("ifname %s result %d ", info->ifname, result);
5162 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5163 info->wifi->tethering = false;
5164 connman_technology_tethering_notify(info->technology, false);
5166 g_free(info->ifname);
5170 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5171 g_free(info->wifi->tethering_param->ssid);
5172 g_free(info->wifi->tethering_param);
5173 info->wifi->tethering_param = NULL;
5178 info->wifi->interface = NULL;
5180 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5185 static int enable_wifi_tethering(struct connman_technology *technology,
5186 const char *bridge, const char *identifier,
5187 const char *passphrase, bool available)
5190 GSupplicantInterface *interface;
5191 struct wifi_data *wifi;
5192 struct wifi_tethering_info *info;
5197 for (list = iface_list; list; list = list->next) {
5200 DBG("wifi %p network %p pending_network %p", wifi,
5201 wifi->network, wifi->pending_network);
5203 interface = wifi->interface;
5208 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5211 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5213 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5214 DBG("%s does not support AP mode (detected)", ifname);
5218 mode = g_supplicant_interface_get_mode(interface);
5219 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5220 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5221 DBG("%s does not support AP mode (capability)", ifname);
5225 if (wifi->network && available)
5228 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5232 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5233 if (!wifi->tethering_param) {
5239 info->technology = technology;
5240 info->wifi->bridge = bridge;
5241 info->ssid = ssid_ap_init(identifier, passphrase);
5245 info->ifname = g_strdup(ifname);
5249 wifi->tethering_param->technology = technology;
5250 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5251 if (!wifi->tethering_param->ssid)
5254 info->wifi->tethering = true;
5255 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5257 berr = connman_technology_tethering_notify(technology, true);
5261 err = g_supplicant_interface_remove(interface,
5262 sta_remove_callback,
5265 DBG("tethering wifi %p ifname %s", wifi, ifname);
5270 g_free(info->ifname);
5273 g_free(wifi->tethering_param);
5274 wifi->tethering_param = NULL;
5277 * Remove bridge if it was correctly created but remove
5278 * operation failed. Instead, if bridge creation failed then
5279 * break out and do not try again on another interface,
5280 * bridge set-up does not depend on it.
5283 connman_technology_tethering_notify(technology, false);
5291 static int tech_set_tethering(struct connman_technology *technology,
5292 const char *identifier, const char *passphrase,
5293 const char *bridge, bool enabled)
5296 struct wifi_data *wifi;
5302 for (list = iface_list; list; list = list->next) {
5305 if (wifi->tethering) {
5306 wifi->tethering = false;
5308 connman_inet_remove_from_bridge(wifi->index,
5310 wifi->bridged = false;
5314 connman_technology_tethering_notify(technology, false);
5319 DBG("trying tethering for available devices");
5320 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5324 DBG("trying tethering for any device");
5325 err = enable_wifi_tethering(technology, bridge, identifier,
5332 static void regdom_callback(int result, const char *alpha2, void *user_data)
5336 if (!wifi_technology)
5342 connman_technology_regdom_notify(wifi_technology, alpha2);
5345 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5347 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5350 static struct connman_technology_driver tech_driver = {
5352 .type = CONNMAN_SERVICE_TYPE_WIFI,
5353 .probe = tech_probe,
5354 .remove = tech_remove,
5355 .set_tethering = tech_set_tethering,
5356 .set_regdom = tech_set_regdom,
5359 static int wifi_init(void)
5363 err = connman_network_driver_register(&network_driver);
5367 err = g_supplicant_register(&callbacks);
5369 connman_network_driver_unregister(&network_driver);
5373 err = connman_technology_driver_register(&tech_driver);
5375 g_supplicant_unregister(&callbacks);
5376 connman_network_driver_unregister(&network_driver);
5383 static void wifi_exit(void)
5387 connman_technology_driver_unregister(&tech_driver);
5389 g_supplicant_unregister(&callbacks);
5391 connman_network_driver_unregister(&network_driver);
5394 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5395 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)