5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <linux/if_arp.h>
34 #include <linux/wireless.h>
35 #include <net/ethernet.h>
38 #define IFF_LOWER_UP 0x10000
41 #include <dbus/dbus.h>
44 #define CONNMAN_API_SUBJECT_TO_CHANGE
45 #include <connman/plugin.h>
46 #include <connman/inet.h>
47 #include <connman/device.h>
48 #include <connman/rtnl.h>
49 #include <connman/technology.h>
50 #include <connman/service.h>
51 #include <connman/peer.h>
52 #include <connman/log.h>
53 #include <connman/option.h>
54 #include <connman/storage.h>
55 #include <include/setting.h>
56 #include <connman/provision.h>
57 #include <connman/utsname.h>
58 #include <connman/machine.h>
60 #include <gsupplicant/gsupplicant.h>
62 #define CLEANUP_TIMEOUT 8 /* in seconds */
63 #define INACTIVE_TIMEOUT 12 /* in seconds */
64 #define FAVORITE_MAXIMUM_RETRIES 2
66 #define BGSCAN_DEFAULT "simple:30:-45:300"
67 #define AUTOSCAN_DEFAULT "exponential:3:300"
69 #define P2P_FIND_TIMEOUT 30
70 #define P2P_CONNECTION_TIMEOUT 100
71 #define P2P_LISTEN_PERIOD 500
72 #define P2P_LISTEN_INTERVAL 2000
74 #define ASSOC_STATUS_NO_CLIENT 17
76 #define LOAD_SHAPING_MAX_RETRIES 7
78 #define LOAD_SHAPING_MAX_RETRIES 3
82 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
85 static struct connman_technology *wifi_technology = NULL;
86 static struct connman_technology *p2p_technology = NULL;
88 enum wifi_ap_capability{
90 WIFI_AP_SUPPORTED = 1,
91 WIFI_AP_NOT_SUPPORTED = 2,
94 struct hidden_params {
96 unsigned int ssid_len;
98 char *anonymous_identity;
100 char *altsubject_match;
101 char *domain_suffix_match;
105 GSupplicantScanParams *scan_params;
110 * Used for autoscan "emulation".
111 * Should be removed when wpa_s autoscan support will be by default.
113 struct autoscan_params {
117 unsigned int timeout;
120 struct wifi_tethering_info {
121 struct wifi_data *wifi;
122 struct connman_technology *technology;
124 GSupplicantSSID *ssid;
129 struct connman_device *device;
130 struct connman_network *network;
131 struct connman_network *pending_network;
133 GSupplicantInterface *interface;
134 GSupplicantState state;
138 enum wifi_ap_capability ap_supported;
140 bool interface_ready;
146 int load_shaping_retries;
147 struct hidden_params *hidden;
148 bool postpone_hidden;
149 struct wifi_tethering_info *tethering_param;
151 * autoscan "emulation".
153 struct autoscan_params *autoscan;
155 GSupplicantScanParams *scan_params;
156 unsigned int p2p_find_timeout;
157 unsigned int p2p_connection_timeout;
158 struct connman_peer *pending_peer;
163 #if defined TIZEN_EXT
164 int assoc_retry_count;
165 struct connman_network *scan_pending_network;
166 bool allow_full_scan;
167 unsigned int automaxspeed_timeout;
171 #if defined TIZEN_EXT_WIFI_MESH
173 struct wifi_mesh_info *mesh_info;
177 #if defined TIZEN_EXT
181 #define TIZEN_ASSOC_RETRY_COUNT 4
183 static gboolean wifi_first_scan = false;
184 static gboolean found_with_first_scan = false;
185 static gboolean is_wifi_notifier_registered = false;
186 static GHashTable *failed_bssids = NULL;
187 static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
191 static GList *iface_list = NULL;
193 static GList *pending_wifi_device = NULL;
194 static GList *p2p_iface_list = NULL;
195 bool wfd_service_registered = false;
197 static void start_autoscan(struct connman_device *device);
199 static int tech_set_tethering(struct connman_technology *technology,
200 const char *identifier, const char *passphrase,
201 const char *bridge, bool enabled);
203 #if defined TIZEN_EXT
204 #define NETCONFIG_SERVICE "net.netconfig"
205 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
206 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
208 struct enc_method_call_data {
209 DBusConnection *connection;
210 struct connman_network *network;
213 static struct enc_method_call_data encrypt_request_data;
215 static void encryption_request_reply(DBusPendingCall *call,
220 DBusMessageIter args;
222 struct connman_service *service;
223 gchar* encrypted_value = NULL;
224 struct connman_network *network = encrypt_request_data.network;
228 reply = dbus_pending_call_steal_reply(call);
230 dbus_error_init(&error);
231 if (dbus_set_error_from_message(&error, reply)) {
232 DBG("send_encryption_request() %s %s", error.name, error.message);
233 dbus_error_free(&error);
237 if (dbus_message_iter_init(reply, &args) == FALSE)
240 dbus_message_iter_get_basic(&args, &out_data);
242 encrypted_value = g_strdup((const gchar *)out_data);
243 service = connman_service_lookup_from_network(network);
246 DBG("encryption result: no service");
250 if (connman_service_get_favorite(service)) {
251 __connman_service_set_passphrase(service, encrypted_value);
252 __connman_service_save(service);
254 connman_network_set_string(network, "WiFi.Passphrase",
257 DBG("encryption result: succeeded");
260 dbus_message_unref(reply);
261 dbus_pending_call_unref(call);
262 dbus_connection_unref(encrypt_request_data.connection);
263 g_free(encrypted_value);
265 encrypt_request_data.connection = NULL;
266 encrypt_request_data.network = NULL;
269 static int send_encryption_request(const char *passphrase,
270 struct connman_network *network)
272 DBusConnection *connection = NULL;
273 DBusMessage *msg = NULL;
274 DBusPendingCall *call;
277 DBG("Invalid parameter");
281 connection = connman_dbus_get_connection();
283 DBG("dbus connection does not exist");
287 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
288 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
290 dbus_connection_unref(connection);
294 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
297 if (!dbus_connection_send_with_reply(connection, msg,
298 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
299 dbus_message_unref(msg);
300 dbus_connection_unref(connection);
305 dbus_message_unref(msg);
306 dbus_connection_unref(connection);
310 encrypt_request_data.connection = connection;
311 encrypt_request_data.network = network;
313 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
314 dbus_message_unref(msg);
320 static int p2p_tech_probe(struct connman_technology *technology)
322 p2p_technology = technology;
327 static void p2p_tech_remove(struct connman_technology *technology)
329 p2p_technology = NULL;
332 static struct connman_technology_driver p2p_tech_driver = {
334 .type = CONNMAN_SERVICE_TYPE_P2P,
335 .probe = p2p_tech_probe,
336 .remove = p2p_tech_remove,
339 static bool is_p2p_connecting(void)
343 for (list = iface_list; list; list = list->next) {
344 struct wifi_data *wifi = list->data;
346 if (wifi->p2p_connecting)
353 static void add_pending_wifi_device(struct wifi_data *wifi)
355 if (g_list_find(pending_wifi_device, wifi))
358 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
361 #if defined TIZEN_EXT_WIFI_MESH
362 struct wifi_mesh_info {
363 struct wifi_data *wifi;
364 GSupplicantInterface *interface;
365 struct connman_mesh *mesh;
372 struct mesh_change_peer_status_info {
374 enum connman_mesh_peer_status peer_status;
375 mesh_change_peer_status_cb_t callback;
379 static struct connman_technology_driver mesh_tech_driver = {
381 .type = CONNMAN_SERVICE_TYPE_MESH,
384 static void mesh_interface_create_callback(int result,
385 GSupplicantInterface *interface,
388 struct wifi_mesh_info *mesh_info = user_data;
389 struct wifi_data *wifi;
390 bool success = false;
392 DBG("result %d ifname %s, mesh_info %p", result,
393 g_supplicant_interface_get_ifname(interface),
396 if (result < 0 || !mesh_info)
399 wifi = mesh_info->wifi;
401 mesh_info->interface = interface;
402 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
403 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
404 DBG("Mesh Interface identifier %s", mesh_info->identifier);
405 wifi->mesh_interface = true;
406 wifi->mesh_info = mesh_info;
407 g_supplicant_interface_set_data(interface, wifi);
411 connman_mesh_notify_interface_create(success);
414 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
417 struct wifi_data *wifi;
418 struct wifi_mesh_info *mesh_info;
419 const char *wifi_ifname;
420 bool parent_found = false;
421 const char *driver = "nl80211";
423 for (list = iface_list; list; list = list->next) {
426 if (!g_supplicant_interface_has_mesh(wifi->interface))
429 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
433 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
440 DBG("Parent interface %s doesn't exist", parent_ifname);
444 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
448 mesh_info->wifi = wifi;
449 mesh_info->ifname = g_strdup(ifname);
450 mesh_info->parent_ifname = g_strdup(parent_ifname);
452 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
453 mesh_interface_create_callback, mesh_info);
457 static void mesh_interface_remove_callback(int result,
458 GSupplicantInterface *interface,
461 struct wifi_data *wifi = user_data;
462 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
463 bool success = false;
465 DBG("result %d mesh_info %p", result, mesh_info);
467 if (result < 0 || !mesh_info)
470 mesh_info->interface = NULL;
471 g_free(mesh_info->parent_ifname);
472 g_free(mesh_info->ifname);
473 g_free(mesh_info->identifier);
475 wifi->mesh_interface = false;
476 wifi->mesh_info = NULL;
480 connman_mesh_notify_interface_remove(success);
483 static int remove_mesh_interface(const char *ifname)
486 struct wifi_data *wifi;
487 struct wifi_mesh_info *mesh_info;
488 bool mesh_if_found = false;
491 for (list = iface_list; list; list = list->next) {
494 if (wifi->mesh_interface) {
495 mesh_if_found = true;
500 if (!mesh_if_found) {
501 DBG("Mesh interface %s doesn't exist", ifname);
505 mesh_info = wifi->mesh_info;
506 ret = g_supplicant_interface_remove(mesh_info->interface,
507 mesh_interface_remove_callback, wifi);
514 static void mesh_disconnect_callback(int result,
515 GSupplicantInterface *interface, void *user_data)
517 struct connman_mesh *mesh = user_data;
519 DBG("result %d interface %p mesh %p", result, interface, mesh);
522 static int mesh_peer_disconnect(struct connman_mesh *mesh)
525 struct wifi_data *wifi;
526 struct wifi_mesh_info *mesh_info;
527 bool mesh_if_found = false;
528 GSupplicantInterface *interface;
530 for (list = iface_list; list; list = list->next) {
533 if (wifi->mesh_interface) {
534 mesh_if_found = true;
539 if (!mesh_if_found) {
540 DBG("Mesh interface is not created");
544 mesh_info = wifi->mesh_info;
546 interface = mesh_info->interface;
547 return g_supplicant_interface_disconnect(interface,
548 mesh_disconnect_callback, mesh);
551 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
554 struct connman_mesh *mesh = user_data;
555 DBG("mesh %p result %d", mesh, result);
558 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
560 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
563 static GSupplicantSecurity mesh_network_security(const char *security)
565 if (g_str_equal(security, "none"))
566 return G_SUPPLICANT_SECURITY_NONE;
567 else if (g_str_equal(security, "sae"))
568 return G_SUPPLICANT_SECURITY_SAE;
570 return G_SUPPLICANT_SECURITY_UNKNOWN;
573 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
576 const char *security;
581 memset(ssid, 0, sizeof(*ssid));
582 ssid->mode = G_SUPPLICANT_MODE_MESH;
584 security = connman_mesh_get_security(mesh);
585 ssid->security = mesh_network_security(security);
587 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
588 ssid->passphrase = connman_mesh_get_passphrase(mesh);
590 ssid->freq = connman_mesh_get_frequency(mesh);
591 name = connman_mesh_get_name(mesh);
593 ssid->ssid_len = strlen(name);
594 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
595 memcpy(ssid->ssid, name, ssid->ssid_len);
600 static int mesh_peer_connect(struct connman_mesh *mesh)
603 struct wifi_data *wifi;
604 struct wifi_mesh_info *mesh_info;
605 bool mesh_if_found = false;
606 GSupplicantInterface *interface;
607 GSupplicantSSID *ssid;
609 for (list = iface_list; list; list = list->next) {
612 if (wifi->mesh_interface) {
613 mesh_if_found = true;
618 if (!mesh_if_found) {
619 DBG("Mesh interface is not created");
623 mesh_info = wifi->mesh_info;
625 interface = mesh_info->interface;
627 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
631 mesh_info->mesh = mesh;
633 mesh_ssid_init(ssid, mesh);
634 return g_supplicant_interface_connect(interface, ssid,
635 mesh_connect_callback, mesh);
638 static void mesh_peer_change_status_callback(int result,
639 GSupplicantInterface *interface,
642 struct mesh_change_peer_status_info *data = user_data;
644 DBG("result %d Peer Status %d", result, data->peer_status);
646 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
647 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
648 connman_mesh_remove_connected_peer(data->peer_address, 52);
652 data->callback(result, data->user_data);
654 g_free(data->peer_address);
659 static int mesh_change_peer_status(const char *peer_address,
660 enum connman_mesh_peer_status status,
661 mesh_change_peer_status_cb_t callback, void *user_data)
664 struct wifi_data *wifi;
665 struct wifi_mesh_info *mesh_info;
666 bool mesh_if_found = false;
667 GSupplicantInterface *interface;
668 struct mesh_change_peer_status_info *data;
671 for (list = iface_list; list; list = list->next) {
674 if (wifi->mesh_interface) {
675 mesh_if_found = true;
680 if (!mesh_if_found) {
681 DBG("Mesh interface is not created");
685 mesh_info = wifi->mesh_info;
687 interface = mesh_info->interface;
690 case CONNMAN_MESH_PEER_ADD:
691 method = "MeshPeerAdd";
693 case CONNMAN_MESH_PEER_REMOVE:
694 method = "MeshPeerRemove";
697 DBG("Invalid method");
701 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
703 DBG("Memory allocation failed");
707 data->peer_address = g_strdup(peer_address);
708 data->peer_status = status;
709 data->callback = callback;
710 data->user_data = user_data;
712 return g_supplicant_interface_mesh_peer_change_status(interface,
713 mesh_peer_change_status_callback, peer_address, method,
717 static struct connman_mesh_driver mesh_driver = {
718 .add_interface = add_mesh_interface,
719 .remove_interface = remove_mesh_interface,
720 .connect = mesh_peer_connect,
721 .disconnect = mesh_peer_disconnect,
722 .change_peer_status = mesh_change_peer_status,
725 static void mesh_support(GSupplicantInterface *interface)
729 if (!g_supplicant_interface_has_mesh(interface))
732 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
733 DBG("Could not register Mesh technology driver");
737 connman_mesh_driver_register(&mesh_driver);
740 static void check_mesh_technology(void)
742 bool mesh_exists = false;
745 for (list = iface_list; list; list = list->next) {
746 struct wifi_data *w = list->data;
749 g_supplicant_interface_has_mesh(w->interface))
754 connman_technology_driver_unregister(&mesh_tech_driver);
755 connman_mesh_driver_unregister(&mesh_driver);
759 static void mesh_group_started(GSupplicantInterface *interface)
761 struct wifi_data *wifi;
762 struct wifi_mesh_info *mesh_info;
763 struct connman_mesh *mesh;
764 const unsigned char *ssid;
765 unsigned int ssid_len;
768 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
769 memcpy(name, ssid, ssid_len);
770 name[ssid_len] = '\0';
771 DBG("name %s", name);
772 wifi = g_supplicant_interface_get_data(interface);
773 DBG("wifi %p", wifi);
778 mesh_info = wifi->mesh_info;
782 mesh = mesh_info->mesh;
786 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
789 static void mesh_group_removed(GSupplicantInterface *interface)
791 struct wifi_data *wifi;
792 struct wifi_mesh_info *mesh_info;
793 struct connman_mesh *mesh;
794 const unsigned char *ssid;
795 unsigned int ssid_len;
796 int disconnect_reason;
799 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
800 memcpy(name, ssid, ssid_len);
801 name[ssid_len] = '\0';
802 DBG("name %s", name);
804 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
805 DBG("Disconnect Reason %d", disconnect_reason);
807 wifi = g_supplicant_interface_get_data(interface);
808 DBG("wifi %p", wifi);
813 mesh_info = wifi->mesh_info;
817 mesh = connman_get_connected_mesh_from_name(name);
819 DBG("%s is not connected", name);
820 mesh = connman_get_connecting_mesh_from_name(name);
822 DBG("%s is not connecting", name);
827 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
828 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
831 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
833 const char *peer_address;
835 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
840 DBG("Peer %s connected", peer_address);
841 connman_mesh_add_connected_peer(peer_address);
844 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
846 const char *peer_address;
849 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
854 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
856 DBG("Peer %s disconnected with reason %d", peer_address, reason);
857 connman_mesh_remove_connected_peer(peer_address, reason);
861 static struct wifi_data *get_pending_wifi_data(const char *ifname)
865 for (list = pending_wifi_device; list; list = list->next) {
866 struct wifi_data *wifi;
867 const char *dev_name;
870 if (!wifi || !wifi->device)
873 dev_name = connman_device_get_string(wifi->device, "Interface");
874 if (!g_strcmp0(ifname, dev_name)) {
875 pending_wifi_device = g_list_delete_link(
876 pending_wifi_device, list);
884 static void remove_pending_wifi_device(struct wifi_data *wifi)
888 link = g_list_find(pending_wifi_device, wifi);
893 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
896 static void peer_cancel_timeout(struct wifi_data *wifi)
898 if (wifi->p2p_connection_timeout > 0)
899 g_source_remove(wifi->p2p_connection_timeout);
901 wifi->p2p_connection_timeout = 0;
902 wifi->p2p_connecting = false;
904 if (wifi->pending_peer) {
905 connman_peer_unref(wifi->pending_peer);
906 wifi->pending_peer = NULL;
910 static gboolean peer_connect_timeout(gpointer data)
912 struct wifi_data *wifi = data;
916 if (wifi->p2p_connecting) {
917 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
918 GSupplicantPeer *gs_peer =
919 g_supplicant_interface_peer_lookup(wifi->interface,
920 connman_peer_get_identifier(wifi->pending_peer));
922 if (g_supplicant_peer_has_requested_connection(gs_peer))
923 state = CONNMAN_PEER_STATE_IDLE;
925 connman_peer_set_state(wifi->pending_peer, state);
928 peer_cancel_timeout(wifi);
933 static void peer_connect_callback(int result, GSupplicantInterface *interface,
936 struct wifi_data *wifi = user_data;
937 struct connman_peer *peer = wifi->pending_peer;
939 DBG("peer %p - %d", peer, result);
945 peer_connect_timeout(wifi);
949 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
951 wifi->p2p_connection_timeout = g_timeout_add_seconds(
952 P2P_CONNECTION_TIMEOUT,
953 peer_connect_timeout, wifi);
956 static int peer_connect(struct connman_peer *peer,
957 enum connman_peer_wps_method wps_method,
960 struct connman_device *device = connman_peer_get_device(peer);
961 GSupplicantPeerParams *peer_params;
962 GSupplicantPeer *gs_peer;
963 struct wifi_data *wifi;
967 DBG("peer %p", peer);
972 wifi = connman_device_get_data(device);
973 if (!wifi || !wifi->interface)
976 if (wifi->p2p_connecting)
979 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
980 connman_peer_get_identifier(peer));
984 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
985 pin = g_supplicant_peer_is_wps_pin(gs_peer);
987 switch (wps_method) {
988 case CONNMAN_PEER_WPS_UNKNOWN:
989 if ((pbc && pin) || pin)
992 case CONNMAN_PEER_WPS_PBC:
997 case CONNMAN_PEER_WPS_PIN:
998 if (!pin || !wps_pin)
1003 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1007 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1009 peer_params->wps_pin = g_strdup(wps_pin);
1011 peer_params->master = connman_peer_service_is_master();
1013 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1014 peer_connect_callback, wifi);
1015 if (ret == -EINPROGRESS) {
1016 wifi->pending_peer = connman_peer_ref(peer);
1017 wifi->p2p_connecting = true;
1018 } else if (ret < 0) {
1019 g_free(peer_params->path);
1020 g_free(peer_params->wps_pin);
1021 g_free(peer_params);
1027 static int peer_disconnect(struct connman_peer *peer)
1029 struct connman_device *device = connman_peer_get_device(peer);
1030 GSupplicantPeerParams peer_params = {};
1031 GSupplicantPeer *gs_peer;
1032 struct wifi_data *wifi;
1035 DBG("peer %p", peer);
1040 wifi = connman_device_get_data(device);
1044 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1045 connman_peer_get_identifier(peer));
1049 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1051 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1053 g_free(peer_params.path);
1055 if (ret == -EINPROGRESS) {
1056 peer_cancel_timeout(wifi);
1057 wifi->p2p_device = false;
1063 struct peer_service_registration {
1064 peer_service_registration_cb_t callback;
1068 static bool is_service_wfd(const unsigned char *specs, int length)
1070 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1076 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1078 struct wifi_data *wifi = data;
1080 if (!wifi->interface ||
1081 !g_supplicant_interface_has_p2p(wifi->interface))
1084 if (!wifi->servicing) {
1085 g_supplicant_interface_p2p_listen(wifi->interface,
1086 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1092 static void register_wfd_service_cb(int result,
1093 GSupplicantInterface *iface, void *user_data)
1095 struct peer_service_registration *reg_data = user_data;
1100 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1102 if (reg_data && reg_data->callback) {
1103 reg_data->callback(result, reg_data->user_data);
1108 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1109 const unsigned char *spec,
1110 int spec_length, const unsigned char *query,
1111 int query_length, int version)
1113 GSupplicantP2PServiceParams *params;
1115 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1120 params->version = version;
1121 params->service = g_memdup(spec, spec_length);
1122 } else if (query_length > 0 && spec_length > 0) {
1123 params->query = g_memdup(query, query_length);
1124 params->query_length = query_length;
1126 params->response = g_memdup(spec, spec_length);
1127 params->response_length = spec_length;
1129 params->wfd_ies = g_memdup(spec, spec_length);
1130 params->wfd_ies_length = spec_length;
1136 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1141 g_free(params->service);
1142 g_free(params->query);
1143 g_free(params->response);
1144 g_free(params->wfd_ies);
1149 static int peer_register_wfd_service(const unsigned char *specification,
1150 int specification_length,
1151 peer_service_registration_cb_t callback,
1154 struct peer_service_registration *reg_data = NULL;
1155 static GSupplicantP2PServiceParams *params;
1160 if (wfd_service_registered)
1163 params = fill_in_peer_service_params(specification,
1164 specification_length, NULL, 0, 0);
1168 reg_data = g_try_malloc0(sizeof(*reg_data));
1174 reg_data->callback = callback;
1175 reg_data->user_data = user_data;
1177 ret = g_supplicant_set_widi_ies(params,
1178 register_wfd_service_cb, reg_data);
1179 if (ret < 0 && ret != -EINPROGRESS)
1182 wfd_service_registered = true;
1186 free_peer_service_params(params);
1192 static void register_peer_service_cb(int result,
1193 GSupplicantInterface *iface, void *user_data)
1195 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1196 struct peer_service_registration *reg_data = user_data;
1198 #if defined TIZEN_EXT
1206 apply_p2p_listen_on_iface(wifi, NULL);
1208 if (reg_data->callback)
1209 reg_data->callback(result, reg_data->user_data);
1214 static int peer_register_service(const unsigned char *specification,
1215 int specification_length,
1216 const unsigned char *query,
1217 int query_length, int version,
1218 peer_service_registration_cb_t callback,
1221 struct peer_service_registration *reg_data;
1222 GSupplicantP2PServiceParams *params;
1229 if (specification && !version && !query &&
1230 is_service_wfd(specification, specification_length)) {
1231 return peer_register_wfd_service(specification,
1232 specification_length, callback, user_data);
1235 reg_data = g_try_malloc0(sizeof(*reg_data));
1239 reg_data->callback = callback;
1240 reg_data->user_data = user_data;
1242 ret_f = -EOPNOTSUPP;
1244 for (list = iface_list; list; list = list->next) {
1245 struct wifi_data *wifi = list->data;
1246 GSupplicantInterface *iface = wifi->interface;
1248 if (!g_supplicant_interface_has_p2p(iface))
1251 params = fill_in_peer_service_params(specification,
1252 specification_length, query,
1253 query_length, version);
1260 ret_f = g_supplicant_interface_p2p_add_service(iface,
1261 register_peer_service_cb, params, reg_data);
1262 if (ret_f == 0 || ret_f == -EINPROGRESS)
1266 ret = g_supplicant_interface_p2p_add_service(iface,
1267 register_peer_service_cb, params, NULL);
1268 if (ret != 0 && ret != -EINPROGRESS)
1269 free_peer_service_params(params);
1272 if (ret_f != 0 && ret_f != -EINPROGRESS)
1278 static int peer_unregister_wfd_service(void)
1280 GSupplicantP2PServiceParams *params;
1283 if (!wfd_service_registered)
1286 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1290 wfd_service_registered = false;
1292 g_supplicant_set_widi_ies(params, NULL, NULL);
1294 for (list = iface_list; list; list = list->next) {
1295 struct wifi_data *wifi = list->data;
1297 if (!g_supplicant_interface_has_p2p(wifi->interface))
1301 if (!wifi->servicing || wifi->servicing < 0) {
1302 g_supplicant_interface_p2p_listen(wifi->interface,
1304 wifi->servicing = 0;
1311 static int peer_unregister_service(const unsigned char *specification,
1312 int specification_length,
1313 const unsigned char *query,
1314 int query_length, int version)
1316 GSupplicantP2PServiceParams *params;
1321 if (specification && !version && !query &&
1322 is_service_wfd(specification, specification_length)) {
1323 ret = peer_unregister_wfd_service();
1324 if (ret != 0 && ret != -EINPROGRESS)
1329 for (list = iface_list; list; list = list->next) {
1330 struct wifi_data *wifi = list->data;
1331 GSupplicantInterface *iface = wifi->interface;
1334 goto stop_listening;
1336 if (!g_supplicant_interface_has_p2p(iface))
1339 params = fill_in_peer_service_params(specification,
1340 specification_length, query,
1341 query_length, version);
1347 ret = g_supplicant_interface_p2p_del_service(iface, params);
1348 if (ret != 0 && ret != -EINPROGRESS)
1349 free_peer_service_params(params);
1352 if (!wifi->servicing || wifi->servicing < 0) {
1353 g_supplicant_interface_p2p_listen(iface, 0, 0);
1354 wifi->servicing = 0;
1361 static struct connman_peer_driver peer_driver = {
1362 .connect = peer_connect,
1363 .disconnect = peer_disconnect,
1364 .register_service = peer_register_service,
1365 .unregister_service = peer_unregister_service,
1368 static void handle_tethering(struct wifi_data *wifi)
1370 if (!wifi->tethering)
1379 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1381 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1384 wifi->bridged = true;
1387 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1389 struct connman_device *device = user_data;
1390 struct wifi_data *wifi = connman_device_get_data(device);
1395 DBG("index %d flags %d change %d", wifi->index, flags, change);
1397 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1399 DBG("interface up");
1401 DBG("interface down");
1404 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1405 if (flags & IFF_LOWER_UP) {
1408 handle_tethering(wifi);
1413 wifi->flags = flags;
1416 static int wifi_probe(struct connman_device *device)
1418 struct wifi_data *wifi;
1420 DBG("device %p", device);
1422 wifi = g_try_new0(struct wifi_data, 1);
1426 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1427 wifi->ap_supported = WIFI_AP_UNKNOWN;
1428 wifi->tethering_param = NULL;
1430 connman_device_set_data(device, wifi);
1431 wifi->device = connman_device_ref(device);
1433 wifi->index = connman_device_get_index(device);
1436 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1437 wifi_newlink, device);
1438 if (is_p2p_connecting())
1439 add_pending_wifi_device(wifi);
1441 iface_list = g_list_append(iface_list, wifi);
1446 static void remove_networks(struct connman_device *device,
1447 struct wifi_data *wifi)
1451 for (list = wifi->networks; list; list = list->next) {
1452 struct connman_network *network = list->data;
1454 connman_device_remove_network(device, network);
1455 connman_network_unref(network);
1458 g_slist_free(wifi->networks);
1459 wifi->networks = NULL;
1462 static void remove_peers(struct wifi_data *wifi)
1466 for (list = wifi->peers; list; list = list->next) {
1467 struct connman_peer *peer = list->data;
1469 connman_peer_unregister(peer);
1470 connman_peer_unref(peer);
1473 g_slist_free(wifi->peers);
1477 static void reset_autoscan(struct connman_device *device)
1479 struct wifi_data *wifi = connman_device_get_data(device);
1480 struct autoscan_params *autoscan;
1484 if (!wifi || !wifi->autoscan)
1487 autoscan = wifi->autoscan;
1489 if (autoscan->timeout == 0 && autoscan->interval == 0)
1492 g_source_remove(autoscan->timeout);
1494 autoscan->timeout = 0;
1495 autoscan->interval = 0;
1497 connman_device_unref(device);
1500 static void stop_autoscan(struct connman_device *device)
1502 const struct wifi_data *wifi = connman_device_get_data(device);
1504 if (!wifi || !wifi->autoscan)
1507 reset_autoscan(device);
1509 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1512 static void check_p2p_technology(void)
1514 bool p2p_exists = false;
1517 for (list = iface_list; list; list = list->next) {
1518 struct wifi_data *w = list->data;
1521 g_supplicant_interface_has_p2p(w->interface))
1526 connman_technology_driver_unregister(&p2p_tech_driver);
1527 connman_peer_driver_unregister(&peer_driver);
1531 static void wifi_remove(struct connman_device *device)
1533 struct wifi_data *wifi = connman_device_get_data(device);
1535 DBG("device %p wifi %p", device, wifi);
1540 stop_autoscan(device);
1542 if (wifi->p2p_device)
1543 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1545 iface_list = g_list_remove(iface_list, wifi);
1547 check_p2p_technology();
1548 #if defined TIZEN_EXT_WIFI_MESH
1549 check_mesh_technology();
1552 remove_pending_wifi_device(wifi);
1554 if (wifi->p2p_find_timeout) {
1555 g_source_remove(wifi->p2p_find_timeout);
1556 connman_device_unref(wifi->device);
1559 if (wifi->p2p_connection_timeout)
1560 g_source_remove(wifi->p2p_connection_timeout);
1562 #if defined TIZEN_EXT
1563 if (wifi->automaxspeed_timeout != 0) {
1564 g_source_remove(wifi->automaxspeed_timeout);
1565 wifi->automaxspeed_timeout = 0;
1569 remove_networks(device, wifi);
1572 connman_device_set_powered(device, false);
1573 connman_device_set_data(device, NULL);
1574 connman_device_unref(wifi->device);
1575 connman_rtnl_remove_watch(wifi->watch);
1577 g_supplicant_interface_set_data(wifi->interface, NULL);
1579 g_supplicant_interface_cancel(wifi->interface);
1581 if (wifi->scan_params)
1582 g_supplicant_free_scan_params(wifi->scan_params);
1584 g_free(wifi->autoscan);
1585 g_free(wifi->identifier);
1589 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1593 for (iter = list; iter; iter = g_slist_next(iter)) {
1594 struct scan_ssid *scan_ssid = iter->data;
1596 if (ssid_len == scan_ssid->ssid_len &&
1597 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1604 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1605 int freq, GSupplicantScanParams *scan_data,
1606 int driver_max_scan_ssids, char *ssid_name)
1609 struct scan_ssid *scan_ssid;
1611 if ((driver_max_scan_ssids == 0 ||
1612 driver_max_scan_ssids > scan_data->num_ssids) &&
1613 (hex_ssid || raw_ssid)) {
1615 unsigned int j = 0, hex;
1618 size_t hex_ssid_len = strlen(hex_ssid);
1620 ssid = g_try_malloc0(hex_ssid_len / 2);
1624 for (i = 0; i < hex_ssid_len; i += 2) {
1625 sscanf(hex_ssid + i, "%02x", &hex);
1634 * If we have already added hidden AP to the list,
1635 * then do not do it again. This might happen if you have
1636 * used or are using multiple wifi cards, so in that case
1637 * you might have multiple service files for same AP.
1639 if (is_duplicate(scan_data->ssids, ssid, j)) {
1645 scan_ssid = g_try_new(struct scan_ssid, 1);
1652 memcpy(scan_ssid->ssid, ssid, j);
1653 scan_ssid->ssid_len = j;
1654 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1657 scan_data->num_ssids++;
1659 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1660 scan_data->num_ssids);
1667 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1669 if (!scan_data->freqs) {
1670 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1671 if (!scan_data->freqs) {
1672 g_slist_free_full(scan_data->ssids, g_free);
1676 scan_data->num_freqs = 1;
1677 scan_data->freqs[0] = freq;
1679 bool duplicate = false;
1681 /* Don't add duplicate entries */
1682 for (i = 0; i < scan_data->num_freqs; i++) {
1683 if (scan_data->freqs[i] == freq) {
1690 scan_data->num_freqs++;
1691 scan_data->freqs = g_try_realloc(scan_data->freqs,
1692 sizeof(uint16_t) * scan_data->num_freqs);
1693 if (!scan_data->freqs) {
1694 g_slist_free_full(scan_data->ssids, g_free);
1697 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1704 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1706 struct connman_config_entry **entries;
1712 int num_ssids = 0, add_param_failed = 0;
1714 services = connman_storage_get_services();
1715 for (i = 0; services && services[i]; i++) {
1716 if (strncmp(services[i], "wifi_", 5) != 0)
1719 keyfile = connman_storage_load_service(services[i]);
1723 value = g_key_file_get_boolean(keyfile,
1724 services[i], "Hidden", NULL);
1726 g_key_file_free(keyfile);
1730 value = g_key_file_get_boolean(keyfile,
1731 services[i], "Favorite", NULL);
1733 g_key_file_free(keyfile);
1737 #if defined TIZEN_EXT
1738 value = g_key_file_get_boolean(keyfile,
1739 services[i], "AutoConnect", NULL);
1741 g_key_file_free(keyfile);
1746 ssid = g_key_file_get_string(keyfile,
1747 services[i], "SSID", NULL);
1749 name = g_key_file_get_string(keyfile, services[i], "Name",
1752 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1760 g_key_file_free(keyfile);
1764 * Check if there are any hidden AP that needs to be provisioned.
1766 entries = connman_config_get_entries("wifi");
1767 for (i = 0; entries && entries[i]; i++) {
1770 if (!entries[i]->hidden)
1773 if (!entries[i]->ssid) {
1774 ssid = entries[i]->name;
1777 ssid = entries[i]->ssid;
1778 len = entries[i]->ssid_len;
1784 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1791 connman_config_free_entries(entries);
1793 if (add_param_failed > 0)
1794 DBG("Unable to scan %d out of %d SSIDs",
1795 add_param_failed, num_ssids);
1797 g_strfreev(services);
1802 static int get_hidden_connections_params(struct wifi_data *wifi,
1803 GSupplicantScanParams *scan_params)
1805 int driver_max_ssids, i;
1806 GSupplicantScanParams *orig_params;
1809 * Scan hidden networks so that we can autoconnect to them.
1810 * We will assume 1 as a default number of ssid to scan.
1812 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1814 if (driver_max_ssids == 0)
1815 driver_max_ssids = 1;
1817 DBG("max ssids %d", driver_max_ssids);
1819 if (!wifi->scan_params) {
1820 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1821 if (!wifi->scan_params)
1824 if (get_hidden_connections(wifi->scan_params) == 0) {
1825 g_supplicant_free_scan_params(wifi->scan_params);
1826 wifi->scan_params = NULL;
1832 orig_params = wifi->scan_params;
1834 /* Let's transfer driver_max_ssids params */
1835 for (i = 0; i < driver_max_ssids; i++) {
1836 struct scan_ssid *ssid;
1838 if (!wifi->scan_params->ssids)
1841 ssid = orig_params->ssids->data;
1842 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1843 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1847 scan_params->num_ssids = i;
1848 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1850 scan_params->freqs = g_memdup(orig_params->freqs,
1851 sizeof(uint16_t) * orig_params->num_freqs);
1852 if (!scan_params->freqs)
1855 scan_params->num_freqs = orig_params->num_freqs;
1860 orig_params->num_ssids -= scan_params->num_ssids;
1862 return scan_params->num_ssids;
1865 g_slist_free_full(scan_params->ssids, g_free);
1866 g_supplicant_free_scan_params(wifi->scan_params);
1867 wifi->scan_params = NULL;
1872 static int throw_wifi_scan(struct connman_device *device,
1873 GSupplicantInterfaceCallback callback)
1875 struct wifi_data *wifi = connman_device_get_data(device);
1881 DBG("device %p %p", device, wifi->interface);
1883 if (wifi->tethering)
1885 #if defined TIZEN_EXT
1886 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1888 if (connman_device_get_scanning(device))
1892 connman_device_ref(device);
1894 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1897 connman_device_set_scanning(device,
1898 CONNMAN_SERVICE_TYPE_WIFI, true);
1900 connman_device_unref(device);
1905 static void hidden_free(struct hidden_params *hidden)
1910 if (hidden->scan_params)
1911 g_supplicant_free_scan_params(hidden->scan_params);
1912 g_free(hidden->identity);
1913 g_free(hidden->passphrase);
1914 g_free(hidden->security);
1918 #if defined TIZEN_EXT
1919 static void service_state_changed(struct connman_service *service,
1920 enum connman_service_state state);
1922 static int network_connect(struct connman_network *network);
1924 static struct connman_notifier notifier = {
1926 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1927 .service_state_changed = service_state_changed,
1930 static void service_state_changed(struct connman_service *service,
1931 enum connman_service_state state)
1933 enum connman_service_type type;
1935 type = connman_service_get_type(service);
1936 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1939 DBG("service %p state %d", service, state);
1942 case CONNMAN_SERVICE_STATE_READY:
1943 case CONNMAN_SERVICE_STATE_ONLINE:
1944 case CONNMAN_SERVICE_STATE_FAILURE:
1945 connman_notifier_unregister(¬ifier);
1946 is_wifi_notifier_registered = FALSE;
1948 __connman_device_request_scan(type);
1957 static void scan_callback(int result, GSupplicantInterface *interface,
1960 struct connman_device *device = user_data;
1961 struct wifi_data *wifi = connman_device_get_data(device);
1964 DBG("result %d wifi %p", result, wifi);
1967 if (wifi->hidden && !wifi->postpone_hidden) {
1968 connman_network_clear_hidden(wifi->hidden->user_data);
1969 hidden_free(wifi->hidden);
1970 wifi->hidden = NULL;
1973 if (wifi->scan_params) {
1974 g_supplicant_free_scan_params(wifi->scan_params);
1975 wifi->scan_params = NULL;
1980 connman_device_reset_scanning(device);
1982 /* User is connecting to a hidden AP, let's wait for finished event */
1983 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1984 GSupplicantScanParams *scan_params;
1987 wifi->postpone_hidden = false;
1988 scan_params = wifi->hidden->scan_params;
1989 wifi->hidden->scan_params = NULL;
1991 reset_autoscan(device);
1993 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1994 scan_callback, device);
1998 /* On error, let's recall scan_callback, which will cleanup */
1999 return scan_callback(ret, interface, user_data);
2002 #if defined TIZEN_EXT
2003 if (wifi && wifi->allow_full_scan) {
2005 DBG("Trigger Full Channel Scan");
2006 wifi->allow_full_scan = FALSE;
2008 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2009 scan_callback, device);
2013 /* On error, let's recall scan_callback, which will cleanup */
2014 return scan_callback(ret, interface, user_data);
2018 scanning = connman_device_get_scanning(device);
2020 connman_device_set_scanning(device,
2021 CONNMAN_SERVICE_TYPE_WIFI, false);
2023 if (result != -ENOLINK)
2024 #if defined TIZEN_EXT
2027 start_autoscan(device);
2030 * If we are here then we were scanning; however, if we are
2031 * also mid-flight disabling the interface, then wifi_disable
2032 * has already cleared the device scanning state and
2033 * unreferenced the device, obviating the need to do it here.
2037 connman_device_unref(device);
2039 #if defined TIZEN_EXT
2040 if (wifi && wifi->scan_pending_network && result != -EIO) {
2041 network_connect(wifi->scan_pending_network);
2042 wifi->scan_pending_network = NULL;
2043 connman_network_set_connecting(wifi->network);
2046 if (is_wifi_notifier_registered != true &&
2047 wifi_first_scan == true && found_with_first_scan == true) {
2048 wifi_first_scan = false;
2049 found_with_first_scan = false;
2051 connman_notifier_register(¬ifier);
2052 is_wifi_notifier_registered = true;
2057 static void scan_callback_hidden(int result,
2058 GSupplicantInterface *interface, void *user_data)
2060 struct connman_device *device = user_data;
2061 struct wifi_data *wifi = connman_device_get_data(device);
2062 GSupplicantScanParams *scan_params;
2065 DBG("result %d wifi %p", result, wifi);
2070 /* User is trying to connect to a hidden AP */
2071 if (wifi->hidden && wifi->postpone_hidden)
2074 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2078 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2079 ret = g_supplicant_interface_scan(wifi->interface,
2081 scan_callback_hidden,
2087 g_supplicant_free_scan_params(scan_params);
2090 scan_callback(result, interface, user_data);
2093 static gboolean autoscan_timeout(gpointer data)
2095 struct connman_device *device = data;
2096 struct wifi_data *wifi = connman_device_get_data(device);
2097 struct autoscan_params *autoscan;
2103 autoscan = wifi->autoscan;
2105 if (autoscan->interval <= 0) {
2106 interval = autoscan->base;
2109 interval = autoscan->interval * autoscan->base;
2111 #if defined TIZEN_EXT
2112 if (autoscan->interval >= autoscan->limit)
2114 if (interval > autoscan->limit)
2116 interval = autoscan->limit;
2118 throw_wifi_scan(wifi->device, scan_callback_hidden);
2121 DBG("interval %d", interval);
2123 autoscan->interval = interval;
2125 autoscan->timeout = g_timeout_add_seconds(interval,
2126 autoscan_timeout, device);
2131 static void start_autoscan(struct connman_device *device)
2133 struct wifi_data *wifi = connman_device_get_data(device);
2134 struct autoscan_params *autoscan;
2141 if (wifi->p2p_device)
2144 if (wifi->connected)
2147 autoscan = wifi->autoscan;
2151 if (autoscan->timeout > 0 || autoscan->interval > 0)
2154 connman_device_ref(device);
2156 autoscan_timeout(device);
2159 static struct autoscan_params *parse_autoscan_params(const char *params)
2161 struct autoscan_params *autoscan;
2166 DBG("Emulating autoscan");
2168 list_params = g_strsplit(params, ":", 0);
2169 if (list_params == 0)
2172 if (g_strv_length(list_params) < 3) {
2173 g_strfreev(list_params);
2177 base = atoi(list_params[1]);
2178 limit = atoi(list_params[2]);
2180 g_strfreev(list_params);
2182 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2184 DBG("Could not allocate memory for autoscan");
2188 DBG("base %d - limit %d", base, limit);
2189 autoscan->base = base;
2190 autoscan->limit = limit;
2195 static void setup_autoscan(struct wifi_data *wifi)
2197 if (!wifi->autoscan)
2198 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2200 start_autoscan(wifi->device);
2203 static void finalize_interface_creation(struct wifi_data *wifi)
2205 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2207 if (!wifi->device) {
2208 connman_error("WiFi device not set");
2212 connman_device_set_powered(wifi->device, true);
2214 if (!connman_setting_get_bool("BackgroundScanning"))
2217 if (wifi->p2p_device)
2220 setup_autoscan(wifi);
2223 static void interface_create_callback(int result,
2224 GSupplicantInterface *interface,
2227 struct wifi_data *wifi = user_data;
2229 DBG("result %d ifname %s, wifi %p", result,
2230 g_supplicant_interface_get_ifname(interface),
2233 if (result < 0 || !wifi)
2236 wifi->interface = interface;
2237 g_supplicant_interface_set_data(interface, wifi);
2239 if (g_supplicant_interface_get_ready(interface)) {
2240 wifi->interface_ready = true;
2241 finalize_interface_creation(wifi);
2245 static int wifi_enable(struct connman_device *device)
2247 struct wifi_data *wifi = connman_device_get_data(device);
2250 const char *driver = connman_option_get_string("wifi");
2253 DBG("device %p %p", device, wifi);
2255 index = connman_device_get_index(device);
2256 if (!wifi || index < 0)
2259 if (is_p2p_connecting())
2260 return -EINPROGRESS;
2262 interface = connman_inet_ifname(index);
2263 ret = g_supplicant_interface_create(interface, driver, NULL,
2264 interface_create_callback,
2271 return -EINPROGRESS;
2274 static int wifi_disable(struct connman_device *device)
2276 struct wifi_data *wifi = connman_device_get_data(device);
2279 DBG("device %p wifi %p", device, wifi);
2284 wifi->connected = false;
2285 wifi->disconnecting = false;
2287 if (wifi->pending_network)
2288 wifi->pending_network = NULL;
2290 stop_autoscan(device);
2292 if (wifi->p2p_find_timeout) {
2293 g_source_remove(wifi->p2p_find_timeout);
2294 wifi->p2p_find_timeout = 0;
2295 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2296 connman_device_unref(wifi->device);
2299 #if defined TIZEN_EXT
2300 if (wifi->automaxspeed_timeout != 0) {
2301 g_source_remove(wifi->automaxspeed_timeout);
2302 wifi->automaxspeed_timeout = 0;
2306 /* In case of a user scan, device is still referenced */
2307 if (connman_device_get_scanning(device)) {
2308 connman_device_set_scanning(device,
2309 CONNMAN_SERVICE_TYPE_WIFI, false);
2310 connman_device_unref(wifi->device);
2313 remove_networks(device, wifi);
2316 #if defined TIZEN_EXT
2317 wifi->scan_pending_network = NULL;
2319 if (is_wifi_notifier_registered == true) {
2320 connman_notifier_unregister(¬ifier);
2321 is_wifi_notifier_registered = false;
2325 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2329 return -EINPROGRESS;
2332 struct last_connected {
2338 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
2340 GTimeVal *aval = (GTimeVal *)a;
2341 GTimeVal *bval = (GTimeVal *)b;
2343 /* Note that the sort order is descending */
2344 if (aval->tv_sec < bval->tv_sec)
2347 if (aval->tv_sec > bval->tv_sec)
2353 static void free_entry(gpointer data)
2355 struct last_connected *entry = data;
2357 g_free(entry->ssid);
2361 static int get_latest_connections(int max_ssids,
2362 GSupplicantScanParams *scan_data)
2364 GSequenceIter *iter;
2365 GSequence *latest_list;
2366 struct last_connected *entry;
2375 latest_list = g_sequence_new(free_entry);
2379 services = connman_storage_get_services();
2380 for (i = 0; services && services[i]; i++) {
2381 if (strncmp(services[i], "wifi_", 5) != 0)
2384 keyfile = connman_storage_load_service(services[i]);
2388 str = g_key_file_get_string(keyfile,
2389 services[i], "Favorite", NULL);
2390 if (!str || g_strcmp0(str, "true")) {
2392 g_key_file_free(keyfile);
2397 str = g_key_file_get_string(keyfile,
2398 services[i], "AutoConnect", NULL);
2399 if (!str || g_strcmp0(str, "true")) {
2401 g_key_file_free(keyfile);
2406 str = g_key_file_get_string(keyfile,
2407 services[i], "Modified", NULL);
2409 g_key_file_free(keyfile);
2412 g_time_val_from_iso8601(str, &modified);
2415 ssid = g_key_file_get_string(keyfile,
2416 services[i], "SSID", NULL);
2418 freq = g_key_file_get_integer(keyfile, services[i],
2421 entry = g_try_new(struct last_connected, 1);
2423 g_sequence_free(latest_list);
2424 g_key_file_free(keyfile);
2430 entry->modified = modified;
2433 g_sequence_insert_sorted(latest_list, entry,
2439 g_key_file_free(keyfile);
2442 g_strfreev(services);
2444 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2446 iter = g_sequence_get_begin_iter(latest_list);
2448 for (i = 0; i < num_ssids; i++) {
2449 entry = g_sequence_get(iter);
2451 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2452 entry->modified.tv_sec);
2454 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2455 max_ssids, entry->ssid);
2457 iter = g_sequence_iter_next(iter);
2460 g_sequence_free(latest_list);
2464 static int wifi_scan_simple(struct connman_device *device)
2466 reset_autoscan(device);
2468 return throw_wifi_scan(device, scan_callback_hidden);
2471 static gboolean p2p_find_stop(gpointer data)
2473 struct connman_device *device = data;
2474 struct wifi_data *wifi = connman_device_get_data(device);
2479 wifi->p2p_find_timeout = 0;
2481 g_supplicant_interface_p2p_stop_find(wifi->interface);
2484 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2486 connman_device_unref(device);
2487 reset_autoscan(device);
2492 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2495 struct connman_device *device = user_data;
2496 struct wifi_data *wifi = connman_device_get_data(device);
2498 DBG("result %d wifi %p", result, wifi);
2503 if (wifi->p2p_find_timeout) {
2504 g_source_remove(wifi->p2p_find_timeout);
2505 wifi->p2p_find_timeout = 0;
2511 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2512 p2p_find_stop, device);
2513 if (!wifi->p2p_find_timeout)
2518 p2p_find_stop(device);
2521 static int p2p_find(struct connman_device *device)
2523 struct wifi_data *wifi;
2528 if (!p2p_technology)
2531 wifi = connman_device_get_data(device);
2533 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2536 reset_autoscan(device);
2537 connman_device_ref(device);
2539 ret = g_supplicant_interface_p2p_find(wifi->interface,
2540 p2p_find_callback, device);
2542 connman_device_unref(device);
2543 start_autoscan(device);
2545 connman_device_set_scanning(device,
2546 CONNMAN_SERVICE_TYPE_P2P, true);
2552 #if defined TIZEN_EXT
2553 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2556 struct connman_device *device = user_data;
2557 struct wifi_data *wifi = connman_device_get_data(device);
2560 DBG("result %d wifi %p", result, wifi);
2562 if (wifi && wifi->scan_params) {
2563 g_supplicant_free_scan_params(wifi->scan_params);
2564 wifi->scan_params = NULL;
2567 scanning = connman_device_get_scanning(device);
2569 connman_device_set_scanning(device,
2570 CONNMAN_SERVICE_TYPE_WIFI, false);
2571 connman_device_unref(device);
2575 static int wifi_specific_scan(enum connman_service_type type,
2576 struct connman_device *device, int scan_type,
2577 GSList *specific_scan_list, void *user_data)
2579 GSList *list = NULL;
2581 struct wifi_data *wifi = connman_device_get_data(device);
2582 GSupplicantScanParams *scan_params = NULL;
2583 struct scan_ssid *scan_ssid = NULL;
2592 if (wifi->p2p_device)
2595 if (type == CONNMAN_SERVICE_TYPE_P2P)
2596 return p2p_find(device);
2598 if (wifi->tethering)
2601 scanning = connman_device_get_scanning(device);
2605 DBG("scan_type: %d", scan_type);
2606 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2607 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2609 DBG("Failed to allocate memory.");
2613 for (list = specific_scan_list; list; list = list->next) {
2614 ssid = (char *)list->data;
2615 int ssid_len = strlen(ssid);
2617 scan_ssid = g_try_new0(struct scan_ssid, 1);
2619 DBG("Failed to allocate memory.");
2620 g_supplicant_free_scan_params(scan_params);
2624 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2625 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2626 scan_ssid->ssid_len = ssid_len;
2627 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2630 scan_params->num_ssids = count;
2632 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2634 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2636 DBG("Failed to allocate memory.");
2640 guint num_freqs = g_slist_length(specific_scan_list);
2641 DBG("num_freqs: %d", num_freqs);
2643 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2644 if (!scan_params->freqs) {
2645 DBG("Failed to allocate memory.");
2646 g_free(scan_params);
2651 for (list = specific_scan_list; list; list = list->next) {
2652 freq = (int)list->data;
2654 scan_params->freqs[count] = freq;
2655 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2658 scan_params->num_freqs = count;
2660 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2661 int freq_count, ap_count;
2662 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2664 DBG("Failed to allocate memory.");
2668 guint size = g_slist_length(specific_scan_list);
2670 scan_params->freqs = g_try_new0(uint16_t, size/2);
2671 if (!scan_params->freqs) {
2672 DBG("Failed to allocate memory.");
2673 g_free(scan_params);
2677 ap_count = freq_count = 0;
2678 for (list = specific_scan_list; list; list = list->next) {
2679 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2680 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2681 int ssid_len = strlen(ssid);
2683 scan_ssid = g_try_new0(struct scan_ssid, 1);
2685 DBG("Failed to allocate memory.");
2686 g_supplicant_free_scan_params(scan_params);
2690 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2691 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2692 scan_ssid->ssid_len = ssid_len;
2693 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2697 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2698 scan_params->freqs[freq_count] = freq;
2699 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2703 scan_params->num_ssids = ap_count;
2704 scan_params->num_freqs = freq_count;
2706 DBG("Invalid scan");
2710 reset_autoscan(device);
2711 connman_device_ref(device);
2713 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2714 specific_scan_callback, device);
2717 connman_device_set_scanning(device,
2718 CONNMAN_SERVICE_TYPE_WIFI, true);
2720 g_supplicant_free_scan_params(scan_params);
2721 connman_device_unref(device);
2728 #if defined TIZEN_EXT_WIFI_MESH
2729 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2732 struct connman_device *device = user_data;
2733 struct wifi_data *wifi = connman_device_get_data(device);
2736 DBG("result %d wifi %p", result, wifi);
2738 scanning = connman_device_get_scanning(device);
2740 connman_device_set_scanning(device,
2741 CONNMAN_SERVICE_TYPE_MESH, false);
2744 connman_device_unref(device);
2747 static int mesh_scan(struct connman_device *device)
2749 struct wifi_data *wifi;
2750 struct wifi_mesh_info *mesh_info;
2755 wifi = connman_device_get_data(device);
2757 if (!wifi->mesh_interface)
2760 mesh_info = wifi->mesh_info;
2761 reset_autoscan(device);
2762 connman_device_ref(device);
2764 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2765 mesh_scan_callback, device);
2767 connman_device_unref(device);
2769 connman_device_set_scanning(device,
2770 CONNMAN_SERVICE_TYPE_MESH, true);
2775 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2778 struct connman_device *device = user_data;
2779 struct wifi_data *wifi = connman_device_get_data(device);
2781 DBG("result %d wifi %p", result, wifi);
2783 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2786 static int mesh_abort_scan(enum connman_service_type type,
2787 struct connman_device *device)
2789 struct wifi_data *wifi = connman_device_get_data(device);
2790 struct wifi_mesh_info *mesh_info;
2794 if (!wifi || !wifi->mesh_interface)
2797 if (type != CONNMAN_SERVICE_TYPE_MESH)
2800 mesh_info = wifi->mesh_info;
2802 scanning = connman_device_get_scanning(device);
2806 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2807 abort_scan_callback, device);
2812 static int mesh_specific_scan(enum connman_service_type type,
2813 struct connman_device *device, const char *ssid,
2814 unsigned int freq, void *user_data)
2816 struct wifi_data *wifi = connman_device_get_data(device);
2817 GSupplicantScanParams *scan_params = NULL;
2818 struct wifi_mesh_info *mesh_info;
2819 struct scan_ssid *scan_ssid;
2823 if (!wifi || !wifi->mesh_interface)
2826 if (type != CONNMAN_SERVICE_TYPE_MESH)
2829 if (wifi->p2p_device)
2832 mesh_info = wifi->mesh_info;
2834 scanning = connman_device_get_scanning(device);
2838 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2842 scan_ssid = g_try_new(struct scan_ssid, 1);
2844 g_free(scan_params);
2848 scan_ssid->ssid_len = strlen(ssid);
2849 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2850 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2851 scan_params->num_ssids = 1;
2853 scan_params->freqs = g_try_new(uint16_t, 1);
2854 if (!scan_params->freqs) {
2855 g_slist_free_full(scan_params->ssids, g_free);
2856 g_free(scan_params);
2860 scan_params->freqs[0] = freq;
2861 scan_params->num_freqs = 1;
2863 reset_autoscan(device);
2864 connman_device_ref(device);
2866 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2867 mesh_scan_callback, device);
2870 connman_device_set_scanning(device,
2871 CONNMAN_SERVICE_TYPE_MESH, true);
2873 g_supplicant_free_scan_params(scan_params);
2874 connman_device_unref(device);
2882 * Note that the hidden scan is only used when connecting to this specific
2883 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2885 static int wifi_scan(enum connman_service_type type,
2886 struct connman_device *device,
2887 const char *ssid, unsigned int ssid_len,
2888 const char *identity, const char* passphrase,
2889 const char *security, void *user_data)
2891 struct wifi_data *wifi = connman_device_get_data(device);
2892 GSupplicantScanParams *scan_params = NULL;
2893 struct scan_ssid *scan_ssid;
2894 struct hidden_params *hidden;
2896 int driver_max_ssids = 0;
2903 if (wifi->p2p_device)
2906 if (wifi->tethering)
2909 if (type == CONNMAN_SERVICE_TYPE_P2P)
2910 return p2p_find(device);
2912 #if defined TIZEN_EXT_WIFI_MESH
2913 if (type == CONNMAN_SERVICE_TYPE_MESH)
2914 return mesh_scan(device);
2917 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2919 scanning = connman_device_get_scanning(device);
2921 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2925 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2927 DBG("max ssids %d", driver_max_ssids);
2928 if (driver_max_ssids == 0)
2929 return wifi_scan_simple(device);
2933 if (scanning && wifi->hidden && wifi->postpone_hidden)
2939 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2944 scan_ssid = g_try_new(struct scan_ssid, 1);
2946 g_free(scan_params);
2950 memcpy(scan_ssid->ssid, ssid, ssid_len);
2951 scan_ssid->ssid_len = ssid_len;
2952 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2954 scan_params->num_ssids = 1;
2956 hidden = g_try_new0(struct hidden_params, 1);
2958 g_supplicant_free_scan_params(scan_params);
2963 hidden_free(wifi->hidden);
2964 wifi->hidden = NULL;
2967 memcpy(hidden->ssid, ssid, ssid_len);
2968 hidden->ssid_len = ssid_len;
2969 hidden->identity = g_strdup(identity);
2970 hidden->passphrase = g_strdup(passphrase);
2971 hidden->security = g_strdup(security);
2972 hidden->user_data = user_data;
2973 wifi->hidden = hidden;
2976 /* Let's keep this active scan for later,
2977 * when current scan will be over. */
2978 wifi->postpone_hidden = TRUE;
2979 hidden->scan_params = scan_params;
2983 } else if (wifi->connected) {
2984 g_supplicant_free_scan_params(scan_params);
2985 return wifi_scan_simple(device);
2987 ret = get_latest_connections(driver_max_ssids, scan_params);
2989 g_supplicant_free_scan_params(scan_params);
2990 return wifi_scan_simple(device);
2994 connman_device_ref(device);
2996 reset_autoscan(device);
2998 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2999 scan_callback, device);
3002 connman_device_set_scanning(device,
3003 CONNMAN_SERVICE_TYPE_WIFI, true);
3004 #if defined TIZEN_EXT
3005 /*To allow the Full Scan after ssid based scan, set the flag here
3006 It is required because Tizen does not use the ConnMan specific
3007 backgroung Scan feature.Tizen has added the BG Scan feature in
3008 net-config. To sync with up ConnMan, we need to issue the Full Scan
3009 after SSID specific scan.*/
3010 wifi->allow_full_scan = TRUE;
3013 g_supplicant_free_scan_params(scan_params);
3014 connman_device_unref(device);
3017 hidden_free(wifi->hidden);
3018 wifi->hidden = NULL;
3025 static void wifi_regdom_callback(int result,
3029 struct connman_device *device = user_data;
3031 connman_device_regdom_notify(device, result, alpha2);
3033 connman_device_unref(device);
3036 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3038 struct wifi_data *wifi = connman_device_get_data(device);
3044 connman_device_ref(device);
3046 ret = g_supplicant_interface_set_country(wifi->interface,
3047 wifi_regdom_callback,
3050 connman_device_unref(device);
3055 static struct connman_device_driver wifi_ng_driver = {
3057 .type = CONNMAN_DEVICE_TYPE_WIFI,
3058 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3059 .probe = wifi_probe,
3060 .remove = wifi_remove,
3061 .enable = wifi_enable,
3062 .disable = wifi_disable,
3064 .set_regdom = wifi_set_regdom,
3065 #if defined TIZEN_EXT
3066 .specific_scan = wifi_specific_scan,
3068 #if defined TIZEN_EXT_WIFI_MESH
3069 .abort_scan = mesh_abort_scan,
3070 .mesh_specific_scan = mesh_specific_scan,
3074 static void system_ready(void)
3078 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3079 connman_error("Failed to register WiFi driver");
3082 static void system_killed(void)
3086 connman_device_driver_unregister(&wifi_ng_driver);
3089 static int network_probe(struct connman_network *network)
3091 DBG("network %p", network);
3096 static void network_remove(struct connman_network *network)
3098 struct connman_device *device = connman_network_get_device(network);
3099 struct wifi_data *wifi;
3101 DBG("network %p", network);
3103 wifi = connman_device_get_data(device);
3107 if (wifi->network != network)
3110 wifi->network = NULL;
3112 #if defined TIZEN_EXT
3113 wifi->disconnecting = false;
3115 if (wifi->pending_network == network)
3116 wifi->pending_network = NULL;
3118 if (wifi->scan_pending_network == network)
3119 wifi->scan_pending_network = NULL;
3123 static void connect_callback(int result, GSupplicantInterface *interface,
3126 #if defined TIZEN_EXT
3128 struct wifi_data *wifi;
3130 struct connman_network *network = user_data;
3132 DBG("network %p result %d", network, result);
3134 #if defined TIZEN_EXT
3135 set_connman_bssid(RESET_BSSID, NULL);
3137 for (list = iface_list; list; list = list->next) {
3140 if (wifi && wifi->network == network)
3144 /* wifi_data may be invalid because wifi is already disabled */
3149 if (result == -ENOKEY) {
3150 connman_network_set_error(network,
3151 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3152 } else if (result < 0) {
3153 connman_network_set_error(network,
3154 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3157 connman_network_unref(network);
3160 static GSupplicantSecurity network_security(const char *security)
3162 if (g_str_equal(security, "none"))
3163 return G_SUPPLICANT_SECURITY_NONE;
3164 else if (g_str_equal(security, "wep"))
3165 return G_SUPPLICANT_SECURITY_WEP;
3166 else if (g_str_equal(security, "psk"))
3167 return G_SUPPLICANT_SECURITY_PSK;
3168 else if (g_str_equal(security, "wpa"))
3169 return G_SUPPLICANT_SECURITY_PSK;
3170 else if (g_str_equal(security, "rsn"))
3171 return G_SUPPLICANT_SECURITY_PSK;
3172 else if (g_str_equal(security, "ieee8021x"))
3173 return G_SUPPLICANT_SECURITY_IEEE8021X;
3174 #if defined TIZEN_EXT
3175 else if (g_str_equal(security, "ft_psk") == TRUE)
3176 return G_SUPPLICANT_SECURITY_FT_PSK;
3177 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3178 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3179 else if (g_str_equal(security, "sae"))
3180 return G_SUPPLICANT_SECURITY_SAE;
3181 else if (g_str_equal(security, "owe"))
3182 return G_SUPPLICANT_SECURITY_OWE;
3185 return G_SUPPLICANT_SECURITY_UNKNOWN;
3188 #if defined TIZEN_EXT
3189 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3191 if (security == NULL)
3192 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3194 if (g_str_equal(security, "FT") == TRUE)
3195 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3196 else if (g_str_equal(security, "CCKM") == TRUE)
3197 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3199 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3203 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3205 const char *security;
3206 #if defined TIZEN_EXT
3207 const void *ssid_data;
3210 memset(ssid, 0, sizeof(*ssid));
3211 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3212 #if defined TIZEN_EXT
3213 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3215 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3220 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3222 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3225 ssid->scan_ssid = 1;
3226 security = connman_network_get_string(network, "WiFi.Security");
3227 ssid->security = network_security(security);
3228 #if defined TIZEN_EXT
3229 ssid->ieee80211w = 1;
3231 ssid->passphrase = connman_network_get_string(network,
3233 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3236 * If our private key password is unset,
3237 * we use the supplied passphrase. That is needed
3238 * for PEAP where 2 passphrases (identity and client
3239 * cert may have to be provided.
3241 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3242 connman_network_set_string(network,
3243 "WiFi.PrivateKeyPassphrase",
3245 /* We must have an identity for both PEAP and TLS */
3246 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3248 /* Use agent provided identity as a fallback */
3249 if (!ssid->identity || strlen(ssid->identity) == 0)
3250 ssid->identity = connman_network_get_string(network,
3251 "WiFi.AgentIdentity");
3253 ssid->anonymous_identity = connman_network_get_string(network,
3254 "WiFi.AnonymousIdentity");
3255 ssid->ca_cert_path = connman_network_get_string(network,
3257 ssid->subject_match = connman_network_get_string(network,
3258 "WiFi.SubjectMatch");
3259 ssid->altsubject_match = connman_network_get_string(network,
3260 "WiFi.AltSubjectMatch");
3261 ssid->domain_suffix_match = connman_network_get_string(network,
3262 "WiFi.DomainSuffixMatch");
3263 ssid->domain_match = connman_network_get_string(network,
3264 "WiFi.DomainMatch");
3265 ssid->client_cert_path = connman_network_get_string(network,
3266 "WiFi.ClientCertFile");
3267 ssid->private_key_path = connman_network_get_string(network,
3268 "WiFi.PrivateKeyFile");
3269 ssid->private_key_passphrase = connman_network_get_string(network,
3270 "WiFi.PrivateKeyPassphrase");
3271 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3273 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3274 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3276 #if defined TIZEN_EXT
3277 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3278 ssid->bssid_for_connect_len = 6;
3279 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3280 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3281 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3282 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3283 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3285 ssid->freq = connman_network_get_frequency(network);
3288 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3289 if (bssid_list && g_slist_length(bssid_list) > 1) {
3291 /* If there are more than one bssid,
3292 * the user-specified bssid is tried only once at the beginning.
3293 * After that, the bssids in the list are tried in order.
3295 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3296 set_connman_bssid(RESET_BSSID, NULL);
3301 char buff[MAC_ADDRESS_LENGTH];
3302 for (list = bssid_list; list; list = list->next) {
3303 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3305 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3306 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3307 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3308 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3310 gchar *curr_bssid = g_strdup((const gchar *)buff);
3312 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3313 DBG("bssid match, try next bssid");
3317 g_hash_table_add(failed_bssids, curr_bssid);
3319 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3320 ssid->bssid = buff_bssid;
3321 ssid->freq = (unsigned int)bssids->frequency;
3327 ssid->bssid = connman_network_get_bssid(network);
3328 g_hash_table_remove_all(failed_bssids);
3331 ssid->bssid = connman_network_get_bssid(network);
3334 ssid->eap_keymgmt = network_eap_keymgmt(
3335 connman_network_get_string(network, "WiFi.KeymgmtType"));
3336 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3338 if(g_strcmp0(ssid->eap, "fast") == 0)
3339 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3342 if (connman_setting_get_bool("BackgroundScanning"))
3343 ssid->bgscan = BGSCAN_DEFAULT;
3346 static int network_connect(struct connman_network *network)
3348 struct connman_device *device = connman_network_get_device(network);
3349 struct wifi_data *wifi;
3350 GSupplicantInterface *interface;
3351 GSupplicantSSID *ssid;
3353 DBG("network %p", network);
3358 wifi = connman_device_get_data(device);
3362 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3366 interface = wifi->interface;
3368 ssid_init(ssid, network);
3370 if (wifi->disconnecting) {
3371 wifi->pending_network = network;
3372 #if defined TIZEN_EXT
3377 wifi->network = connman_network_ref(network);
3379 #if defined TIZEN_EXT
3380 wifi->scan_pending_network = NULL;
3383 return g_supplicant_interface_connect(interface, ssid,
3384 connect_callback, network);
3387 return -EINPROGRESS;
3390 static void disconnect_callback(int result, GSupplicantInterface *interface,
3393 #if defined TIZEN_EXT
3395 struct wifi_data *wifi;
3396 struct connman_network *network = user_data;
3398 DBG("network %p result %d", network, result);
3400 for (list = iface_list; list; list = list->next) {
3403 if (wifi->network == NULL && wifi->disconnecting == true)
3404 wifi->disconnecting = false;
3406 if (wifi->network == network)
3410 /* wifi_data may be invalid because wifi is already disabled */
3415 struct wifi_data *wifi = user_data;
3418 DBG("result %d supplicant interface %p wifi %p",
3419 result, interface, wifi);
3421 if (result == -ECONNABORTED) {
3422 DBG("wifi interface no longer available");
3426 if (wifi->network) {
3427 connman_network_set_connected(wifi->network, false);
3428 wifi->network = NULL;
3431 wifi->disconnecting = false;
3432 wifi->connected = false;
3434 if (wifi->pending_network) {
3435 network_connect(wifi->pending_network);
3436 wifi->pending_network = NULL;
3439 start_autoscan(wifi->device);
3442 static int network_disconnect(struct connman_network *network)
3444 struct connman_device *device = connman_network_get_device(network);
3445 struct wifi_data *wifi;
3447 #if defined TIZEN_EXT
3448 struct connman_service *service;
3451 DBG("network %p", network);
3453 wifi = connman_device_get_data(device);
3454 if (!wifi || !wifi->interface)
3457 #if defined TIZEN_EXT
3458 if (connman_network_get_associating(network) == true) {
3459 connman_network_clear_associating(network);
3460 connman_network_set_bool(network, "WiFi.UseWPS", false);
3462 service = connman_service_lookup_from_network(network);
3464 if (service != NULL &&
3465 (__connman_service_is_connected_state(service,
3466 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3467 __connman_service_is_connected_state(service,
3468 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3469 (connman_service_get_favorite(service) == false))
3470 __connman_service_set_passphrase(service, NULL);
3473 if (wifi->pending_network == network)
3474 wifi->pending_network = NULL;
3476 if (wifi->scan_pending_network == network)
3477 wifi->scan_pending_network = NULL;
3480 connman_network_set_associating(network, false);
3482 if (wifi->disconnecting)
3485 wifi->disconnecting = true;
3487 #if defined TIZEN_EXT
3488 err = g_supplicant_interface_disconnect(wifi->interface,
3489 disconnect_callback, network);
3491 err = g_supplicant_interface_disconnect(wifi->interface,
3492 disconnect_callback, wifi);
3496 wifi->disconnecting = false;
3501 #if defined TIZEN_EXT
3502 static void set_connection_mode(struct connman_network *network,
3505 ieee80211_modes_e phy_mode;
3506 connection_mode_e conn_mode;
3508 phy_mode = connman_network_get_phy_mode(network);
3510 case IEEE80211_MODE_B:
3511 if (linkspeed > 0 && linkspeed <= 11)
3512 conn_mode = CONNECTION_MODE_IEEE80211B;
3514 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3517 case IEEE80211_MODE_BG:
3518 if (linkspeed > 0 && linkspeed <= 11)
3519 conn_mode = CONNECTION_MODE_IEEE80211B;
3520 else if (linkspeed > 11 && linkspeed <= 54)
3521 conn_mode = CONNECTION_MODE_IEEE80211G;
3523 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3526 case IEEE80211_MODE_BGN:
3527 if (linkspeed > 0 && linkspeed <= 11)
3528 conn_mode = CONNECTION_MODE_IEEE80211B;
3529 else if (linkspeed > 11 && linkspeed <= 54)
3530 conn_mode = CONNECTION_MODE_IEEE80211G;
3531 else if (linkspeed > 54 && linkspeed <= 450)
3532 conn_mode = CONNECTION_MODE_IEEE80211N;
3534 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3537 case IEEE80211_MODE_A:
3538 if (linkspeed > 0 && linkspeed <= 54)
3539 conn_mode = CONNECTION_MODE_IEEE80211A;
3541 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3544 case IEEE80211_MODE_AN:
3545 if (linkspeed > 0 && linkspeed <= 54)
3546 conn_mode = CONNECTION_MODE_IEEE80211A;
3547 else if (linkspeed > 54 && linkspeed <= 450)
3548 conn_mode = CONNECTION_MODE_IEEE80211N;
3550 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3553 case IEEE80211_MODE_ANAC:
3554 if (linkspeed > 0 && linkspeed <= 54)
3555 conn_mode = CONNECTION_MODE_IEEE80211A;
3556 else if (linkspeed > 54 && linkspeed <= 450)
3557 conn_mode = CONNECTION_MODE_IEEE80211N;
3558 else if (linkspeed > 450 && linkspeed <= 1300)
3559 conn_mode = CONNECTION_MODE_IEEE80211AC;
3561 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3565 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3569 DBG("connection mode(%d)", conn_mode);
3570 connman_network_set_connection_mode(network, conn_mode);
3573 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3575 struct connman_network *network = user_data;
3578 DBG("Failed to get maxspeed from signalpoll !");
3582 DBG("maxspeed = %d", maxspeed);
3584 connman_network_set_maxspeed(network, maxspeed);
3585 set_connection_mode(network, maxspeed);
3589 static int network_signalpoll(struct wifi_data *wifi)
3591 GSupplicantInterface *interface;
3592 struct connman_network *network;
3594 if (!wifi || !wifi->network)
3597 interface = wifi->interface;
3598 network = wifi->network;
3600 DBG("network %p", network);
3602 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3605 static gboolean autosignalpoll_timeout(gpointer data)
3607 struct wifi_data *wifi = data;
3609 if (!wifi || !wifi->automaxspeed_timeout) {
3610 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3614 int ret = network_signalpoll(wifi);
3616 DBG("Fail to get max speed !!");
3617 wifi->automaxspeed_timeout = 0;
3625 static struct connman_network_driver network_driver = {
3627 .type = CONNMAN_NETWORK_TYPE_WIFI,
3628 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3629 .probe = network_probe,
3630 .remove = network_remove,
3631 .connect = network_connect,
3632 .disconnect = network_disconnect,
3635 static void interface_added(GSupplicantInterface *interface)
3637 const char *ifname = g_supplicant_interface_get_ifname(interface);
3638 const char *driver = g_supplicant_interface_get_driver(interface);
3639 #if defined TIZEN_EXT
3640 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3643 struct wifi_data *wifi;
3645 wifi = g_supplicant_interface_get_data(interface);
3647 wifi = get_pending_wifi_data(ifname);
3651 wifi->interface = interface;
3652 g_supplicant_interface_set_data(interface, wifi);
3653 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3654 wifi->p2p_device = true;
3657 DBG("ifname %s driver %s wifi %p tethering %d",
3658 ifname, driver, wifi, wifi->tethering);
3660 if (!wifi->device) {
3661 connman_error("WiFi device not set");
3665 connman_device_set_powered(wifi->device, true);
3666 #if defined TIZEN_EXT
3667 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3668 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3669 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3670 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3674 static bool is_idle(struct wifi_data *wifi)
3676 DBG("state %d", wifi->state);
3678 switch (wifi->state) {
3679 case G_SUPPLICANT_STATE_UNKNOWN:
3680 case G_SUPPLICANT_STATE_DISABLED:
3681 case G_SUPPLICANT_STATE_DISCONNECTED:
3682 case G_SUPPLICANT_STATE_INACTIVE:
3683 case G_SUPPLICANT_STATE_SCANNING:
3686 case G_SUPPLICANT_STATE_AUTHENTICATING:
3687 case G_SUPPLICANT_STATE_ASSOCIATING:
3688 case G_SUPPLICANT_STATE_ASSOCIATED:
3689 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3690 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3691 case G_SUPPLICANT_STATE_COMPLETED:
3698 static bool is_idle_wps(GSupplicantInterface *interface,
3699 struct wifi_data *wifi)
3701 /* First, let's check if WPS processing did not went wrong */
3702 if (g_supplicant_interface_get_wps_state(interface) ==
3703 G_SUPPLICANT_WPS_STATE_FAIL)
3706 /* Unlike normal connection, being associated while processing wps
3707 * actually means that we are idling. */
3708 switch (wifi->state) {
3709 case G_SUPPLICANT_STATE_UNKNOWN:
3710 case G_SUPPLICANT_STATE_DISABLED:
3711 case G_SUPPLICANT_STATE_DISCONNECTED:
3712 case G_SUPPLICANT_STATE_INACTIVE:
3713 case G_SUPPLICANT_STATE_SCANNING:
3714 case G_SUPPLICANT_STATE_ASSOCIATED:
3716 case G_SUPPLICANT_STATE_AUTHENTICATING:
3717 case G_SUPPLICANT_STATE_ASSOCIATING:
3718 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3719 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3720 case G_SUPPLICANT_STATE_COMPLETED:
3727 static bool handle_wps_completion(GSupplicantInterface *interface,
3728 struct connman_network *network,
3729 struct connman_device *device,
3730 struct wifi_data *wifi)
3734 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3736 const unsigned char *ssid, *wps_ssid;
3737 unsigned int ssid_len, wps_ssid_len;
3738 const char *wps_key;
3740 /* Checking if we got associated with requested
3742 ssid = connman_network_get_blob(network, "WiFi.SSID",
3745 wps_ssid = g_supplicant_interface_get_wps_ssid(
3746 interface, &wps_ssid_len);
3748 if (!wps_ssid || wps_ssid_len != ssid_len ||
3749 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3750 connman_network_set_associating(network, false);
3751 #if defined TIZEN_EXT
3752 g_supplicant_interface_disconnect(wifi->interface,
3753 disconnect_callback, wifi->network);
3755 connman_network_set_bool(network, "WiFi.UseWPS", false);
3756 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3758 g_supplicant_interface_disconnect(wifi->interface,
3759 disconnect_callback, wifi);
3764 wps_key = g_supplicant_interface_get_wps_key(interface);
3765 #if defined TIZEN_EXT
3766 /* Check the passphrase and encrypt it
3769 gchar *passphrase = g_strdup(wps_key);
3771 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3773 if (check_passphrase_ext(network, passphrase) < 0) {
3774 DBG("[WPS] Invalid passphrase");
3779 ret = send_encryption_request(passphrase, network);
3784 DBG("[WPS] Encryption request succeeded");
3786 DBG("[WPS] Encryption request failed %d", ret);
3789 connman_network_set_string(network, "WiFi.Passphrase",
3792 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3799 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3800 struct wifi_data *wifi)
3802 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3803 #if defined TIZEN_EXT
3804 wifi->assoc_code > 0 &&
3806 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3808 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3809 wifi->load_shaping_retries ++;
3812 wifi->load_shaping_retries = 0;
3816 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3817 struct connman_network *network,
3818 struct wifi_data *wifi)
3820 #if defined TIZEN_EXT
3821 const char *security;
3822 struct connman_service *service;
3824 if (wifi->connected)
3827 security = connman_network_get_string(network, "WiFi.Security");
3829 if (security && g_str_equal(security, "ieee8021x") == true &&
3830 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3832 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3837 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3840 struct connman_service *service;
3842 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3845 if (wifi->connected)
3849 service = connman_service_lookup_from_network(network);
3855 if (connman_service_get_favorite(service)) {
3856 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3861 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3866 #if defined TIZEN_EXT
3867 static bool handle_wifi_assoc_retry(struct connman_network *network,
3868 struct wifi_data *wifi)
3870 const char *security;
3872 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3873 connman_network_get_connecting(network) != true) {
3874 wifi->assoc_retry_count = 0;
3878 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3879 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3880 wifi->assoc_retry_count = 0;
3884 security = connman_network_get_string(network, "WiFi.Security");
3885 if (security && g_str_equal(security, "ieee8021x") == true &&
3886 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3887 wifi->assoc_retry_count = 0;
3891 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3892 wifi->assoc_retry_count = 0;
3894 /* Honestly it's not an invalid-key error,
3895 * however QA team recommends that the invalid-key error
3896 * might be better to display for user experience.
3898 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3907 static void interface_state(GSupplicantInterface *interface)
3909 struct connman_network *network;
3910 struct connman_device *device;
3911 struct wifi_data *wifi;
3912 GSupplicantState state = g_supplicant_interface_get_state(interface);
3916 wifi = g_supplicant_interface_get_data(interface);
3918 DBG("wifi %p interface state %d", wifi, state);
3923 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3924 if (wifi->tethering_param) {
3925 g_free(wifi->tethering_param->ssid);
3926 g_free(wifi->tethering_param);
3927 wifi->tethering_param = NULL;
3931 device = wifi->device;
3935 if (g_supplicant_interface_get_ready(interface) &&
3936 !wifi->interface_ready) {
3937 wifi->interface_ready = true;
3938 finalize_interface_creation(wifi);
3941 network = wifi->network;
3946 case G_SUPPLICANT_STATE_SCANNING:
3947 if (wifi->connected)
3948 connman_network_set_connected(network, false);
3952 case G_SUPPLICANT_STATE_AUTHENTICATING:
3953 case G_SUPPLICANT_STATE_ASSOCIATING:
3954 #if defined TIZEN_EXT
3955 reset_autoscan(device);
3957 stop_autoscan(device);
3960 if (!wifi->connected)
3961 connman_network_set_associating(network, true);
3965 case G_SUPPLICANT_STATE_COMPLETED:
3966 #if defined TIZEN_EXT
3967 /* though it should be already reset: */
3968 reset_autoscan(device);
3970 wifi->assoc_retry_count = 0;
3972 wifi->scan_pending_network = NULL;
3974 /* should be cleared scanning flag */
3975 bool scanning = connman_device_get_scanning(device);
3977 connman_device_set_scanning(device,
3978 CONNMAN_SERVICE_TYPE_WIFI, false);
3979 connman_device_unref(device);
3982 if (!wifi->automaxspeed_timeout) {
3983 DBG("Going to start signalpoll timer!!");
3984 int ret = network_signalpoll(wifi);
3986 DBG("Fail to get max speed !!");
3988 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
3991 g_hash_table_remove_all(failed_bssids);
3993 /* though it should be already stopped: */
3994 stop_autoscan(device);
3997 if (!handle_wps_completion(interface, network, device, wifi))
4000 connman_network_set_connected(network, true);
4002 wifi->disconnect_code = 0;
4003 wifi->assoc_code = 0;
4004 wifi->load_shaping_retries = 0;
4007 case G_SUPPLICANT_STATE_DISCONNECTED:
4008 #if defined TIZEN_EXT
4009 connman_network_set_maxspeed(network, 0);
4011 if (wifi->automaxspeed_timeout != 0) {
4012 g_source_remove(wifi->automaxspeed_timeout);
4013 wifi->automaxspeed_timeout = 0;
4014 DBG("Remove signalpoll timer!!");
4018 * If we're in one of the idle modes, we have
4019 * not started association yet and thus setting
4020 * those ones to FALSE could cancel an association
4023 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4025 if (is_idle_wps(interface, wifi))
4031 #if defined TIZEN_EXT
4032 if (handle_assoc_status_code(interface, wifi)) {
4033 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4034 guint bssid_length = 0;
4037 bssid_length = g_slist_length(bssid_list);
4039 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4040 network_connect(network);
4044 wifi->load_shaping_retries = 0;
4047 g_hash_table_remove_all(failed_bssids);
4049 if (handle_assoc_status_code(interface, wifi))
4053 /* If previous state was 4way-handshake, then
4054 * it's either: psk was incorrect and thus we retry
4055 * or if we reach the maximum retries we declare the
4057 if (handle_4way_handshake_failure(interface,
4061 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4062 switch (wifi->disconnect_code) {
4063 case 1: /* Unspecified reason */
4064 /* Let's assume it's because we got blocked */
4066 case 6: /* Class 2 frame received from nonauthenticated STA */
4067 connman_network_set_error(network,
4068 CONNMAN_NETWORK_ERROR_BLOCKED);
4075 #if defined TIZEN_EXT
4076 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4077 * Retry association until its retry count is expired */
4078 if (handle_wifi_assoc_retry(network, wifi) == true) {
4079 throw_wifi_scan(wifi->device, scan_callback);
4080 wifi->scan_pending_network = wifi->network;
4084 if(wifi->disconnect_code > 0){
4085 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4086 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4090 connman_network_set_connected(network, false);
4091 connman_network_set_associating(network, false);
4092 wifi->disconnecting = false;
4094 start_autoscan(device);
4098 case G_SUPPLICANT_STATE_INACTIVE:
4099 #if defined TIZEN_EXT
4100 if (handle_wps_completion(interface, network, device, wifi) == false)
4103 connman_network_set_associating(network, false);
4104 start_autoscan(device);
4108 case G_SUPPLICANT_STATE_UNKNOWN:
4109 case G_SUPPLICANT_STATE_DISABLED:
4110 case G_SUPPLICANT_STATE_ASSOCIATED:
4111 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4112 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4116 old_connected = wifi->connected;
4117 wifi->state = state;
4119 /* Saving wpa_s state policy:
4120 * If connected and if the state changes are roaming related:
4121 * --> We stay connected
4123 * --> We are connected
4125 * --> We are not connected
4128 case G_SUPPLICANT_STATE_AUTHENTICATING:
4129 case G_SUPPLICANT_STATE_ASSOCIATING:
4130 case G_SUPPLICANT_STATE_ASSOCIATED:
4131 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4132 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4133 if (wifi->connected)
4134 connman_warn("Probably roaming right now!"
4135 " Staying connected...");
4137 case G_SUPPLICANT_STATE_SCANNING:
4138 wifi->connected = false;
4141 start_autoscan(device);
4143 case G_SUPPLICANT_STATE_COMPLETED:
4144 wifi->connected = true;
4147 wifi->connected = false;
4154 static void interface_removed(GSupplicantInterface *interface)
4156 const char *ifname = g_supplicant_interface_get_ifname(interface);
4157 struct wifi_data *wifi;
4159 DBG("ifname %s", ifname);
4161 wifi = g_supplicant_interface_get_data(interface);
4163 #if defined TIZEN_EXT_WIFI_MESH
4164 if (wifi && wifi->mesh_interface) {
4165 DBG("Notify mesh interface remove");
4166 connman_mesh_notify_interface_remove(true);
4167 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4168 g_free(mesh_info->parent_ifname);
4169 g_free(mesh_info->ifname);
4170 g_free(mesh_info->identifier);
4172 wifi->mesh_interface = false;
4173 wifi->mesh_info = NULL;
4179 wifi->interface = NULL;
4181 if (wifi && wifi->tethering)
4184 if (!wifi || !wifi->device) {
4185 DBG("wifi interface already removed");
4189 connman_device_set_powered(wifi->device, false);
4191 check_p2p_technology();
4192 #if defined TIZEN_EXT_WIFI_MESH
4193 check_mesh_technology();
4197 static void set_device_type(const char *type, char dev_type[17])
4199 const char *oui = "0050F204";
4200 const char *category = "0001";
4201 const char *sub_category = "0000";
4203 if (!g_strcmp0(type, "handset")) {
4205 sub_category = "0005";
4206 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4207 sub_category = "0001";
4208 else if (!g_strcmp0(type, "server"))
4209 sub_category = "0002";
4210 else if (!g_strcmp0(type, "laptop"))
4211 sub_category = "0005";
4212 else if (!g_strcmp0(type, "desktop"))
4213 sub_category = "0006";
4214 else if (!g_strcmp0(type, "tablet"))
4215 sub_category = "0009";
4216 else if (!g_strcmp0(type, "watch"))
4219 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4222 static void p2p_support(GSupplicantInterface *interface)
4224 char dev_type[17] = {};
4225 const char *hostname;
4232 if (!g_supplicant_interface_has_p2p(interface))
4235 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4236 DBG("Could not register P2P technology driver");
4240 hostname = connman_utsname_get_hostname();
4242 hostname = "ConnMan";
4244 set_device_type(connman_machine_get_type(), dev_type);
4245 g_supplicant_interface_set_p2p_device_config(interface,
4246 hostname, dev_type);
4247 connman_peer_driver_register(&peer_driver);
4250 static void scan_started(GSupplicantInterface *interface)
4255 static void scan_finished(GSupplicantInterface *interface)
4257 #if defined TIZEN_EXT
4258 struct wifi_data *wifi;
4259 bool is_associating = false;
4260 static bool is_scanning = true;
4265 #if defined TIZEN_EXT
4266 wifi = g_supplicant_interface_get_data(interface);
4267 if (wifi && wifi->scan_pending_network) {
4268 network_connect(wifi->scan_pending_network);
4269 wifi->scan_pending_network = NULL;
4272 //service state - associating
4273 if(!wifi || !wifi->network)
4276 is_associating = connman_network_get_associating(wifi->network);
4277 if(is_associating && is_scanning){
4278 is_scanning = false;
4279 DBG("send scan for connecting");
4280 throw_wifi_scan(wifi->device, scan_callback);
4291 static void ap_create_fail(GSupplicantInterface *interface)
4293 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4296 if ((wifi->tethering) && (wifi->tethering_param)) {
4297 DBG("%s create AP fail \n",
4298 g_supplicant_interface_get_ifname(wifi->interface));
4300 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4301 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4302 wifi->tethering = false;
4304 ret = tech_set_tethering(wifi->tethering_param->technology,
4305 wifi->tethering_param->ssid->ssid,
4306 wifi->tethering_param->ssid->passphrase,
4307 wifi->bridge, true);
4309 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4310 connman_technology_tethering_notify(wifi_technology,false);
4313 g_free(wifi->tethering_param->ssid);
4314 g_free(wifi->tethering_param);
4315 wifi->tethering_param = NULL;
4321 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4323 unsigned char strength;
4325 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4327 #if !defined TIZEN_EXT
4334 #if defined TIZEN_EXT_WIFI_MESH
4335 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4337 GSupplicantInterface *interface;
4338 struct wifi_data *wifi;
4339 const char *name, *security;
4340 struct connman_mesh *connman_mesh;
4341 struct wifi_mesh_info *mesh_info;
4342 const unsigned char *bssid;
4343 const char *identifier;
4348 interface = g_supplicant_network_get_interface(supplicant_network);
4349 wifi = g_supplicant_interface_get_data(interface);
4350 if (!wifi || !wifi->mesh_interface) {
4351 DBG("Virtual Mesh interface not created");
4355 bssid = g_supplicant_network_get_bssid(supplicant_network);
4356 address = g_malloc0(19);
4357 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4358 bssid[2], bssid[3], bssid[4], bssid[5]);
4360 identifier = g_supplicant_network_get_identifier(supplicant_network);
4361 name = g_supplicant_network_get_name(supplicant_network);
4362 security = g_supplicant_network_get_security(supplicant_network);
4363 frequency = g_supplicant_network_get_frequency(supplicant_network);
4365 mesh_info = wifi->mesh_info;
4366 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4370 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4372 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4373 connman_mesh_set_name(connman_mesh, name);
4374 connman_mesh_set_security(connman_mesh, security);
4375 connman_mesh_set_frequency(connman_mesh, frequency);
4376 connman_mesh_set_address(connman_mesh, address);
4377 connman_mesh_set_index(connman_mesh, mesh_info->index);
4378 connman_mesh_set_strength(connman_mesh,
4379 calculate_strength(supplicant_network));
4380 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4382 ret = connman_mesh_register(connman_mesh);
4383 if (ret == -EALREADY)
4384 DBG("Mesh Peer is already registered");
4390 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4392 GSupplicantInterface *interface;
4393 struct wifi_data *wifi;
4394 struct connman_mesh *connman_mesh;
4395 struct wifi_mesh_info *mesh_info;
4396 const char *identifier;
4398 interface = g_supplicant_network_get_interface(supplicant_network);
4399 wifi = g_supplicant_interface_get_data(interface);
4400 if (!wifi || !wifi->mesh_interface) {
4401 DBG("Virtual Mesh interface not created");
4405 identifier = g_supplicant_network_get_identifier(supplicant_network);
4407 DBG("Failed to get Mesh Peer identifier");
4411 mesh_info = wifi->mesh_info;
4412 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4414 /* Do not unregister connected mesh peer */
4415 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4416 DBG("Mesh Peer %s is connected", identifier);
4419 DBG("Mesh Peer identifier %s removed", identifier);
4420 connman_mesh_unregister(connman_mesh);
4425 static void network_added(GSupplicantNetwork *supplicant_network)
4427 struct connman_network *network;
4428 GSupplicantInterface *interface;
4429 struct wifi_data *wifi;
4430 const char *name, *identifier, *security, *group, *mode;
4431 const unsigned char *ssid;
4432 unsigned int ssid_len;
4436 bool wps_advertizing;
4438 #if defined TIZEN_EXT
4439 GSList *vsie_list = NULL;
4440 const unsigned char *country_code;
4441 ieee80211_modes_e phy_mode;
4444 mode = g_supplicant_network_get_mode(supplicant_network);
4445 identifier = g_supplicant_network_get_identifier(supplicant_network);
4447 DBG("%s", identifier);
4449 if (!g_strcmp0(mode, "adhoc"))
4452 #if defined TIZEN_EXT_WIFI_MESH
4453 if (!g_strcmp0(mode, "mesh")) {
4454 mesh_peer_added(supplicant_network);
4459 interface = g_supplicant_network_get_interface(supplicant_network);
4460 wifi = g_supplicant_interface_get_data(interface);
4461 name = g_supplicant_network_get_name(supplicant_network);
4462 security = g_supplicant_network_get_security(supplicant_network);
4463 group = g_supplicant_network_get_identifier(supplicant_network);
4464 wps = g_supplicant_network_get_wps(supplicant_network);
4465 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4466 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4467 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4468 supplicant_network);
4473 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4475 network = connman_device_get_network(wifi->device, identifier);
4478 network = connman_network_create(identifier,
4479 CONNMAN_NETWORK_TYPE_WIFI);
4483 connman_network_set_index(network, wifi->index);
4485 if (connman_device_add_network(wifi->device, network) < 0) {
4486 connman_network_unref(network);
4490 wifi->networks = g_slist_prepend(wifi->networks, network);
4493 if (name && name[0] != '\0')
4494 connman_network_set_name(network, name);
4496 connman_network_set_blob(network, "WiFi.SSID",
4498 #if defined TIZEN_EXT
4499 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4501 connman_network_set_vsie_list(network, vsie_list);
4503 DBG("vsie_list is NULL");
4504 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4505 connman_network_set_countrycode(network, country_code);
4506 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4507 connman_network_set_phy_mode(network, phy_mode);
4509 connman_network_set_string(network, "WiFi.Security", security);
4510 connman_network_set_strength(network,
4511 calculate_strength(supplicant_network));
4512 connman_network_set_bool(network, "WiFi.WPS", wps);
4515 /* Is AP advertizing for WPS association?
4516 * If so, we decide to use WPS by default */
4517 if (wps_ready && wps_pbc &&
4519 #if !defined TIZEN_EXT
4520 connman_network_set_bool(network, "WiFi.UseWPS", true);
4522 DBG("wps is activating by ap but ignore it.");
4527 connman_network_set_frequency(network,
4528 g_supplicant_network_get_frequency(supplicant_network));
4529 #if defined TIZEN_EXT
4530 connman_network_set_bssid(network,
4531 g_supplicant_network_get_bssid(supplicant_network));
4532 connman_network_set_maxrate(network,
4533 g_supplicant_network_get_maxrate(supplicant_network));
4534 connman_network_set_enc_mode(network,
4535 g_supplicant_network_get_enc_mode(supplicant_network));
4536 connman_network_set_rsn_mode(network,
4537 g_supplicant_network_get_rsn_mode(supplicant_network));
4538 connman_network_set_keymgmt(network,
4539 g_supplicant_network_get_keymgmt(supplicant_network));
4540 connman_network_set_bool(network, "WiFi.HS20AP",
4541 g_supplicant_network_is_hs20AP(supplicant_network));
4542 connman_network_set_bssid_list(network,
4543 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4545 connman_network_set_available(network, true);
4546 connman_network_set_string(network, "WiFi.Mode", mode);
4548 #if defined TIZEN_EXT
4553 connman_network_set_group(network, group);
4555 #if defined TIZEN_EXT
4556 if (wifi_first_scan == true)
4557 found_with_first_scan = true;
4560 if (wifi->hidden && ssid) {
4561 #if defined TIZEN_EXT
4562 if (network_security(wifi->hidden->security) ==
4563 network_security(security) &&
4565 if (!g_strcmp0(wifi->hidden->security, security) &&
4567 wifi->hidden->ssid_len == ssid_len &&
4568 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4569 connman_network_connect_hidden(network,
4570 wifi->hidden->identity,
4571 wifi->hidden->passphrase,
4572 wifi->hidden->user_data);
4573 wifi->hidden->user_data = NULL;
4574 hidden_free(wifi->hidden);
4575 wifi->hidden = NULL;
4580 static void network_removed(GSupplicantNetwork *network)
4582 GSupplicantInterface *interface;
4583 struct wifi_data *wifi;
4584 const char *name, *identifier;
4585 struct connman_network *connman_network;
4587 #if defined TIZEN_EXT_WIFI_MESH
4589 mode = g_supplicant_network_get_mode(network);
4590 if (!g_strcmp0(mode, "mesh")) {
4591 mesh_peer_removed(network);
4596 interface = g_supplicant_network_get_interface(network);
4597 wifi = g_supplicant_interface_get_data(interface);
4598 identifier = g_supplicant_network_get_identifier(network);
4599 name = g_supplicant_network_get_name(network);
4601 DBG("name %s", name);
4606 connman_network = connman_device_get_network(wifi->device, identifier);
4607 if (!connman_network)
4610 #if defined TIZEN_EXT
4611 if (connman_network == wifi->scan_pending_network)
4612 wifi->scan_pending_network = NULL;
4614 if (connman_network == wifi->pending_network)
4615 wifi->pending_network = NULL;
4617 if(connman_network_get_connecting(connman_network) == true){
4618 connman_network_set_connected(connman_network, false);
4622 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4624 connman_device_remove_network(wifi->device, connman_network);
4625 connman_network_unref(connman_network);
4628 static void network_changed(GSupplicantNetwork *network, const char *property)
4630 GSupplicantInterface *interface;
4631 struct wifi_data *wifi;
4632 const char *name, *identifier;
4633 struct connman_network *connman_network;
4635 #if defined TIZEN_EXT
4636 const unsigned char *bssid;
4637 unsigned int maxrate;
4640 const unsigned char *country_code;
4641 ieee80211_modes_e phy_mode;
4645 interface = g_supplicant_network_get_interface(network);
4646 wifi = g_supplicant_interface_get_data(interface);
4647 identifier = g_supplicant_network_get_identifier(network);
4648 name = g_supplicant_network_get_name(network);
4650 DBG("name %s", name);
4655 connman_network = connman_device_get_network(wifi->device, identifier);
4656 if (!connman_network)
4659 if (g_str_equal(property, "Signal")) {
4660 connman_network_set_strength(connman_network,
4661 calculate_strength(network));
4662 connman_network_update(connman_network);
4665 #if defined TIZEN_EXT
4666 bssid = g_supplicant_network_get_bssid(network);
4667 maxrate = g_supplicant_network_get_maxrate(network);
4668 frequency = g_supplicant_network_get_frequency(network);
4669 wps = g_supplicant_network_get_wps(network);
4670 phy_mode = g_supplicant_network_get_phy_mode(network);
4672 connman_network_set_bssid(connman_network, bssid);
4673 connman_network_set_maxrate(connman_network, maxrate);
4674 connman_network_set_frequency(connman_network, frequency);
4675 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4676 country_code = g_supplicant_network_get_countrycode(network);
4677 connman_network_set_countrycode(connman_network, country_code);
4678 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4679 connman_network_set_bssid_list(connman_network, bssid_list);
4680 connman_network_set_phy_mode(connman_network, phy_mode);
4682 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4683 connman_network_get_associating(connman_network))
4684 network_connect(connman_network);
4688 static void network_associated(GSupplicantNetwork *network)
4690 GSupplicantInterface *interface;
4691 struct wifi_data *wifi;
4692 struct connman_network *connman_network;
4693 const char *identifier;
4697 interface = g_supplicant_network_get_interface(network);
4701 wifi = g_supplicant_interface_get_data(interface);
4705 identifier = g_supplicant_network_get_identifier(network);
4707 connman_network = connman_device_get_network(wifi->device, identifier);
4708 if (!connman_network)
4711 if (wifi->network) {
4712 if (wifi->network == connman_network)
4716 * This should never happen, we got associated with
4717 * a network different than the one we were expecting.
4719 DBG("Associated to %p while expecting %p",
4720 connman_network, wifi->network);
4722 connman_network_set_associating(wifi->network, false);
4725 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4727 wifi->network = connman_network_ref(connman_network);
4731 * Interface state changes callback (interface_state) is always
4732 * called before network_associated callback thus we need to call
4733 * interface_state again in order to process the new state now that
4734 * we have the network properly set.
4736 interface_state(interface);
4739 static void apply_peer_services(GSupplicantPeer *peer,
4740 struct connman_peer *connman_peer)
4742 const unsigned char *data;
4747 connman_peer_reset_services(connman_peer);
4749 data = g_supplicant_peer_get_widi_ies(peer, &length);
4751 connman_peer_add_service(connman_peer,
4752 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4756 static void add_station(const char *mac)
4758 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4762 static void remove_station(const char *mac)
4764 connman_technology_tethering_remove_station(mac);
4767 static void peer_found(GSupplicantPeer *peer)
4769 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4770 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4771 struct connman_peer *connman_peer;
4772 const char *identifier, *name;
4774 #if defined TIZEN_EXT
4778 identifier = g_supplicant_peer_get_identifier(peer);
4779 name = g_supplicant_peer_get_name(peer);
4781 DBG("ident: %s", identifier);
4783 connman_peer = connman_peer_get(wifi->device, identifier);
4787 connman_peer = connman_peer_create(identifier);
4788 connman_peer_set_name(connman_peer, name);
4789 connman_peer_set_device(connman_peer, wifi->device);
4790 apply_peer_services(peer, connman_peer);
4792 ret = connman_peer_register(connman_peer);
4793 if (ret < 0 && ret != -EALREADY)
4794 connman_peer_unref(connman_peer);
4796 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4799 static void peer_lost(GSupplicantPeer *peer)
4801 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4802 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4803 struct connman_peer *connman_peer;
4804 const char *identifier;
4809 identifier = g_supplicant_peer_get_identifier(peer);
4811 DBG("ident: %s", identifier);
4813 connman_peer = connman_peer_get(wifi->device, identifier);
4815 if (wifi->p2p_connecting &&
4816 wifi->pending_peer == connman_peer) {
4817 peer_connect_timeout(wifi);
4819 connman_peer_unregister(connman_peer);
4820 connman_peer_unref(connman_peer);
4823 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4826 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4828 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4829 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4830 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4831 struct connman_peer *connman_peer;
4832 const char *identifier;
4834 identifier = g_supplicant_peer_get_identifier(peer);
4836 DBG("ident: %s", identifier);
4841 connman_peer = connman_peer_get(wifi->device, identifier);
4846 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4847 apply_peer_services(peer, connman_peer);
4848 connman_peer_services_changed(connman_peer);
4850 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4851 if (!g_supplicant_peer_is_in_a_group(peer))
4852 p_state = CONNMAN_PEER_STATE_IDLE;
4854 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4856 case G_SUPPLICANT_PEER_GROUP_STARTED:
4858 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4859 p_state = CONNMAN_PEER_STATE_IDLE;
4861 case G_SUPPLICANT_PEER_GROUP_JOINED:
4862 connman_peer_set_iface_address(connman_peer,
4863 g_supplicant_peer_get_iface_address(peer));
4865 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4866 p_state = CONNMAN_PEER_STATE_IDLE;
4868 case G_SUPPLICANT_PEER_GROUP_FAILED:
4869 if (g_supplicant_peer_has_requested_connection(peer))
4870 p_state = CONNMAN_PEER_STATE_IDLE;
4872 p_state = CONNMAN_PEER_STATE_FAILURE;
4876 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4877 p_state == CONNMAN_PEER_STATE_FAILURE) {
4878 if (wifi->p2p_connecting
4879 && connman_peer == wifi->pending_peer)
4880 peer_cancel_timeout(wifi);
4882 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4885 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4888 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4889 GSupplicantInterface *g_iface;
4890 struct wifi_data *g_wifi;
4892 g_iface = g_supplicant_peer_get_group_interface(peer);
4896 g_wifi = g_supplicant_interface_get_data(g_iface);
4900 connman_peer_set_as_master(connman_peer,
4901 !g_supplicant_peer_is_client(peer));
4902 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4905 * If wpa_supplicant didn't create a dedicated p2p-group
4906 * interface then mark this interface as p2p_device to avoid
4907 * scan and auto-scan are launched on it while P2P is connected.
4909 if (!g_list_find(p2p_iface_list, g_wifi))
4910 wifi->p2p_device = true;
4913 connman_peer_set_state(connman_peer, p_state);
4916 static void peer_request(GSupplicantPeer *peer)
4918 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4919 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4920 struct connman_peer *connman_peer;
4921 const char *identifier;
4923 #if defined TIZEN_EXT
4928 identifier = g_supplicant_peer_get_identifier(peer);
4930 DBG("ident: %s", identifier);
4932 connman_peer = connman_peer_get(wifi->device, identifier);
4936 connman_peer_request_connection(connman_peer);
4939 #if defined TIZEN_EXT
4940 static void system_power_off(void)
4943 struct wifi_data *wifi;
4944 struct connman_service *service;
4945 struct connman_ipconfig *ipconfig_ipv4;
4947 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4948 for (list = iface_list; list; list = list->next) {
4951 if (wifi->network != NULL) {
4952 service = connman_service_lookup_from_network(wifi->network);
4953 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4954 __connman_dhcp_stop(ipconfig_ipv4);
4960 static void network_merged(GSupplicantNetwork *network)
4962 GSupplicantInterface *interface;
4963 GSupplicantState state;
4964 struct wifi_data *wifi;
4965 const char *identifier;
4966 struct connman_network *connman_network;
4970 interface = g_supplicant_network_get_interface(network);
4974 state = g_supplicant_interface_get_state(interface);
4975 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4978 wifi = g_supplicant_interface_get_data(interface);
4982 identifier = g_supplicant_network_get_identifier(network);
4984 connman_network = connman_device_get_network(wifi->device, identifier);
4985 if (!connman_network)
4988 DBG("merged identifier %s", identifier);
4990 if (wifi->connected == FALSE) {
4992 case G_SUPPLICANT_STATE_AUTHENTICATING:
4993 case G_SUPPLICANT_STATE_ASSOCIATING:
4994 case G_SUPPLICANT_STATE_ASSOCIATED:
4995 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4996 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4997 connman_network_set_associating(connman_network, TRUE);
4999 case G_SUPPLICANT_STATE_COMPLETED:
5000 connman_network_set_connected(connman_network, TRUE);
5003 DBG("Not handled the state : %d", state);
5008 ishs20AP = g_supplicant_network_is_hs20AP(network);
5011 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5012 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5013 connman_network_set_string(connman_network, "WiFi.EAP",
5015 connman_network_set_string(connman_network, "WiFi.Identity",
5016 g_supplicant_network_get_identity(network));
5017 connman_network_set_string(connman_network, "WiFi.Phase2",
5018 g_supplicant_network_get_phase2(network));
5023 wifi->network = connman_network;
5026 static void assoc_failed(void *user_data)
5028 struct connman_network *network = user_data;
5029 connman_network_set_associating(network, false);
5033 static void debug(const char *str)
5035 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5036 connman_debug("%s", str);
5039 static void disconnect_reasoncode(GSupplicantInterface *interface,
5042 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5045 wifi->disconnect_code = reasoncode;
5049 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5051 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5054 wifi->assoc_code = status_code;
5058 static const GSupplicantCallbacks callbacks = {
5059 .system_ready = system_ready,
5060 .system_killed = system_killed,
5061 .interface_added = interface_added,
5062 .interface_state = interface_state,
5063 .interface_removed = interface_removed,
5064 .p2p_support = p2p_support,
5065 .scan_started = scan_started,
5066 .scan_finished = scan_finished,
5067 .ap_create_fail = ap_create_fail,
5068 .network_added = network_added,
5069 .network_removed = network_removed,
5070 .network_changed = network_changed,
5071 .network_associated = network_associated,
5072 .add_station = add_station,
5073 .remove_station = remove_station,
5074 .peer_found = peer_found,
5075 .peer_lost = peer_lost,
5076 .peer_changed = peer_changed,
5077 .peer_request = peer_request,
5078 #if defined TIZEN_EXT
5079 .system_power_off = system_power_off,
5080 .network_merged = network_merged,
5081 .assoc_failed = assoc_failed,
5084 .disconnect_reasoncode = disconnect_reasoncode,
5085 .assoc_status_code = assoc_status_code,
5086 #if defined TIZEN_EXT_WIFI_MESH
5087 .mesh_support = mesh_support,
5088 .mesh_group_started = mesh_group_started,
5089 .mesh_group_removed = mesh_group_removed,
5090 .mesh_peer_connected = mesh_peer_connected,
5091 .mesh_peer_disconnected = mesh_peer_disconnected,
5096 static int tech_probe(struct connman_technology *technology)
5098 wifi_technology = technology;
5103 static void tech_remove(struct connman_technology *technology)
5105 wifi_technology = NULL;
5108 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5109 const char *passphrase)
5111 GSupplicantSSID *ap;
5113 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5117 ap->mode = G_SUPPLICANT_MODE_MASTER;
5118 #if defined TIZEN_EXT
5119 ap->ssid = (void *) ssid;
5123 ap->ssid_len = strlen(ssid);
5127 if (!passphrase || strlen(passphrase) == 0) {
5128 ap->security = G_SUPPLICANT_SECURITY_NONE;
5129 ap->passphrase = NULL;
5131 ap->security = G_SUPPLICANT_SECURITY_PSK;
5132 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5133 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5134 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5135 ap->passphrase = passphrase;
5141 static void ap_start_callback(int result, GSupplicantInterface *interface,
5144 struct wifi_tethering_info *info = user_data;
5146 DBG("result %d index %d bridge %s",
5147 result, info->wifi->index, info->wifi->bridge);
5149 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5150 connman_inet_remove_from_bridge(info->wifi->index,
5151 info->wifi->bridge);
5153 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5154 connman_technology_tethering_notify(info->technology, false);
5155 g_free(info->wifi->tethering_param->ssid);
5156 g_free(info->wifi->tethering_param);
5157 info->wifi->tethering_param = NULL;
5161 g_free(info->ifname);
5165 static void ap_create_callback(int result,
5166 GSupplicantInterface *interface,
5169 struct wifi_tethering_info *info = user_data;
5171 DBG("result %d ifname %s", result,
5172 g_supplicant_interface_get_ifname(interface));
5174 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5175 connman_inet_remove_from_bridge(info->wifi->index,
5176 info->wifi->bridge);
5178 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5179 connman_technology_tethering_notify(info->technology, false);
5180 g_free(info->wifi->tethering_param->ssid);
5181 g_free(info->wifi->tethering_param);
5182 info->wifi->tethering_param = NULL;
5186 g_free(info->ifname);
5192 info->wifi->interface = interface;
5193 g_supplicant_interface_set_data(interface, info->wifi);
5195 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5196 connman_error("Failed to set interface ap_scan property");
5198 g_supplicant_interface_connect(interface, info->ssid,
5199 ap_start_callback, info);
5202 static void sta_remove_callback(int result,
5203 GSupplicantInterface *interface,
5206 struct wifi_tethering_info *info = user_data;
5207 const char *driver = connman_option_get_string("wifi");
5209 DBG("ifname %s result %d ", info->ifname, result);
5211 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5212 info->wifi->tethering = false;
5213 connman_technology_tethering_notify(info->technology, false);
5215 g_free(info->ifname);
5219 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5220 g_free(info->wifi->tethering_param->ssid);
5221 g_free(info->wifi->tethering_param);
5222 info->wifi->tethering_param = NULL;
5227 info->wifi->interface = NULL;
5229 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5234 static int enable_wifi_tethering(struct connman_technology *technology,
5235 const char *bridge, const char *identifier,
5236 const char *passphrase, bool available)
5239 GSupplicantInterface *interface;
5240 struct wifi_data *wifi;
5241 struct wifi_tethering_info *info;
5246 for (list = iface_list; list; list = list->next) {
5249 DBG("wifi %p network %p pending_network %p", wifi,
5250 wifi->network, wifi->pending_network);
5252 interface = wifi->interface;
5257 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5260 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5262 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5263 DBG("%s does not support AP mode (detected)", ifname);
5267 mode = g_supplicant_interface_get_mode(interface);
5268 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5269 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5270 DBG("%s does not support AP mode (capability)", ifname);
5274 if (wifi->network && available)
5277 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5281 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5282 if (!wifi->tethering_param) {
5288 info->technology = technology;
5289 info->wifi->bridge = bridge;
5290 info->ssid = ssid_ap_init(identifier, passphrase);
5294 info->ifname = g_strdup(ifname);
5298 wifi->tethering_param->technology = technology;
5299 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5300 if (!wifi->tethering_param->ssid)
5303 info->wifi->tethering = true;
5304 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5306 berr = connman_technology_tethering_notify(technology, true);
5310 err = g_supplicant_interface_remove(interface,
5311 sta_remove_callback,
5314 DBG("tethering wifi %p ifname %s", wifi, ifname);
5319 g_free(info->ifname);
5322 g_free(wifi->tethering_param);
5323 wifi->tethering_param = NULL;
5326 * Remove bridge if it was correctly created but remove
5327 * operation failed. Instead, if bridge creation failed then
5328 * break out and do not try again on another interface,
5329 * bridge set-up does not depend on it.
5332 connman_technology_tethering_notify(technology, false);
5340 static int tech_set_tethering(struct connman_technology *technology,
5341 const char *identifier, const char *passphrase,
5342 const char *bridge, bool enabled)
5345 struct wifi_data *wifi;
5351 for (list = iface_list; list; list = list->next) {
5354 if (wifi->tethering) {
5355 wifi->tethering = false;
5357 connman_inet_remove_from_bridge(wifi->index,
5359 wifi->bridged = false;
5363 connman_technology_tethering_notify(technology, false);
5368 DBG("trying tethering for available devices");
5369 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5373 DBG("trying tethering for any device");
5374 err = enable_wifi_tethering(technology, bridge, identifier,
5381 static void regdom_callback(int result, const char *alpha2, void *user_data)
5385 if (!wifi_technology)
5391 connman_technology_regdom_notify(wifi_technology, alpha2);
5394 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5396 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5399 static struct connman_technology_driver tech_driver = {
5401 .type = CONNMAN_SERVICE_TYPE_WIFI,
5402 .probe = tech_probe,
5403 .remove = tech_remove,
5404 .set_tethering = tech_set_tethering,
5405 .set_regdom = tech_set_regdom,
5408 static int wifi_init(void)
5412 err = connman_network_driver_register(&network_driver);
5416 err = g_supplicant_register(&callbacks);
5418 connman_network_driver_unregister(&network_driver);
5422 err = connman_technology_driver_register(&tech_driver);
5424 g_supplicant_unregister(&callbacks);
5425 connman_network_driver_unregister(&network_driver);
5429 #if defined TIZEN_EXT
5430 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5435 static void wifi_exit(void)
5439 connman_technology_driver_unregister(&tech_driver);
5441 g_supplicant_unregister(&callbacks);
5443 connman_network_driver_unregister(&network_driver);
5445 #if defined TIZEN_EXT
5446 g_hash_table_unref(failed_bssids);
5450 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5451 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)