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);
3636 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3637 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3638 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3642 static bool is_idle(struct wifi_data *wifi)
3644 DBG("state %d", wifi->state);
3646 switch (wifi->state) {
3647 case G_SUPPLICANT_STATE_UNKNOWN:
3648 case G_SUPPLICANT_STATE_DISABLED:
3649 case G_SUPPLICANT_STATE_DISCONNECTED:
3650 case G_SUPPLICANT_STATE_INACTIVE:
3651 case G_SUPPLICANT_STATE_SCANNING:
3654 case G_SUPPLICANT_STATE_AUTHENTICATING:
3655 case G_SUPPLICANT_STATE_ASSOCIATING:
3656 case G_SUPPLICANT_STATE_ASSOCIATED:
3657 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3658 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3659 case G_SUPPLICANT_STATE_COMPLETED:
3666 static bool is_idle_wps(GSupplicantInterface *interface,
3667 struct wifi_data *wifi)
3669 /* First, let's check if WPS processing did not went wrong */
3670 if (g_supplicant_interface_get_wps_state(interface) ==
3671 G_SUPPLICANT_WPS_STATE_FAIL)
3674 /* Unlike normal connection, being associated while processing wps
3675 * actually means that we are idling. */
3676 switch (wifi->state) {
3677 case G_SUPPLICANT_STATE_UNKNOWN:
3678 case G_SUPPLICANT_STATE_DISABLED:
3679 case G_SUPPLICANT_STATE_DISCONNECTED:
3680 case G_SUPPLICANT_STATE_INACTIVE:
3681 case G_SUPPLICANT_STATE_SCANNING:
3682 case G_SUPPLICANT_STATE_ASSOCIATED:
3684 case G_SUPPLICANT_STATE_AUTHENTICATING:
3685 case G_SUPPLICANT_STATE_ASSOCIATING:
3686 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3687 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3688 case G_SUPPLICANT_STATE_COMPLETED:
3695 static bool handle_wps_completion(GSupplicantInterface *interface,
3696 struct connman_network *network,
3697 struct connman_device *device,
3698 struct wifi_data *wifi)
3702 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3704 const unsigned char *ssid, *wps_ssid;
3705 unsigned int ssid_len, wps_ssid_len;
3706 const char *wps_key;
3708 /* Checking if we got associated with requested
3710 ssid = connman_network_get_blob(network, "WiFi.SSID",
3713 wps_ssid = g_supplicant_interface_get_wps_ssid(
3714 interface, &wps_ssid_len);
3716 if (!wps_ssid || wps_ssid_len != ssid_len ||
3717 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3718 connman_network_set_associating(network, false);
3719 #if defined TIZEN_EXT
3720 g_supplicant_interface_disconnect(wifi->interface,
3721 disconnect_callback, wifi->network);
3723 connman_network_set_bool(network, "WiFi.UseWPS", false);
3724 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3726 g_supplicant_interface_disconnect(wifi->interface,
3727 disconnect_callback, wifi);
3732 wps_key = g_supplicant_interface_get_wps_key(interface);
3733 #if defined TIZEN_EXT
3734 /* Check the passphrase and encrypt it
3737 gchar *passphrase = g_strdup(wps_key);
3739 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3741 if (check_passphrase_ext(network, passphrase) < 0) {
3742 DBG("[WPS] Invalid passphrase");
3747 ret = send_encryption_request(passphrase, network);
3752 DBG("[WPS] Encryption request succeeded");
3754 DBG("[WPS] Encryption request failed %d", ret);
3757 connman_network_set_string(network, "WiFi.Passphrase",
3760 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3767 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3768 struct wifi_data *wifi)
3770 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3771 #if defined TIZEN_EXT
3772 wifi->assoc_code > 0 &&
3774 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3776 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3777 wifi->load_shaping_retries ++;
3780 wifi->load_shaping_retries = 0;
3784 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3785 struct connman_network *network,
3786 struct wifi_data *wifi)
3788 #if defined TIZEN_EXT
3789 const char *security;
3790 struct connman_service *service;
3792 if (wifi->connected)
3795 security = connman_network_get_string(network, "WiFi.Security");
3797 if (security && g_str_equal(security, "ieee8021x") == true &&
3798 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3800 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3805 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3808 struct connman_service *service;
3810 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3813 if (wifi->connected)
3817 service = connman_service_lookup_from_network(network);
3823 if (connman_service_get_favorite(service)) {
3824 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3829 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3834 #if defined TIZEN_EXT
3835 static bool handle_wifi_assoc_retry(struct connman_network *network,
3836 struct wifi_data *wifi)
3838 const char *security;
3840 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3841 connman_network_get_connecting(network) != true) {
3842 wifi->assoc_retry_count = 0;
3846 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3847 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3848 wifi->assoc_retry_count = 0;
3852 security = connman_network_get_string(network, "WiFi.Security");
3853 if (security && g_str_equal(security, "ieee8021x") == true &&
3854 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3855 wifi->assoc_retry_count = 0;
3859 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3860 wifi->assoc_retry_count = 0;
3862 /* Honestly it's not an invalid-key error,
3863 * however QA team recommends that the invalid-key error
3864 * might be better to display for user experience.
3866 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3875 static void interface_state(GSupplicantInterface *interface)
3877 struct connman_network *network;
3878 struct connman_device *device;
3879 struct wifi_data *wifi;
3880 GSupplicantState state = g_supplicant_interface_get_state(interface);
3884 wifi = g_supplicant_interface_get_data(interface);
3886 DBG("wifi %p interface state %d", wifi, state);
3891 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3892 if (wifi->tethering_param) {
3893 g_free(wifi->tethering_param->ssid);
3894 g_free(wifi->tethering_param);
3895 wifi->tethering_param = NULL;
3899 device = wifi->device;
3903 if (g_supplicant_interface_get_ready(interface) &&
3904 !wifi->interface_ready) {
3905 wifi->interface_ready = true;
3906 finalize_interface_creation(wifi);
3909 network = wifi->network;
3914 case G_SUPPLICANT_STATE_SCANNING:
3915 if (wifi->connected)
3916 connman_network_set_connected(network, false);
3920 case G_SUPPLICANT_STATE_AUTHENTICATING:
3921 case G_SUPPLICANT_STATE_ASSOCIATING:
3922 #if defined TIZEN_EXT
3923 reset_autoscan(device);
3925 stop_autoscan(device);
3928 if (!wifi->connected)
3929 connman_network_set_associating(network, true);
3933 case G_SUPPLICANT_STATE_COMPLETED:
3934 #if defined TIZEN_EXT
3935 /* though it should be already reset: */
3936 reset_autoscan(device);
3938 wifi->assoc_retry_count = 0;
3940 wifi->scan_pending_network = NULL;
3942 /* should be cleared scanning flag */
3943 bool scanning = connman_device_get_scanning(device);
3945 connman_device_set_scanning(device,
3946 CONNMAN_SERVICE_TYPE_WIFI, false);
3947 connman_device_unref(device);
3950 if (!wifi->automaxspeed_timeout) {
3951 DBG("Going to start signalpoll timer!!");
3952 int ret = network_signalpoll(wifi);
3954 DBG("Fail to get max speed !!");
3956 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
3959 /* though it should be already stopped: */
3960 stop_autoscan(device);
3963 if (!handle_wps_completion(interface, network, device, wifi))
3966 connman_network_set_connected(network, true);
3968 wifi->disconnect_code = 0;
3969 wifi->assoc_code = 0;
3970 wifi->load_shaping_retries = 0;
3973 case G_SUPPLICANT_STATE_DISCONNECTED:
3974 #if defined TIZEN_EXT
3975 connman_network_set_maxspeed(network, 0);
3977 if (wifi->automaxspeed_timeout != 0) {
3978 g_source_remove(wifi->automaxspeed_timeout);
3979 wifi->automaxspeed_timeout = 0;
3980 DBG("Remove signalpoll timer!!");
3984 * If we're in one of the idle modes, we have
3985 * not started association yet and thus setting
3986 * those ones to FALSE could cancel an association
3989 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3991 if (is_idle_wps(interface, wifi))
3997 #if defined TIZEN_EXT
3998 if (handle_assoc_status_code(interface, wifi)) {
3999 network_connect(network);
4003 if (handle_assoc_status_code(interface, wifi))
4007 /* If previous state was 4way-handshake, then
4008 * it's either: psk was incorrect and thus we retry
4009 * or if we reach the maximum retries we declare the
4011 if (handle_4way_handshake_failure(interface,
4015 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4016 switch (wifi->disconnect_code) {
4017 case 1: /* Unspecified reason */
4018 /* Let's assume it's because we got blocked */
4020 case 6: /* Class 2 frame received from nonauthenticated STA */
4021 connman_network_set_error(network,
4022 CONNMAN_NETWORK_ERROR_BLOCKED);
4029 #if defined TIZEN_EXT
4030 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4031 * Retry association until its retry count is expired */
4032 if (handle_wifi_assoc_retry(network, wifi) == true) {
4033 throw_wifi_scan(wifi->device, scan_callback);
4034 wifi->scan_pending_network = wifi->network;
4038 if(wifi->disconnect_code > 0){
4039 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4040 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4044 connman_network_set_connected(network, false);
4045 connman_network_set_associating(network, false);
4046 wifi->disconnecting = false;
4048 start_autoscan(device);
4052 case G_SUPPLICANT_STATE_INACTIVE:
4053 #if defined TIZEN_EXT
4054 if (handle_wps_completion(interface, network, device, wifi) == false)
4057 connman_network_set_associating(network, false);
4058 start_autoscan(device);
4062 case G_SUPPLICANT_STATE_UNKNOWN:
4063 case G_SUPPLICANT_STATE_DISABLED:
4064 case G_SUPPLICANT_STATE_ASSOCIATED:
4065 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4066 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4070 old_connected = wifi->connected;
4071 wifi->state = state;
4073 /* Saving wpa_s state policy:
4074 * If connected and if the state changes are roaming related:
4075 * --> We stay connected
4077 * --> We are connected
4079 * --> We are not connected
4082 case G_SUPPLICANT_STATE_AUTHENTICATING:
4083 case G_SUPPLICANT_STATE_ASSOCIATING:
4084 case G_SUPPLICANT_STATE_ASSOCIATED:
4085 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4086 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4087 if (wifi->connected)
4088 connman_warn("Probably roaming right now!"
4089 " Staying connected...");
4091 case G_SUPPLICANT_STATE_SCANNING:
4092 wifi->connected = false;
4095 start_autoscan(device);
4097 case G_SUPPLICANT_STATE_COMPLETED:
4098 wifi->connected = true;
4101 wifi->connected = false;
4108 static void interface_removed(GSupplicantInterface *interface)
4110 const char *ifname = g_supplicant_interface_get_ifname(interface);
4111 struct wifi_data *wifi;
4113 DBG("ifname %s", ifname);
4115 wifi = g_supplicant_interface_get_data(interface);
4117 #if defined TIZEN_EXT_WIFI_MESH
4118 if (wifi && wifi->mesh_interface) {
4119 DBG("Notify mesh interface remove");
4120 connman_mesh_notify_interface_remove(true);
4121 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4122 g_free(mesh_info->parent_ifname);
4123 g_free(mesh_info->ifname);
4124 g_free(mesh_info->identifier);
4126 wifi->mesh_interface = false;
4127 wifi->mesh_info = NULL;
4133 wifi->interface = NULL;
4135 if (wifi && wifi->tethering)
4138 if (!wifi || !wifi->device) {
4139 DBG("wifi interface already removed");
4143 connman_device_set_powered(wifi->device, false);
4145 check_p2p_technology();
4146 #if defined TIZEN_EXT_WIFI_MESH
4147 check_mesh_technology();
4151 static void set_device_type(const char *type, char dev_type[17])
4153 const char *oui = "0050F204";
4154 const char *category = "0001";
4155 const char *sub_category = "0000";
4157 if (!g_strcmp0(type, "handset")) {
4159 sub_category = "0005";
4160 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4161 sub_category = "0001";
4162 else if (!g_strcmp0(type, "server"))
4163 sub_category = "0002";
4164 else if (!g_strcmp0(type, "laptop"))
4165 sub_category = "0005";
4166 else if (!g_strcmp0(type, "desktop"))
4167 sub_category = "0006";
4168 else if (!g_strcmp0(type, "tablet"))
4169 sub_category = "0009";
4170 else if (!g_strcmp0(type, "watch"))
4173 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4176 static void p2p_support(GSupplicantInterface *interface)
4178 char dev_type[17] = {};
4179 const char *hostname;
4186 if (!g_supplicant_interface_has_p2p(interface))
4189 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4190 DBG("Could not register P2P technology driver");
4194 hostname = connman_utsname_get_hostname();
4196 hostname = "ConnMan";
4198 set_device_type(connman_machine_get_type(), dev_type);
4199 g_supplicant_interface_set_p2p_device_config(interface,
4200 hostname, dev_type);
4201 connman_peer_driver_register(&peer_driver);
4204 static void scan_started(GSupplicantInterface *interface)
4209 static void scan_finished(GSupplicantInterface *interface)
4211 #if defined TIZEN_EXT
4212 struct wifi_data *wifi;
4213 bool is_associating = false;
4214 static bool is_scanning = true;
4219 #if defined TIZEN_EXT
4220 wifi = g_supplicant_interface_get_data(interface);
4221 if (wifi && wifi->scan_pending_network) {
4222 network_connect(wifi->scan_pending_network);
4223 wifi->scan_pending_network = NULL;
4226 //service state - associating
4227 if(!wifi || !wifi->network)
4230 is_associating = connman_network_get_associating(wifi->network);
4231 if(is_associating && is_scanning){
4232 is_scanning = false;
4233 DBG("send scan for connecting");
4234 throw_wifi_scan(wifi->device, scan_callback);
4245 static void ap_create_fail(GSupplicantInterface *interface)
4247 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4250 if ((wifi->tethering) && (wifi->tethering_param)) {
4251 DBG("%s create AP fail \n",
4252 g_supplicant_interface_get_ifname(wifi->interface));
4254 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4255 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4256 wifi->tethering = false;
4258 ret = tech_set_tethering(wifi->tethering_param->technology,
4259 wifi->tethering_param->ssid->ssid,
4260 wifi->tethering_param->ssid->passphrase,
4261 wifi->bridge, true);
4263 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4264 connman_technology_tethering_notify(wifi_technology,false);
4267 g_free(wifi->tethering_param->ssid);
4268 g_free(wifi->tethering_param);
4269 wifi->tethering_param = NULL;
4275 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4277 unsigned char strength;
4279 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4281 #if !defined TIZEN_EXT
4288 #if defined TIZEN_EXT_WIFI_MESH
4289 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4291 GSupplicantInterface *interface;
4292 struct wifi_data *wifi;
4293 const char *name, *security;
4294 struct connman_mesh *connman_mesh;
4295 struct wifi_mesh_info *mesh_info;
4296 const unsigned char *bssid;
4297 const char *identifier;
4302 interface = g_supplicant_network_get_interface(supplicant_network);
4303 wifi = g_supplicant_interface_get_data(interface);
4304 if (!wifi || !wifi->mesh_interface) {
4305 DBG("Virtual Mesh interface not created");
4309 bssid = g_supplicant_network_get_bssid(supplicant_network);
4310 address = g_malloc0(19);
4311 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4312 bssid[2], bssid[3], bssid[4], bssid[5]);
4314 identifier = g_supplicant_network_get_identifier(supplicant_network);
4315 name = g_supplicant_network_get_name(supplicant_network);
4316 security = g_supplicant_network_get_security(supplicant_network);
4317 frequency = g_supplicant_network_get_frequency(supplicant_network);
4319 mesh_info = wifi->mesh_info;
4320 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4324 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4326 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4327 connman_mesh_set_name(connman_mesh, name);
4328 connman_mesh_set_security(connman_mesh, security);
4329 connman_mesh_set_frequency(connman_mesh, frequency);
4330 connman_mesh_set_address(connman_mesh, address);
4331 connman_mesh_set_index(connman_mesh, mesh_info->index);
4332 connman_mesh_set_strength(connman_mesh,
4333 calculate_strength(supplicant_network));
4334 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4336 ret = connman_mesh_register(connman_mesh);
4337 if (ret == -EALREADY)
4338 DBG("Mesh Peer is already registered");
4344 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4346 GSupplicantInterface *interface;
4347 struct wifi_data *wifi;
4348 struct connman_mesh *connman_mesh;
4349 struct wifi_mesh_info *mesh_info;
4350 const char *identifier;
4352 interface = g_supplicant_network_get_interface(supplicant_network);
4353 wifi = g_supplicant_interface_get_data(interface);
4354 if (!wifi || !wifi->mesh_interface) {
4355 DBG("Virtual Mesh interface not created");
4359 identifier = g_supplicant_network_get_identifier(supplicant_network);
4361 DBG("Failed to get Mesh Peer identifier");
4365 mesh_info = wifi->mesh_info;
4366 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4368 /* Do not unregister connected mesh peer */
4369 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4370 DBG("Mesh Peer %s is connected", identifier);
4373 DBG("Mesh Peer identifier %s removed", identifier);
4374 connman_mesh_unregister(connman_mesh);
4379 static void network_added(GSupplicantNetwork *supplicant_network)
4381 struct connman_network *network;
4382 GSupplicantInterface *interface;
4383 struct wifi_data *wifi;
4384 const char *name, *identifier, *security, *group, *mode;
4385 const unsigned char *ssid;
4386 unsigned int ssid_len;
4390 bool wps_advertizing;
4392 #if defined TIZEN_EXT
4393 GSList *vsie_list = NULL;
4394 const unsigned char *country_code;
4395 ieee80211_modes_e phy_mode;
4398 mode = g_supplicant_network_get_mode(supplicant_network);
4399 identifier = g_supplicant_network_get_identifier(supplicant_network);
4401 DBG("%s", identifier);
4403 if (!g_strcmp0(mode, "adhoc"))
4406 #if defined TIZEN_EXT_WIFI_MESH
4407 if (!g_strcmp0(mode, "mesh")) {
4408 mesh_peer_added(supplicant_network);
4413 interface = g_supplicant_network_get_interface(supplicant_network);
4414 wifi = g_supplicant_interface_get_data(interface);
4415 name = g_supplicant_network_get_name(supplicant_network);
4416 security = g_supplicant_network_get_security(supplicant_network);
4417 group = g_supplicant_network_get_identifier(supplicant_network);
4418 wps = g_supplicant_network_get_wps(supplicant_network);
4419 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4420 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4421 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4422 supplicant_network);
4427 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4429 network = connman_device_get_network(wifi->device, identifier);
4432 network = connman_network_create(identifier,
4433 CONNMAN_NETWORK_TYPE_WIFI);
4437 connman_network_set_index(network, wifi->index);
4439 if (connman_device_add_network(wifi->device, network) < 0) {
4440 connman_network_unref(network);
4444 wifi->networks = g_slist_prepend(wifi->networks, network);
4447 if (name && name[0] != '\0')
4448 connman_network_set_name(network, name);
4450 connman_network_set_blob(network, "WiFi.SSID",
4452 #if defined TIZEN_EXT
4453 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4455 connman_network_set_vsie_list(network, vsie_list);
4457 DBG("vsie_list is NULL");
4458 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4459 connman_network_set_countrycode(network, country_code);
4460 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4461 connman_network_set_phy_mode(network, phy_mode);
4463 connman_network_set_string(network, "WiFi.Security", security);
4464 connman_network_set_strength(network,
4465 calculate_strength(supplicant_network));
4466 connman_network_set_bool(network, "WiFi.WPS", wps);
4469 /* Is AP advertizing for WPS association?
4470 * If so, we decide to use WPS by default */
4471 if (wps_ready && wps_pbc &&
4473 #if !defined TIZEN_EXT
4474 connman_network_set_bool(network, "WiFi.UseWPS", true);
4476 DBG("wps is activating by ap but ignore it.");
4481 connman_network_set_frequency(network,
4482 g_supplicant_network_get_frequency(supplicant_network));
4483 #if defined TIZEN_EXT
4484 connman_network_set_bssid(network,
4485 g_supplicant_network_get_bssid(supplicant_network));
4486 connman_network_set_maxrate(network,
4487 g_supplicant_network_get_maxrate(supplicant_network));
4488 connman_network_set_enc_mode(network,
4489 g_supplicant_network_get_enc_mode(supplicant_network));
4490 connman_network_set_rsn_mode(network,
4491 g_supplicant_network_get_rsn_mode(supplicant_network));
4492 connman_network_set_keymgmt(network,
4493 g_supplicant_network_get_keymgmt(supplicant_network));
4494 connman_network_set_bool(network, "WiFi.HS20AP",
4495 g_supplicant_network_is_hs20AP(supplicant_network));
4496 connman_network_set_bssid_list(network,
4497 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4499 connman_network_set_available(network, true);
4500 connman_network_set_string(network, "WiFi.Mode", mode);
4502 #if defined TIZEN_EXT
4507 connman_network_set_group(network, group);
4509 #if defined TIZEN_EXT
4510 if (wifi_first_scan == true)
4511 found_with_first_scan = true;
4514 if (wifi->hidden && ssid) {
4515 #if defined TIZEN_EXT
4516 if (network_security(wifi->hidden->security) ==
4517 network_security(security) &&
4519 if (!g_strcmp0(wifi->hidden->security, security) &&
4521 wifi->hidden->ssid_len == ssid_len &&
4522 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4523 connman_network_connect_hidden(network,
4524 wifi->hidden->identity,
4525 wifi->hidden->passphrase,
4526 wifi->hidden->user_data);
4527 wifi->hidden->user_data = NULL;
4528 hidden_free(wifi->hidden);
4529 wifi->hidden = NULL;
4534 static void network_removed(GSupplicantNetwork *network)
4536 GSupplicantInterface *interface;
4537 struct wifi_data *wifi;
4538 const char *name, *identifier;
4539 struct connman_network *connman_network;
4541 #if defined TIZEN_EXT_WIFI_MESH
4543 mode = g_supplicant_network_get_mode(network);
4544 if (!g_strcmp0(mode, "mesh")) {
4545 mesh_peer_removed(network);
4550 interface = g_supplicant_network_get_interface(network);
4551 wifi = g_supplicant_interface_get_data(interface);
4552 identifier = g_supplicant_network_get_identifier(network);
4553 name = g_supplicant_network_get_name(network);
4555 DBG("name %s", name);
4560 connman_network = connman_device_get_network(wifi->device, identifier);
4561 if (!connman_network)
4564 #if defined TIZEN_EXT
4565 if (connman_network == wifi->scan_pending_network)
4566 wifi->scan_pending_network = NULL;
4568 if (connman_network == wifi->pending_network)
4569 wifi->pending_network = NULL;
4571 if(connman_network_get_connecting(connman_network) == true){
4572 connman_network_set_connected(connman_network, false);
4576 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4578 connman_device_remove_network(wifi->device, connman_network);
4579 connman_network_unref(connman_network);
4582 static void network_changed(GSupplicantNetwork *network, const char *property)
4584 GSupplicantInterface *interface;
4585 struct wifi_data *wifi;
4586 const char *name, *identifier;
4587 struct connman_network *connman_network;
4589 #if defined TIZEN_EXT
4590 const unsigned char *bssid;
4591 unsigned int maxrate;
4594 const unsigned char *country_code;
4595 ieee80211_modes_e phy_mode;
4599 interface = g_supplicant_network_get_interface(network);
4600 wifi = g_supplicant_interface_get_data(interface);
4601 identifier = g_supplicant_network_get_identifier(network);
4602 name = g_supplicant_network_get_name(network);
4604 DBG("name %s", name);
4609 connman_network = connman_device_get_network(wifi->device, identifier);
4610 if (!connman_network)
4613 if (g_str_equal(property, "Signal")) {
4614 connman_network_set_strength(connman_network,
4615 calculate_strength(network));
4616 connman_network_update(connman_network);
4619 #if defined TIZEN_EXT
4620 bssid = g_supplicant_network_get_bssid(network);
4621 maxrate = g_supplicant_network_get_maxrate(network);
4622 frequency = g_supplicant_network_get_frequency(network);
4623 wps = g_supplicant_network_get_wps(network);
4624 phy_mode = g_supplicant_network_get_phy_mode(network);
4626 connman_network_set_bssid(connman_network, bssid);
4627 connman_network_set_maxrate(connman_network, maxrate);
4628 connman_network_set_frequency(connman_network, frequency);
4629 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4630 country_code = g_supplicant_network_get_countrycode(network);
4631 connman_network_set_countrycode(connman_network, country_code);
4632 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4633 connman_network_set_bssid_list(connman_network, bssid_list);
4634 connman_network_set_phy_mode(connman_network, phy_mode);
4636 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4637 connman_network_get_associating(connman_network))
4638 network_connect(connman_network);
4642 static void network_associated(GSupplicantNetwork *network)
4644 GSupplicantInterface *interface;
4645 struct wifi_data *wifi;
4646 struct connman_network *connman_network;
4647 const char *identifier;
4651 interface = g_supplicant_network_get_interface(network);
4655 wifi = g_supplicant_interface_get_data(interface);
4659 identifier = g_supplicant_network_get_identifier(network);
4661 connman_network = connman_device_get_network(wifi->device, identifier);
4662 if (!connman_network)
4665 if (wifi->network) {
4666 if (wifi->network == connman_network)
4670 * This should never happen, we got associated with
4671 * a network different than the one we were expecting.
4673 DBG("Associated to %p while expecting %p",
4674 connman_network, wifi->network);
4676 connman_network_set_associating(wifi->network, false);
4679 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4681 wifi->network = connman_network_ref(connman_network);
4685 * Interface state changes callback (interface_state) is always
4686 * called before network_associated callback thus we need to call
4687 * interface_state again in order to process the new state now that
4688 * we have the network properly set.
4690 interface_state(interface);
4693 static void apply_peer_services(GSupplicantPeer *peer,
4694 struct connman_peer *connman_peer)
4696 const unsigned char *data;
4701 connman_peer_reset_services(connman_peer);
4703 data = g_supplicant_peer_get_widi_ies(peer, &length);
4705 connman_peer_add_service(connman_peer,
4706 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4710 static void add_station(const char *mac)
4712 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4716 static void remove_station(const char *mac)
4718 connman_technology_tethering_remove_station(mac);
4721 static void peer_found(GSupplicantPeer *peer)
4723 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4724 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4725 struct connman_peer *connman_peer;
4726 const char *identifier, *name;
4728 #if defined TIZEN_EXT
4732 identifier = g_supplicant_peer_get_identifier(peer);
4733 name = g_supplicant_peer_get_name(peer);
4735 DBG("ident: %s", identifier);
4737 connman_peer = connman_peer_get(wifi->device, identifier);
4741 connman_peer = connman_peer_create(identifier);
4742 connman_peer_set_name(connman_peer, name);
4743 connman_peer_set_device(connman_peer, wifi->device);
4744 apply_peer_services(peer, connman_peer);
4746 ret = connman_peer_register(connman_peer);
4747 if (ret < 0 && ret != -EALREADY)
4748 connman_peer_unref(connman_peer);
4750 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4753 static void peer_lost(GSupplicantPeer *peer)
4755 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4756 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4757 struct connman_peer *connman_peer;
4758 const char *identifier;
4763 identifier = g_supplicant_peer_get_identifier(peer);
4765 DBG("ident: %s", identifier);
4767 connman_peer = connman_peer_get(wifi->device, identifier);
4769 if (wifi->p2p_connecting &&
4770 wifi->pending_peer == connman_peer) {
4771 peer_connect_timeout(wifi);
4773 connman_peer_unregister(connman_peer);
4774 connman_peer_unref(connman_peer);
4777 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4780 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4782 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4783 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4784 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4785 struct connman_peer *connman_peer;
4786 const char *identifier;
4788 identifier = g_supplicant_peer_get_identifier(peer);
4790 DBG("ident: %s", identifier);
4795 connman_peer = connman_peer_get(wifi->device, identifier);
4800 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4801 apply_peer_services(peer, connman_peer);
4802 connman_peer_services_changed(connman_peer);
4804 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4805 if (!g_supplicant_peer_is_in_a_group(peer))
4806 p_state = CONNMAN_PEER_STATE_IDLE;
4808 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4810 case G_SUPPLICANT_PEER_GROUP_STARTED:
4812 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4813 p_state = CONNMAN_PEER_STATE_IDLE;
4815 case G_SUPPLICANT_PEER_GROUP_JOINED:
4816 connman_peer_set_iface_address(connman_peer,
4817 g_supplicant_peer_get_iface_address(peer));
4819 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4820 p_state = CONNMAN_PEER_STATE_IDLE;
4822 case G_SUPPLICANT_PEER_GROUP_FAILED:
4823 if (g_supplicant_peer_has_requested_connection(peer))
4824 p_state = CONNMAN_PEER_STATE_IDLE;
4826 p_state = CONNMAN_PEER_STATE_FAILURE;
4830 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4831 p_state == CONNMAN_PEER_STATE_FAILURE) {
4832 if (wifi->p2p_connecting
4833 && connman_peer == wifi->pending_peer)
4834 peer_cancel_timeout(wifi);
4836 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4839 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4842 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4843 GSupplicantInterface *g_iface;
4844 struct wifi_data *g_wifi;
4846 g_iface = g_supplicant_peer_get_group_interface(peer);
4850 g_wifi = g_supplicant_interface_get_data(g_iface);
4854 connman_peer_set_as_master(connman_peer,
4855 !g_supplicant_peer_is_client(peer));
4856 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4859 * If wpa_supplicant didn't create a dedicated p2p-group
4860 * interface then mark this interface as p2p_device to avoid
4861 * scan and auto-scan are launched on it while P2P is connected.
4863 if (!g_list_find(p2p_iface_list, g_wifi))
4864 wifi->p2p_device = true;
4867 connman_peer_set_state(connman_peer, p_state);
4870 static void peer_request(GSupplicantPeer *peer)
4872 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4873 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4874 struct connman_peer *connman_peer;
4875 const char *identifier;
4877 #if defined TIZEN_EXT
4882 identifier = g_supplicant_peer_get_identifier(peer);
4884 DBG("ident: %s", identifier);
4886 connman_peer = connman_peer_get(wifi->device, identifier);
4890 connman_peer_request_connection(connman_peer);
4893 #if defined TIZEN_EXT
4894 static void system_power_off(void)
4897 struct wifi_data *wifi;
4898 struct connman_service *service;
4899 struct connman_ipconfig *ipconfig_ipv4;
4901 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4902 for (list = iface_list; list; list = list->next) {
4905 if (wifi->network != NULL) {
4906 service = connman_service_lookup_from_network(wifi->network);
4907 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4908 __connman_dhcp_stop(ipconfig_ipv4);
4914 static void network_merged(GSupplicantNetwork *network)
4916 GSupplicantInterface *interface;
4917 GSupplicantState state;
4918 struct wifi_data *wifi;
4919 const char *identifier;
4920 struct connman_network *connman_network;
4924 interface = g_supplicant_network_get_interface(network);
4928 state = g_supplicant_interface_get_state(interface);
4929 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4932 wifi = g_supplicant_interface_get_data(interface);
4936 identifier = g_supplicant_network_get_identifier(network);
4938 connman_network = connman_device_get_network(wifi->device, identifier);
4939 if (!connman_network)
4942 DBG("merged identifier %s", identifier);
4944 if (wifi->connected == FALSE) {
4946 case G_SUPPLICANT_STATE_AUTHENTICATING:
4947 case G_SUPPLICANT_STATE_ASSOCIATING:
4948 case G_SUPPLICANT_STATE_ASSOCIATED:
4949 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4950 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4951 connman_network_set_associating(connman_network, TRUE);
4953 case G_SUPPLICANT_STATE_COMPLETED:
4954 connman_network_set_connected(connman_network, TRUE);
4957 DBG("Not handled the state : %d", state);
4962 ishs20AP = g_supplicant_network_is_hs20AP(network);
4965 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
4966 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
4967 connman_network_set_string(connman_network, "WiFi.EAP",
4969 connman_network_set_string(connman_network, "WiFi.Identity",
4970 g_supplicant_network_get_identity(network));
4971 connman_network_set_string(connman_network, "WiFi.Phase2",
4972 g_supplicant_network_get_phase2(network));
4977 wifi->network = connman_network;
4980 static void assoc_failed(void *user_data)
4982 struct connman_network *network = user_data;
4983 connman_network_set_associating(network, false);
4987 static void debug(const char *str)
4989 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
4990 connman_debug("%s", str);
4993 static void disconnect_reasoncode(GSupplicantInterface *interface,
4996 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4999 wifi->disconnect_code = reasoncode;
5003 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5005 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5008 wifi->assoc_code = status_code;
5012 static const GSupplicantCallbacks callbacks = {
5013 .system_ready = system_ready,
5014 .system_killed = system_killed,
5015 .interface_added = interface_added,
5016 .interface_state = interface_state,
5017 .interface_removed = interface_removed,
5018 .p2p_support = p2p_support,
5019 .scan_started = scan_started,
5020 .scan_finished = scan_finished,
5021 .ap_create_fail = ap_create_fail,
5022 .network_added = network_added,
5023 .network_removed = network_removed,
5024 .network_changed = network_changed,
5025 .network_associated = network_associated,
5026 .add_station = add_station,
5027 .remove_station = remove_station,
5028 .peer_found = peer_found,
5029 .peer_lost = peer_lost,
5030 .peer_changed = peer_changed,
5031 .peer_request = peer_request,
5032 #if defined TIZEN_EXT
5033 .system_power_off = system_power_off,
5034 .network_merged = network_merged,
5035 .assoc_failed = assoc_failed,
5038 .disconnect_reasoncode = disconnect_reasoncode,
5039 .assoc_status_code = assoc_status_code,
5040 #if defined TIZEN_EXT_WIFI_MESH
5041 .mesh_support = mesh_support,
5042 .mesh_group_started = mesh_group_started,
5043 .mesh_group_removed = mesh_group_removed,
5044 .mesh_peer_connected = mesh_peer_connected,
5045 .mesh_peer_disconnected = mesh_peer_disconnected,
5050 static int tech_probe(struct connman_technology *technology)
5052 wifi_technology = technology;
5057 static void tech_remove(struct connman_technology *technology)
5059 wifi_technology = NULL;
5062 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5063 const char *passphrase)
5065 GSupplicantSSID *ap;
5067 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5071 ap->mode = G_SUPPLICANT_MODE_MASTER;
5072 #if defined TIZEN_EXT
5073 ap->ssid = (void *) ssid;
5077 ap->ssid_len = strlen(ssid);
5081 if (!passphrase || strlen(passphrase) == 0) {
5082 ap->security = G_SUPPLICANT_SECURITY_NONE;
5083 ap->passphrase = NULL;
5085 ap->security = G_SUPPLICANT_SECURITY_PSK;
5086 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5087 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5088 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5089 ap->passphrase = passphrase;
5095 static void ap_start_callback(int result, GSupplicantInterface *interface,
5098 struct wifi_tethering_info *info = user_data;
5100 DBG("result %d index %d bridge %s",
5101 result, info->wifi->index, info->wifi->bridge);
5103 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5104 connman_inet_remove_from_bridge(info->wifi->index,
5105 info->wifi->bridge);
5107 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5108 connman_technology_tethering_notify(info->technology, false);
5109 g_free(info->wifi->tethering_param->ssid);
5110 g_free(info->wifi->tethering_param);
5111 info->wifi->tethering_param = NULL;
5115 g_free(info->ifname);
5119 static void ap_create_callback(int result,
5120 GSupplicantInterface *interface,
5123 struct wifi_tethering_info *info = user_data;
5125 DBG("result %d ifname %s", result,
5126 g_supplicant_interface_get_ifname(interface));
5128 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5129 connman_inet_remove_from_bridge(info->wifi->index,
5130 info->wifi->bridge);
5132 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5133 connman_technology_tethering_notify(info->technology, false);
5134 g_free(info->wifi->tethering_param->ssid);
5135 g_free(info->wifi->tethering_param);
5136 info->wifi->tethering_param = NULL;
5140 g_free(info->ifname);
5146 info->wifi->interface = interface;
5147 g_supplicant_interface_set_data(interface, info->wifi);
5149 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5150 connman_error("Failed to set interface ap_scan property");
5152 g_supplicant_interface_connect(interface, info->ssid,
5153 ap_start_callback, info);
5156 static void sta_remove_callback(int result,
5157 GSupplicantInterface *interface,
5160 struct wifi_tethering_info *info = user_data;
5161 const char *driver = connman_option_get_string("wifi");
5163 DBG("ifname %s result %d ", info->ifname, result);
5165 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5166 info->wifi->tethering = false;
5167 connman_technology_tethering_notify(info->technology, false);
5169 g_free(info->ifname);
5173 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5174 g_free(info->wifi->tethering_param->ssid);
5175 g_free(info->wifi->tethering_param);
5176 info->wifi->tethering_param = NULL;
5181 info->wifi->interface = NULL;
5183 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5188 static int enable_wifi_tethering(struct connman_technology *technology,
5189 const char *bridge, const char *identifier,
5190 const char *passphrase, bool available)
5193 GSupplicantInterface *interface;
5194 struct wifi_data *wifi;
5195 struct wifi_tethering_info *info;
5200 for (list = iface_list; list; list = list->next) {
5203 DBG("wifi %p network %p pending_network %p", wifi,
5204 wifi->network, wifi->pending_network);
5206 interface = wifi->interface;
5211 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5214 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5216 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5217 DBG("%s does not support AP mode (detected)", ifname);
5221 mode = g_supplicant_interface_get_mode(interface);
5222 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5223 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5224 DBG("%s does not support AP mode (capability)", ifname);
5228 if (wifi->network && available)
5231 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5235 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5236 if (!wifi->tethering_param) {
5242 info->technology = technology;
5243 info->wifi->bridge = bridge;
5244 info->ssid = ssid_ap_init(identifier, passphrase);
5248 info->ifname = g_strdup(ifname);
5252 wifi->tethering_param->technology = technology;
5253 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5254 if (!wifi->tethering_param->ssid)
5257 info->wifi->tethering = true;
5258 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5260 berr = connman_technology_tethering_notify(technology, true);
5264 err = g_supplicant_interface_remove(interface,
5265 sta_remove_callback,
5268 DBG("tethering wifi %p ifname %s", wifi, ifname);
5273 g_free(info->ifname);
5276 g_free(wifi->tethering_param);
5277 wifi->tethering_param = NULL;
5280 * Remove bridge if it was correctly created but remove
5281 * operation failed. Instead, if bridge creation failed then
5282 * break out and do not try again on another interface,
5283 * bridge set-up does not depend on it.
5286 connman_technology_tethering_notify(technology, false);
5294 static int tech_set_tethering(struct connman_technology *technology,
5295 const char *identifier, const char *passphrase,
5296 const char *bridge, bool enabled)
5299 struct wifi_data *wifi;
5305 for (list = iface_list; list; list = list->next) {
5308 if (wifi->tethering) {
5309 wifi->tethering = false;
5311 connman_inet_remove_from_bridge(wifi->index,
5313 wifi->bridged = false;
5317 connman_technology_tethering_notify(technology, false);
5322 DBG("trying tethering for available devices");
5323 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5327 DBG("trying tethering for any device");
5328 err = enable_wifi_tethering(technology, bridge, identifier,
5335 static void regdom_callback(int result, const char *alpha2, void *user_data)
5339 if (!wifi_technology)
5345 connman_technology_regdom_notify(wifi_technology, alpha2);
5348 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5350 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5353 static struct connman_technology_driver tech_driver = {
5355 .type = CONNMAN_SERVICE_TYPE_WIFI,
5356 .probe = tech_probe,
5357 .remove = tech_remove,
5358 .set_tethering = tech_set_tethering,
5359 .set_regdom = tech_set_regdom,
5362 static int wifi_init(void)
5366 err = connman_network_driver_register(&network_driver);
5370 err = g_supplicant_register(&callbacks);
5372 connman_network_driver_unregister(&network_driver);
5376 err = connman_technology_driver_register(&tech_driver);
5378 g_supplicant_unregister(&callbacks);
5379 connman_network_driver_unregister(&network_driver);
5386 static void wifi_exit(void)
5390 connman_technology_driver_unregister(&tech_driver);
5392 g_supplicant_unregister(&callbacks);
5394 connman_network_driver_unregister(&network_driver);
5397 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5398 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)