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;
168 GSupplicantScanParams *hidden_scan_params;
172 #if defined TIZEN_EXT_WIFI_MESH
174 struct wifi_mesh_info *mesh_info;
178 #if defined TIZEN_EXT
182 #define TIZEN_ASSOC_RETRY_COUNT 4
184 static gboolean wifi_first_scan = false;
185 static gboolean found_with_first_scan = false;
186 static gboolean is_wifi_notifier_registered = false;
187 static GHashTable *failed_bssids = NULL;
188 static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
192 static GList *iface_list = NULL;
194 static GList *pending_wifi_device = NULL;
195 static GList *p2p_iface_list = NULL;
196 bool wfd_service_registered = false;
198 static void start_autoscan(struct connman_device *device);
200 static int tech_set_tethering(struct connman_technology *technology,
201 const char *identifier, const char *passphrase,
202 const char *bridge, bool enabled);
204 #if defined TIZEN_EXT
205 #define NETCONFIG_SERVICE "net.netconfig"
206 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
207 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
209 struct enc_method_call_data {
210 DBusConnection *connection;
211 struct connman_network *network;
214 static struct enc_method_call_data encrypt_request_data;
216 static void encryption_request_reply(DBusPendingCall *call,
221 DBusMessageIter args;
223 struct connman_service *service;
224 gchar* encrypted_value = NULL;
225 struct connman_network *network = encrypt_request_data.network;
229 reply = dbus_pending_call_steal_reply(call);
231 dbus_error_init(&error);
232 if (dbus_set_error_from_message(&error, reply)) {
233 DBG("send_encryption_request() %s %s", error.name, error.message);
234 dbus_error_free(&error);
238 if (dbus_message_iter_init(reply, &args) == FALSE)
241 dbus_message_iter_get_basic(&args, &out_data);
243 encrypted_value = g_strdup((const gchar *)out_data);
244 service = connman_service_lookup_from_network(network);
247 DBG("encryption result: no service");
251 if (connman_service_get_favorite(service)) {
252 __connman_service_set_passphrase(service, encrypted_value);
253 __connman_service_save(service);
255 connman_network_set_string(network, "WiFi.Passphrase",
258 DBG("encryption result: succeeded");
261 dbus_message_unref(reply);
262 dbus_pending_call_unref(call);
263 dbus_connection_unref(encrypt_request_data.connection);
264 g_free(encrypted_value);
266 encrypt_request_data.connection = NULL;
267 encrypt_request_data.network = NULL;
270 static int send_encryption_request(const char *passphrase,
271 struct connman_network *network)
273 DBusConnection *connection = NULL;
274 DBusMessage *msg = NULL;
275 DBusPendingCall *call;
278 DBG("Invalid parameter");
282 connection = connman_dbus_get_connection();
284 DBG("dbus connection does not exist");
288 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
289 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
291 dbus_connection_unref(connection);
295 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
298 if (!dbus_connection_send_with_reply(connection, msg,
299 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
300 dbus_message_unref(msg);
301 dbus_connection_unref(connection);
306 dbus_message_unref(msg);
307 dbus_connection_unref(connection);
311 encrypt_request_data.connection = connection;
312 encrypt_request_data.network = network;
314 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
315 dbus_message_unref(msg);
321 static int p2p_tech_probe(struct connman_technology *technology)
323 p2p_technology = technology;
328 static void p2p_tech_remove(struct connman_technology *technology)
330 p2p_technology = NULL;
333 static struct connman_technology_driver p2p_tech_driver = {
335 .type = CONNMAN_SERVICE_TYPE_P2P,
336 .probe = p2p_tech_probe,
337 .remove = p2p_tech_remove,
340 static bool is_p2p_connecting(void)
344 for (list = iface_list; list; list = list->next) {
345 struct wifi_data *wifi = list->data;
347 if (wifi->p2p_connecting)
354 static void add_pending_wifi_device(struct wifi_data *wifi)
356 if (g_list_find(pending_wifi_device, wifi))
359 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
362 #if defined TIZEN_EXT_WIFI_MESH
363 struct wifi_mesh_info {
364 struct wifi_data *wifi;
365 GSupplicantInterface *interface;
366 struct connman_mesh *mesh;
373 struct mesh_change_peer_status_info {
375 enum connman_mesh_peer_status peer_status;
376 mesh_change_peer_status_cb_t callback;
380 static struct connman_technology_driver mesh_tech_driver = {
382 .type = CONNMAN_SERVICE_TYPE_MESH,
385 static void mesh_interface_create_callback(int result,
386 GSupplicantInterface *interface,
389 struct wifi_mesh_info *mesh_info = user_data;
390 struct wifi_data *wifi;
391 bool success = false;
393 DBG("result %d ifname %s, mesh_info %p", result,
394 g_supplicant_interface_get_ifname(interface),
397 if (result < 0 || !mesh_info)
400 wifi = mesh_info->wifi;
402 mesh_info->interface = interface;
403 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
404 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
405 DBG("Mesh Interface identifier %s", mesh_info->identifier);
406 wifi->mesh_interface = true;
407 wifi->mesh_info = mesh_info;
408 g_supplicant_interface_set_data(interface, wifi);
412 connman_mesh_notify_interface_create(success);
415 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
418 struct wifi_data *wifi;
419 struct wifi_mesh_info *mesh_info;
420 const char *wifi_ifname;
421 bool parent_found = false;
422 const char *driver = "nl80211";
424 for (list = iface_list; list; list = list->next) {
427 if (!g_supplicant_interface_has_mesh(wifi->interface))
430 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
434 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
441 DBG("Parent interface %s doesn't exist", parent_ifname);
445 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
449 mesh_info->wifi = wifi;
450 mesh_info->ifname = g_strdup(ifname);
451 mesh_info->parent_ifname = g_strdup(parent_ifname);
453 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
454 mesh_interface_create_callback, mesh_info);
458 static void mesh_interface_remove_callback(int result,
459 GSupplicantInterface *interface,
462 struct wifi_data *wifi = user_data;
463 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
464 bool success = false;
466 DBG("result %d mesh_info %p", result, mesh_info);
468 if (result < 0 || !mesh_info)
471 mesh_info->interface = NULL;
472 g_free(mesh_info->parent_ifname);
473 g_free(mesh_info->ifname);
474 g_free(mesh_info->identifier);
476 wifi->mesh_interface = false;
477 wifi->mesh_info = NULL;
481 connman_mesh_notify_interface_remove(success);
484 static int remove_mesh_interface(const char *ifname)
487 struct wifi_data *wifi;
488 struct wifi_mesh_info *mesh_info;
489 bool mesh_if_found = false;
492 for (list = iface_list; list; list = list->next) {
495 if (wifi->mesh_interface) {
496 mesh_if_found = true;
501 if (!mesh_if_found) {
502 DBG("Mesh interface %s doesn't exist", ifname);
506 mesh_info = wifi->mesh_info;
507 ret = g_supplicant_interface_remove(mesh_info->interface,
508 mesh_interface_remove_callback, wifi);
515 static void mesh_disconnect_callback(int result,
516 GSupplicantInterface *interface, void *user_data)
518 struct connman_mesh *mesh = user_data;
520 DBG("result %d interface %p mesh %p", result, interface, mesh);
523 static int mesh_peer_disconnect(struct connman_mesh *mesh)
526 struct wifi_data *wifi;
527 struct wifi_mesh_info *mesh_info;
528 bool mesh_if_found = false;
529 GSupplicantInterface *interface;
531 for (list = iface_list; list; list = list->next) {
534 if (wifi->mesh_interface) {
535 mesh_if_found = true;
540 if (!mesh_if_found) {
541 DBG("Mesh interface is not created");
545 mesh_info = wifi->mesh_info;
547 interface = mesh_info->interface;
548 return g_supplicant_interface_disconnect(interface,
549 mesh_disconnect_callback, mesh);
552 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
555 struct connman_mesh *mesh = user_data;
556 DBG("mesh %p result %d", mesh, result);
559 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
561 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
564 static GSupplicantSecurity mesh_network_security(const char *security)
566 if (g_str_equal(security, "none"))
567 return G_SUPPLICANT_SECURITY_NONE;
568 else if (g_str_equal(security, "sae"))
569 return G_SUPPLICANT_SECURITY_SAE;
571 return G_SUPPLICANT_SECURITY_UNKNOWN;
574 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
577 const char *security;
582 memset(ssid, 0, sizeof(*ssid));
583 ssid->mode = G_SUPPLICANT_MODE_MESH;
585 security = connman_mesh_get_security(mesh);
586 ssid->security = mesh_network_security(security);
588 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
589 ssid->passphrase = connman_mesh_get_passphrase(mesh);
591 ssid->freq = connman_mesh_get_frequency(mesh);
592 name = connman_mesh_get_name(mesh);
594 ssid->ssid_len = strlen(name);
595 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
596 memcpy(ssid->ssid, name, ssid->ssid_len);
601 static int mesh_peer_connect(struct connman_mesh *mesh)
604 struct wifi_data *wifi;
605 struct wifi_mesh_info *mesh_info;
606 bool mesh_if_found = false;
607 GSupplicantInterface *interface;
608 GSupplicantSSID *ssid;
610 for (list = iface_list; list; list = list->next) {
613 if (wifi->mesh_interface) {
614 mesh_if_found = true;
619 if (!mesh_if_found) {
620 DBG("Mesh interface is not created");
624 mesh_info = wifi->mesh_info;
626 interface = mesh_info->interface;
628 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
632 mesh_info->mesh = mesh;
634 mesh_ssid_init(ssid, mesh);
635 return g_supplicant_interface_connect(interface, ssid,
636 mesh_connect_callback, mesh);
639 static void mesh_peer_change_status_callback(int result,
640 GSupplicantInterface *interface,
643 struct mesh_change_peer_status_info *data = user_data;
645 DBG("result %d Peer Status %d", result, data->peer_status);
647 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
648 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
649 connman_mesh_remove_connected_peer(data->peer_address, 52);
653 data->callback(result, data->user_data);
655 g_free(data->peer_address);
660 static int mesh_change_peer_status(const char *peer_address,
661 enum connman_mesh_peer_status status,
662 mesh_change_peer_status_cb_t callback, void *user_data)
665 struct wifi_data *wifi;
666 struct wifi_mesh_info *mesh_info;
667 bool mesh_if_found = false;
668 GSupplicantInterface *interface;
669 struct mesh_change_peer_status_info *data;
672 for (list = iface_list; list; list = list->next) {
675 if (wifi->mesh_interface) {
676 mesh_if_found = true;
681 if (!mesh_if_found) {
682 DBG("Mesh interface is not created");
686 mesh_info = wifi->mesh_info;
688 interface = mesh_info->interface;
691 case CONNMAN_MESH_PEER_ADD:
692 method = "MeshPeerAdd";
694 case CONNMAN_MESH_PEER_REMOVE:
695 method = "MeshPeerRemove";
698 DBG("Invalid method");
702 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
704 DBG("Memory allocation failed");
708 data->peer_address = g_strdup(peer_address);
709 data->peer_status = status;
710 data->callback = callback;
711 data->user_data = user_data;
713 return g_supplicant_interface_mesh_peer_change_status(interface,
714 mesh_peer_change_status_callback, peer_address, method,
718 static struct connman_mesh_driver mesh_driver = {
719 .add_interface = add_mesh_interface,
720 .remove_interface = remove_mesh_interface,
721 .connect = mesh_peer_connect,
722 .disconnect = mesh_peer_disconnect,
723 .change_peer_status = mesh_change_peer_status,
726 static void mesh_support(GSupplicantInterface *interface)
730 if (!g_supplicant_interface_has_mesh(interface))
733 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
734 DBG("Could not register Mesh technology driver");
738 connman_mesh_driver_register(&mesh_driver);
741 static void check_mesh_technology(void)
743 bool mesh_exists = false;
746 for (list = iface_list; list; list = list->next) {
747 struct wifi_data *w = list->data;
750 g_supplicant_interface_has_mesh(w->interface))
755 connman_technology_driver_unregister(&mesh_tech_driver);
756 connman_mesh_driver_unregister(&mesh_driver);
760 static void mesh_group_started(GSupplicantInterface *interface)
762 struct wifi_data *wifi;
763 struct wifi_mesh_info *mesh_info;
764 struct connman_mesh *mesh;
765 const unsigned char *ssid;
766 unsigned int ssid_len;
769 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
770 memcpy(name, ssid, ssid_len);
771 name[ssid_len] = '\0';
772 DBG("name %s", name);
773 wifi = g_supplicant_interface_get_data(interface);
774 DBG("wifi %p", wifi);
779 mesh_info = wifi->mesh_info;
783 mesh = mesh_info->mesh;
787 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
790 static void mesh_group_removed(GSupplicantInterface *interface)
792 struct wifi_data *wifi;
793 struct wifi_mesh_info *mesh_info;
794 struct connman_mesh *mesh;
795 const unsigned char *ssid;
796 unsigned int ssid_len;
797 int disconnect_reason;
800 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
801 memcpy(name, ssid, ssid_len);
802 name[ssid_len] = '\0';
803 DBG("name %s", name);
805 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
806 DBG("Disconnect Reason %d", disconnect_reason);
808 wifi = g_supplicant_interface_get_data(interface);
809 DBG("wifi %p", wifi);
814 mesh_info = wifi->mesh_info;
818 mesh = connman_get_connected_mesh_from_name(name);
820 DBG("%s is not connected", name);
821 mesh = connman_get_connecting_mesh_from_name(name);
823 DBG("%s is not connecting", name);
828 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
829 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
832 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
834 const char *peer_address;
836 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
841 DBG("Peer %s connected", peer_address);
842 connman_mesh_add_connected_peer(peer_address);
845 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
847 const char *peer_address;
850 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
855 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
857 DBG("Peer %s disconnected with reason %d", peer_address, reason);
858 connman_mesh_remove_connected_peer(peer_address, reason);
862 static struct wifi_data *get_pending_wifi_data(const char *ifname)
866 for (list = pending_wifi_device; list; list = list->next) {
867 struct wifi_data *wifi;
868 const char *dev_name;
871 if (!wifi || !wifi->device)
874 dev_name = connman_device_get_string(wifi->device, "Interface");
875 if (!g_strcmp0(ifname, dev_name)) {
876 pending_wifi_device = g_list_delete_link(
877 pending_wifi_device, list);
885 static void remove_pending_wifi_device(struct wifi_data *wifi)
889 link = g_list_find(pending_wifi_device, wifi);
894 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
897 static void peer_cancel_timeout(struct wifi_data *wifi)
899 if (wifi->p2p_connection_timeout > 0)
900 g_source_remove(wifi->p2p_connection_timeout);
902 wifi->p2p_connection_timeout = 0;
903 wifi->p2p_connecting = false;
905 if (wifi->pending_peer) {
906 connman_peer_unref(wifi->pending_peer);
907 wifi->pending_peer = NULL;
911 static gboolean peer_connect_timeout(gpointer data)
913 struct wifi_data *wifi = data;
917 if (wifi->p2p_connecting) {
918 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
919 GSupplicantPeer *gs_peer =
920 g_supplicant_interface_peer_lookup(wifi->interface,
921 connman_peer_get_identifier(wifi->pending_peer));
923 if (g_supplicant_peer_has_requested_connection(gs_peer))
924 state = CONNMAN_PEER_STATE_IDLE;
926 connman_peer_set_state(wifi->pending_peer, state);
929 peer_cancel_timeout(wifi);
934 static void peer_connect_callback(int result, GSupplicantInterface *interface,
937 struct wifi_data *wifi = user_data;
938 struct connman_peer *peer = wifi->pending_peer;
940 DBG("peer %p - %d", peer, result);
946 peer_connect_timeout(wifi);
950 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
952 wifi->p2p_connection_timeout = g_timeout_add_seconds(
953 P2P_CONNECTION_TIMEOUT,
954 peer_connect_timeout, wifi);
957 static int peer_connect(struct connman_peer *peer,
958 enum connman_peer_wps_method wps_method,
961 struct connman_device *device = connman_peer_get_device(peer);
962 GSupplicantPeerParams *peer_params;
963 GSupplicantPeer *gs_peer;
964 struct wifi_data *wifi;
968 DBG("peer %p", peer);
973 wifi = connman_device_get_data(device);
974 if (!wifi || !wifi->interface)
977 if (wifi->p2p_connecting)
980 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
981 connman_peer_get_identifier(peer));
985 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
986 pin = g_supplicant_peer_is_wps_pin(gs_peer);
988 switch (wps_method) {
989 case CONNMAN_PEER_WPS_UNKNOWN:
990 if ((pbc && pin) || pin)
993 case CONNMAN_PEER_WPS_PBC:
998 case CONNMAN_PEER_WPS_PIN:
999 if (!pin || !wps_pin)
1004 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1008 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1010 peer_params->wps_pin = g_strdup(wps_pin);
1012 peer_params->master = connman_peer_service_is_master();
1014 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1015 peer_connect_callback, wifi);
1016 if (ret == -EINPROGRESS) {
1017 wifi->pending_peer = connman_peer_ref(peer);
1018 wifi->p2p_connecting = true;
1019 } else if (ret < 0) {
1020 g_free(peer_params->path);
1021 g_free(peer_params->wps_pin);
1022 g_free(peer_params);
1028 static int peer_disconnect(struct connman_peer *peer)
1030 struct connman_device *device = connman_peer_get_device(peer);
1031 GSupplicantPeerParams peer_params = {};
1032 GSupplicantPeer *gs_peer;
1033 struct wifi_data *wifi;
1036 DBG("peer %p", peer);
1041 wifi = connman_device_get_data(device);
1045 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1046 connman_peer_get_identifier(peer));
1050 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1052 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1054 g_free(peer_params.path);
1056 if (ret == -EINPROGRESS) {
1057 peer_cancel_timeout(wifi);
1058 wifi->p2p_device = false;
1064 struct peer_service_registration {
1065 peer_service_registration_cb_t callback;
1069 static bool is_service_wfd(const unsigned char *specs, int length)
1071 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1077 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1079 struct wifi_data *wifi = data;
1081 if (!wifi->interface ||
1082 !g_supplicant_interface_has_p2p(wifi->interface))
1085 if (!wifi->servicing) {
1086 g_supplicant_interface_p2p_listen(wifi->interface,
1087 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1093 static void register_wfd_service_cb(int result,
1094 GSupplicantInterface *iface, void *user_data)
1096 struct peer_service_registration *reg_data = user_data;
1101 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1103 if (reg_data && reg_data->callback) {
1104 reg_data->callback(result, reg_data->user_data);
1109 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1110 const unsigned char *spec,
1111 int spec_length, const unsigned char *query,
1112 int query_length, int version)
1114 GSupplicantP2PServiceParams *params;
1116 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1121 params->version = version;
1122 params->service = g_memdup(spec, spec_length);
1123 } else if (query_length > 0 && spec_length > 0) {
1124 params->query = g_memdup(query, query_length);
1125 params->query_length = query_length;
1127 params->response = g_memdup(spec, spec_length);
1128 params->response_length = spec_length;
1130 params->wfd_ies = g_memdup(spec, spec_length);
1131 params->wfd_ies_length = spec_length;
1137 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1142 g_free(params->service);
1143 g_free(params->query);
1144 g_free(params->response);
1145 g_free(params->wfd_ies);
1150 static int peer_register_wfd_service(const unsigned char *specification,
1151 int specification_length,
1152 peer_service_registration_cb_t callback,
1155 struct peer_service_registration *reg_data = NULL;
1156 static GSupplicantP2PServiceParams *params;
1161 if (wfd_service_registered)
1164 params = fill_in_peer_service_params(specification,
1165 specification_length, NULL, 0, 0);
1169 reg_data = g_try_malloc0(sizeof(*reg_data));
1175 reg_data->callback = callback;
1176 reg_data->user_data = user_data;
1178 ret = g_supplicant_set_widi_ies(params,
1179 register_wfd_service_cb, reg_data);
1180 if (ret < 0 && ret != -EINPROGRESS)
1183 wfd_service_registered = true;
1187 free_peer_service_params(params);
1193 static void register_peer_service_cb(int result,
1194 GSupplicantInterface *iface, void *user_data)
1196 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1197 struct peer_service_registration *reg_data = user_data;
1199 #if defined TIZEN_EXT
1207 apply_p2p_listen_on_iface(wifi, NULL);
1209 if (reg_data->callback)
1210 reg_data->callback(result, reg_data->user_data);
1215 static int peer_register_service(const unsigned char *specification,
1216 int specification_length,
1217 const unsigned char *query,
1218 int query_length, int version,
1219 peer_service_registration_cb_t callback,
1222 struct peer_service_registration *reg_data;
1223 GSupplicantP2PServiceParams *params;
1230 if (specification && !version && !query &&
1231 is_service_wfd(specification, specification_length)) {
1232 return peer_register_wfd_service(specification,
1233 specification_length, callback, user_data);
1236 reg_data = g_try_malloc0(sizeof(*reg_data));
1240 reg_data->callback = callback;
1241 reg_data->user_data = user_data;
1243 ret_f = -EOPNOTSUPP;
1245 for (list = iface_list; list; list = list->next) {
1246 struct wifi_data *wifi = list->data;
1247 GSupplicantInterface *iface = wifi->interface;
1249 if (!g_supplicant_interface_has_p2p(iface))
1252 params = fill_in_peer_service_params(specification,
1253 specification_length, query,
1254 query_length, version);
1261 ret_f = g_supplicant_interface_p2p_add_service(iface,
1262 register_peer_service_cb, params, reg_data);
1263 if (ret_f == 0 || ret_f == -EINPROGRESS)
1267 ret = g_supplicant_interface_p2p_add_service(iface,
1268 register_peer_service_cb, params, NULL);
1269 if (ret != 0 && ret != -EINPROGRESS)
1270 free_peer_service_params(params);
1273 if (ret_f != 0 && ret_f != -EINPROGRESS)
1279 static int peer_unregister_wfd_service(void)
1281 GSupplicantP2PServiceParams *params;
1284 if (!wfd_service_registered)
1287 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1291 wfd_service_registered = false;
1293 g_supplicant_set_widi_ies(params, NULL, NULL);
1295 for (list = iface_list; list; list = list->next) {
1296 struct wifi_data *wifi = list->data;
1298 if (!g_supplicant_interface_has_p2p(wifi->interface))
1302 if (!wifi->servicing || wifi->servicing < 0) {
1303 g_supplicant_interface_p2p_listen(wifi->interface,
1305 wifi->servicing = 0;
1312 static int peer_unregister_service(const unsigned char *specification,
1313 int specification_length,
1314 const unsigned char *query,
1315 int query_length, int version)
1317 GSupplicantP2PServiceParams *params;
1322 if (specification && !version && !query &&
1323 is_service_wfd(specification, specification_length)) {
1324 ret = peer_unregister_wfd_service();
1325 if (ret != 0 && ret != -EINPROGRESS)
1330 for (list = iface_list; list; list = list->next) {
1331 struct wifi_data *wifi = list->data;
1332 GSupplicantInterface *iface = wifi->interface;
1335 goto stop_listening;
1337 if (!g_supplicant_interface_has_p2p(iface))
1340 params = fill_in_peer_service_params(specification,
1341 specification_length, query,
1342 query_length, version);
1348 ret = g_supplicant_interface_p2p_del_service(iface, params);
1349 if (ret != 0 && ret != -EINPROGRESS)
1350 free_peer_service_params(params);
1353 if (!wifi->servicing || wifi->servicing < 0) {
1354 g_supplicant_interface_p2p_listen(iface, 0, 0);
1355 wifi->servicing = 0;
1362 static struct connman_peer_driver peer_driver = {
1363 .connect = peer_connect,
1364 .disconnect = peer_disconnect,
1365 .register_service = peer_register_service,
1366 .unregister_service = peer_unregister_service,
1369 static void handle_tethering(struct wifi_data *wifi)
1371 if (!wifi->tethering)
1380 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1382 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1385 wifi->bridged = true;
1388 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1390 struct connman_device *device = user_data;
1391 struct wifi_data *wifi = connman_device_get_data(device);
1396 DBG("index %d flags %d change %d", wifi->index, flags, change);
1398 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1400 DBG("interface up");
1402 DBG("interface down");
1405 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1406 if (flags & IFF_LOWER_UP) {
1409 handle_tethering(wifi);
1414 wifi->flags = flags;
1417 static int wifi_probe(struct connman_device *device)
1419 struct wifi_data *wifi;
1421 DBG("device %p", device);
1423 wifi = g_try_new0(struct wifi_data, 1);
1427 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1428 wifi->ap_supported = WIFI_AP_UNKNOWN;
1429 wifi->tethering_param = NULL;
1431 connman_device_set_data(device, wifi);
1432 wifi->device = connman_device_ref(device);
1434 wifi->index = connman_device_get_index(device);
1437 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1438 wifi_newlink, device);
1439 if (is_p2p_connecting())
1440 add_pending_wifi_device(wifi);
1442 iface_list = g_list_append(iface_list, wifi);
1447 static void remove_networks(struct connman_device *device,
1448 struct wifi_data *wifi)
1452 for (list = wifi->networks; list; list = list->next) {
1453 struct connman_network *network = list->data;
1455 connman_device_remove_network(device, network);
1456 connman_network_unref(network);
1459 g_slist_free(wifi->networks);
1460 wifi->networks = NULL;
1463 static void remove_peers(struct wifi_data *wifi)
1467 for (list = wifi->peers; list; list = list->next) {
1468 struct connman_peer *peer = list->data;
1470 connman_peer_unregister(peer);
1471 connman_peer_unref(peer);
1474 g_slist_free(wifi->peers);
1478 static void reset_autoscan(struct connman_device *device)
1480 struct wifi_data *wifi = connman_device_get_data(device);
1481 struct autoscan_params *autoscan;
1485 if (!wifi || !wifi->autoscan)
1488 autoscan = wifi->autoscan;
1490 if (autoscan->timeout == 0 && autoscan->interval == 0)
1493 g_source_remove(autoscan->timeout);
1495 autoscan->timeout = 0;
1496 autoscan->interval = 0;
1498 connman_device_unref(device);
1501 static void stop_autoscan(struct connman_device *device)
1503 const struct wifi_data *wifi = connman_device_get_data(device);
1505 if (!wifi || !wifi->autoscan)
1508 reset_autoscan(device);
1510 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1513 static void check_p2p_technology(void)
1515 bool p2p_exists = false;
1518 for (list = iface_list; list; list = list->next) {
1519 struct wifi_data *w = list->data;
1522 g_supplicant_interface_has_p2p(w->interface))
1527 connman_technology_driver_unregister(&p2p_tech_driver);
1528 connman_peer_driver_unregister(&peer_driver);
1532 static void wifi_remove(struct connman_device *device)
1534 struct wifi_data *wifi = connman_device_get_data(device);
1536 DBG("device %p wifi %p", device, wifi);
1541 stop_autoscan(device);
1543 if (wifi->p2p_device)
1544 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1546 iface_list = g_list_remove(iface_list, wifi);
1548 check_p2p_technology();
1549 #if defined TIZEN_EXT_WIFI_MESH
1550 check_mesh_technology();
1553 remove_pending_wifi_device(wifi);
1555 if (wifi->p2p_find_timeout) {
1556 g_source_remove(wifi->p2p_find_timeout);
1557 connman_device_unref(wifi->device);
1560 if (wifi->p2p_connection_timeout)
1561 g_source_remove(wifi->p2p_connection_timeout);
1563 #if defined TIZEN_EXT
1564 if (wifi->automaxspeed_timeout != 0) {
1565 g_source_remove(wifi->automaxspeed_timeout);
1566 wifi->automaxspeed_timeout = 0;
1570 remove_networks(device, wifi);
1573 connman_device_set_powered(device, false);
1574 connman_device_set_data(device, NULL);
1575 connman_device_unref(wifi->device);
1576 connman_rtnl_remove_watch(wifi->watch);
1578 g_supplicant_interface_set_data(wifi->interface, NULL);
1580 g_supplicant_interface_cancel(wifi->interface);
1582 if (wifi->scan_params)
1583 g_supplicant_free_scan_params(wifi->scan_params);
1584 #if defined TIZEN_EXT
1585 if (wifi->hidden_scan_params) {
1586 while (wifi->hidden_scan_params->ssids) {
1587 struct scan_ssid *ssid;
1588 ssid = wifi->hidden_scan_params->ssids->data;
1589 wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
1591 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1595 g_free(wifi->autoscan);
1596 g_free(wifi->identifier);
1600 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1604 for (iter = list; iter; iter = g_slist_next(iter)) {
1605 struct scan_ssid *scan_ssid = iter->data;
1607 if (ssid_len == scan_ssid->ssid_len &&
1608 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1615 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1616 int freq, GSupplicantScanParams *scan_data,
1617 int driver_max_scan_ssids, char *ssid_name)
1620 struct scan_ssid *scan_ssid;
1622 if ((driver_max_scan_ssids == 0 ||
1623 driver_max_scan_ssids > scan_data->num_ssids) &&
1624 (hex_ssid || raw_ssid)) {
1626 unsigned int j = 0, hex;
1629 size_t hex_ssid_len = strlen(hex_ssid);
1631 ssid = g_try_malloc0(hex_ssid_len / 2);
1635 for (i = 0; i < hex_ssid_len; i += 2) {
1636 sscanf(hex_ssid + i, "%02x", &hex);
1645 * If we have already added hidden AP to the list,
1646 * then do not do it again. This might happen if you have
1647 * used or are using multiple wifi cards, so in that case
1648 * you might have multiple service files for same AP.
1650 if (is_duplicate(scan_data->ssids, ssid, j)) {
1656 scan_ssid = g_try_new(struct scan_ssid, 1);
1663 memcpy(scan_ssid->ssid, ssid, j);
1664 scan_ssid->ssid_len = j;
1665 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1668 scan_data->num_ssids++;
1670 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1671 scan_data->num_ssids);
1678 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1680 if (!scan_data->freqs) {
1681 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1682 if (!scan_data->freqs) {
1683 g_slist_free_full(scan_data->ssids, g_free);
1687 scan_data->num_freqs = 1;
1688 scan_data->freqs[0] = freq;
1690 bool duplicate = false;
1692 /* Don't add duplicate entries */
1693 for (i = 0; i < scan_data->num_freqs; i++) {
1694 if (scan_data->freqs[i] == freq) {
1701 scan_data->num_freqs++;
1702 scan_data->freqs = g_try_realloc(scan_data->freqs,
1703 sizeof(uint16_t) * scan_data->num_freqs);
1704 if (!scan_data->freqs) {
1705 g_slist_free_full(scan_data->ssids, g_free);
1708 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1715 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1717 struct connman_config_entry **entries;
1723 int num_ssids = 0, add_param_failed = 0;
1725 services = connman_storage_get_services();
1726 for (i = 0; services && services[i]; i++) {
1727 if (strncmp(services[i], "wifi_", 5) != 0)
1730 keyfile = connman_storage_load_service(services[i]);
1734 value = g_key_file_get_boolean(keyfile,
1735 services[i], "Hidden", NULL);
1737 g_key_file_free(keyfile);
1741 value = g_key_file_get_boolean(keyfile,
1742 services[i], "Favorite", NULL);
1744 g_key_file_free(keyfile);
1748 #if defined TIZEN_EXT
1749 value = g_key_file_get_boolean(keyfile,
1750 services[i], "AutoConnect", NULL);
1752 g_key_file_free(keyfile);
1757 ssid = g_key_file_get_string(keyfile,
1758 services[i], "SSID", NULL);
1760 name = g_key_file_get_string(keyfile, services[i], "Name",
1763 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1771 g_key_file_free(keyfile);
1775 * Check if there are any hidden AP that needs to be provisioned.
1777 entries = connman_config_get_entries("wifi");
1778 for (i = 0; entries && entries[i]; i++) {
1781 if (!entries[i]->hidden)
1784 if (!entries[i]->ssid) {
1785 ssid = entries[i]->name;
1788 ssid = entries[i]->ssid;
1789 len = entries[i]->ssid_len;
1795 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1802 connman_config_free_entries(entries);
1804 if (add_param_failed > 0)
1805 DBG("Unable to scan %d out of %d SSIDs",
1806 add_param_failed, num_ssids);
1808 g_strfreev(services);
1813 static int get_hidden_connections_params(struct wifi_data *wifi,
1814 GSupplicantScanParams *scan_params)
1816 int driver_max_ssids, i;
1817 GSupplicantScanParams *orig_params;
1820 * Scan hidden networks so that we can autoconnect to them.
1821 * We will assume 1 as a default number of ssid to scan.
1823 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1825 if (driver_max_ssids == 0)
1826 driver_max_ssids = 1;
1828 DBG("max ssids %d", driver_max_ssids);
1830 #if defined TIZEN_EXT
1831 if (!wifi->hidden_scan_params) {
1832 wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1833 if (!wifi->hidden_scan_params)
1836 if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
1837 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1838 wifi->hidden_scan_params = NULL;
1844 orig_params = wifi->hidden_scan_params;
1846 if (!wifi->scan_params) {
1847 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1848 if (!wifi->scan_params)
1851 if (get_hidden_connections(wifi->scan_params) == 0) {
1852 g_supplicant_free_scan_params(wifi->scan_params);
1853 wifi->scan_params = NULL;
1859 orig_params = wifi->scan_params;
1862 /* Let's transfer driver_max_ssids params */
1863 for (i = 0; i < driver_max_ssids; i++) {
1864 struct scan_ssid *ssid;
1866 #if defined TIZEN_EXT
1867 if (!wifi->hidden_scan_params->ssids)
1869 if (!wifi->scan_params->ssids)
1873 ssid = orig_params->ssids->data;
1874 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1875 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1879 scan_params->num_ssids = i;
1880 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1882 scan_params->freqs = g_memdup(orig_params->freqs,
1883 sizeof(uint16_t) * orig_params->num_freqs);
1884 if (!scan_params->freqs)
1887 scan_params->num_freqs = orig_params->num_freqs;
1892 orig_params->num_ssids -= scan_params->num_ssids;
1894 return scan_params->num_ssids;
1897 g_slist_free_full(scan_params->ssids, g_free);
1898 #if defined TIZEN_EXT
1899 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1900 wifi->hidden_scan_params = NULL;
1902 g_supplicant_free_scan_params(wifi->scan_params);
1903 wifi->scan_params = NULL;
1909 static int throw_wifi_scan(struct connman_device *device,
1910 GSupplicantInterfaceCallback callback)
1912 struct wifi_data *wifi = connman_device_get_data(device);
1918 DBG("device %p %p", device, wifi->interface);
1920 if (wifi->tethering)
1922 #if defined TIZEN_EXT
1923 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1925 if (connman_device_get_scanning(device))
1929 connman_device_ref(device);
1931 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1934 connman_device_set_scanning(device,
1935 CONNMAN_SERVICE_TYPE_WIFI, true);
1937 connman_device_unref(device);
1942 static void hidden_free(struct hidden_params *hidden)
1947 if (hidden->scan_params)
1948 g_supplicant_free_scan_params(hidden->scan_params);
1949 g_free(hidden->identity);
1950 g_free(hidden->passphrase);
1951 g_free(hidden->security);
1955 #if defined TIZEN_EXT
1956 static void service_state_changed(struct connman_service *service,
1957 enum connman_service_state state);
1959 static int network_connect(struct connman_network *network);
1961 static struct connman_notifier notifier = {
1963 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1964 .service_state_changed = service_state_changed,
1967 static void service_state_changed(struct connman_service *service,
1968 enum connman_service_state state)
1970 enum connman_service_type type;
1972 type = connman_service_get_type(service);
1973 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1976 DBG("service %p state %d", service, state);
1979 case CONNMAN_SERVICE_STATE_READY:
1980 case CONNMAN_SERVICE_STATE_ONLINE:
1981 case CONNMAN_SERVICE_STATE_FAILURE:
1982 connman_notifier_unregister(¬ifier);
1983 is_wifi_notifier_registered = FALSE;
1985 __connman_device_request_scan(type);
1994 static void scan_callback(int result, GSupplicantInterface *interface,
1997 struct connman_device *device = user_data;
1998 struct wifi_data *wifi = connman_device_get_data(device);
2001 DBG("result %d wifi %p", result, wifi);
2004 if (wifi->hidden && !wifi->postpone_hidden) {
2005 connman_network_clear_hidden(wifi->hidden->user_data);
2006 hidden_free(wifi->hidden);
2007 wifi->hidden = NULL;
2010 if (wifi->scan_params) {
2011 g_supplicant_free_scan_params(wifi->scan_params);
2012 wifi->scan_params = NULL;
2015 #if defined TIZEN_EXT
2016 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2017 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2018 wifi->hidden_scan_params = NULL;
2024 connman_device_reset_scanning(device);
2026 /* User is connecting to a hidden AP, let's wait for finished event */
2027 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2028 GSupplicantScanParams *scan_params;
2031 wifi->postpone_hidden = false;
2032 scan_params = wifi->hidden->scan_params;
2033 wifi->hidden->scan_params = NULL;
2035 reset_autoscan(device);
2037 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2038 scan_callback, device);
2042 /* On error, let's recall scan_callback, which will cleanup */
2043 return scan_callback(ret, interface, user_data);
2046 #if defined TIZEN_EXT
2047 if (wifi && wifi->allow_full_scan) {
2049 DBG("Trigger Full Channel Scan");
2050 wifi->allow_full_scan = FALSE;
2052 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2053 scan_callback, device);
2057 /* On error, let's recall scan_callback, which will cleanup */
2058 return scan_callback(ret, interface, user_data);
2062 scanning = connman_device_get_scanning(device);
2064 connman_device_set_scanning(device,
2065 CONNMAN_SERVICE_TYPE_WIFI, false);
2067 if (result != -ENOLINK)
2068 #if defined TIZEN_EXT
2071 start_autoscan(device);
2074 * If we are here then we were scanning; however, if we are
2075 * also mid-flight disabling the interface, then wifi_disable
2076 * has already cleared the device scanning state and
2077 * unreferenced the device, obviating the need to do it here.
2081 connman_device_unref(device);
2083 #if defined TIZEN_EXT
2084 if (wifi && wifi->scan_pending_network && result != -EIO) {
2085 network_connect(wifi->scan_pending_network);
2086 wifi->scan_pending_network = NULL;
2087 connman_network_set_connecting(wifi->network);
2090 if (is_wifi_notifier_registered != true &&
2091 wifi_first_scan == true && found_with_first_scan == true) {
2092 wifi_first_scan = false;
2093 found_with_first_scan = false;
2095 connman_notifier_register(¬ifier);
2096 is_wifi_notifier_registered = true;
2101 static void scan_callback_hidden(int result,
2102 GSupplicantInterface *interface, void *user_data)
2104 struct connman_device *device = user_data;
2105 struct wifi_data *wifi = connman_device_get_data(device);
2106 GSupplicantScanParams *scan_params;
2109 DBG("result %d wifi %p", result, wifi);
2114 /* User is trying to connect to a hidden AP */
2115 if (wifi->hidden && wifi->postpone_hidden)
2118 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2122 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2123 ret = g_supplicant_interface_scan(wifi->interface,
2125 #if defined TIZEN_EXT
2128 scan_callback_hidden,
2136 g_supplicant_free_scan_params(scan_params);
2139 scan_callback(result, interface, user_data);
2142 static gboolean autoscan_timeout(gpointer data)
2144 struct connman_device *device = data;
2145 struct wifi_data *wifi = connman_device_get_data(device);
2146 struct autoscan_params *autoscan;
2152 autoscan = wifi->autoscan;
2154 if (autoscan->interval <= 0) {
2155 interval = autoscan->base;
2158 interval = autoscan->interval * autoscan->base;
2160 #if defined TIZEN_EXT
2161 if (autoscan->interval >= autoscan->limit)
2163 if (interval > autoscan->limit)
2165 interval = autoscan->limit;
2167 throw_wifi_scan(wifi->device, scan_callback_hidden);
2170 DBG("interval %d", interval);
2172 autoscan->interval = interval;
2174 autoscan->timeout = g_timeout_add_seconds(interval,
2175 autoscan_timeout, device);
2180 static void start_autoscan(struct connman_device *device)
2182 struct wifi_data *wifi = connman_device_get_data(device);
2183 struct autoscan_params *autoscan;
2190 if (wifi->p2p_device)
2193 if (wifi->connected)
2196 autoscan = wifi->autoscan;
2200 if (autoscan->timeout > 0 || autoscan->interval > 0)
2203 connman_device_ref(device);
2205 autoscan_timeout(device);
2208 static struct autoscan_params *parse_autoscan_params(const char *params)
2210 struct autoscan_params *autoscan;
2215 DBG("Emulating autoscan");
2217 list_params = g_strsplit(params, ":", 0);
2218 if (list_params == 0)
2221 if (g_strv_length(list_params) < 3) {
2222 g_strfreev(list_params);
2226 base = atoi(list_params[1]);
2227 limit = atoi(list_params[2]);
2229 g_strfreev(list_params);
2231 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2233 DBG("Could not allocate memory for autoscan");
2237 DBG("base %d - limit %d", base, limit);
2238 autoscan->base = base;
2239 autoscan->limit = limit;
2244 static void setup_autoscan(struct wifi_data *wifi)
2246 if (!wifi->autoscan)
2247 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2249 start_autoscan(wifi->device);
2252 static void finalize_interface_creation(struct wifi_data *wifi)
2254 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2256 if (!wifi->device) {
2257 connman_error("WiFi device not set");
2261 connman_device_set_powered(wifi->device, true);
2263 if (!connman_setting_get_bool("BackgroundScanning"))
2266 if (wifi->p2p_device)
2269 setup_autoscan(wifi);
2272 static void interface_create_callback(int result,
2273 GSupplicantInterface *interface,
2276 struct wifi_data *wifi = user_data;
2278 DBG("result %d ifname %s, wifi %p", result,
2279 g_supplicant_interface_get_ifname(interface),
2282 if (result < 0 || !wifi)
2285 wifi->interface = interface;
2286 g_supplicant_interface_set_data(interface, wifi);
2288 if (g_supplicant_interface_get_ready(interface)) {
2289 wifi->interface_ready = true;
2290 finalize_interface_creation(wifi);
2294 static int wifi_enable(struct connman_device *device)
2296 struct wifi_data *wifi = connman_device_get_data(device);
2299 const char *driver = connman_option_get_string("wifi");
2302 DBG("device %p %p", device, wifi);
2304 index = connman_device_get_index(device);
2305 if (!wifi || index < 0)
2308 if (is_p2p_connecting())
2309 return -EINPROGRESS;
2311 interface = connman_inet_ifname(index);
2312 ret = g_supplicant_interface_create(interface, driver, NULL,
2313 interface_create_callback,
2320 return -EINPROGRESS;
2323 static int wifi_disable(struct connman_device *device)
2325 struct wifi_data *wifi = connman_device_get_data(device);
2328 DBG("device %p wifi %p", device, wifi);
2333 wifi->connected = false;
2334 wifi->disconnecting = false;
2336 if (wifi->pending_network)
2337 wifi->pending_network = NULL;
2339 stop_autoscan(device);
2341 if (wifi->p2p_find_timeout) {
2342 g_source_remove(wifi->p2p_find_timeout);
2343 wifi->p2p_find_timeout = 0;
2344 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2345 connman_device_unref(wifi->device);
2348 #if defined TIZEN_EXT
2349 if (wifi->automaxspeed_timeout != 0) {
2350 g_source_remove(wifi->automaxspeed_timeout);
2351 wifi->automaxspeed_timeout = 0;
2355 /* In case of a user scan, device is still referenced */
2356 if (connman_device_get_scanning(device)) {
2357 connman_device_set_scanning(device,
2358 CONNMAN_SERVICE_TYPE_WIFI, false);
2359 connman_device_unref(wifi->device);
2362 remove_networks(device, wifi);
2365 #if defined TIZEN_EXT
2366 wifi->scan_pending_network = NULL;
2368 if (is_wifi_notifier_registered == true) {
2369 connman_notifier_unregister(¬ifier);
2370 is_wifi_notifier_registered = false;
2374 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2378 return -EINPROGRESS;
2381 struct last_connected {
2387 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
2389 GTimeVal *aval = (GTimeVal *)a;
2390 GTimeVal *bval = (GTimeVal *)b;
2392 /* Note that the sort order is descending */
2393 if (aval->tv_sec < bval->tv_sec)
2396 if (aval->tv_sec > bval->tv_sec)
2402 static void free_entry(gpointer data)
2404 struct last_connected *entry = data;
2406 g_free(entry->ssid);
2410 static int get_latest_connections(int max_ssids,
2411 GSupplicantScanParams *scan_data)
2413 GSequenceIter *iter;
2414 GSequence *latest_list;
2415 struct last_connected *entry;
2424 latest_list = g_sequence_new(free_entry);
2428 services = connman_storage_get_services();
2429 for (i = 0; services && services[i]; i++) {
2430 if (strncmp(services[i], "wifi_", 5) != 0)
2433 keyfile = connman_storage_load_service(services[i]);
2437 str = g_key_file_get_string(keyfile,
2438 services[i], "Favorite", NULL);
2439 if (!str || g_strcmp0(str, "true")) {
2441 g_key_file_free(keyfile);
2446 str = g_key_file_get_string(keyfile,
2447 services[i], "AutoConnect", NULL);
2448 if (!str || g_strcmp0(str, "true")) {
2450 g_key_file_free(keyfile);
2455 str = g_key_file_get_string(keyfile,
2456 services[i], "Modified", NULL);
2458 g_key_file_free(keyfile);
2461 g_time_val_from_iso8601(str, &modified);
2464 ssid = g_key_file_get_string(keyfile,
2465 services[i], "SSID", NULL);
2467 freq = g_key_file_get_integer(keyfile, services[i],
2470 entry = g_try_new(struct last_connected, 1);
2472 g_sequence_free(latest_list);
2473 g_key_file_free(keyfile);
2479 entry->modified = modified;
2482 g_sequence_insert_sorted(latest_list, entry,
2488 g_key_file_free(keyfile);
2491 g_strfreev(services);
2493 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2495 iter = g_sequence_get_begin_iter(latest_list);
2497 for (i = 0; i < num_ssids; i++) {
2498 entry = g_sequence_get(iter);
2500 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2501 entry->modified.tv_sec);
2503 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2504 max_ssids, entry->ssid);
2506 iter = g_sequence_iter_next(iter);
2509 g_sequence_free(latest_list);
2513 static int wifi_scan_simple(struct connman_device *device)
2515 reset_autoscan(device);
2517 return throw_wifi_scan(device, scan_callback_hidden);
2520 static gboolean p2p_find_stop(gpointer data)
2522 struct connman_device *device = data;
2523 struct wifi_data *wifi = connman_device_get_data(device);
2528 wifi->p2p_find_timeout = 0;
2530 g_supplicant_interface_p2p_stop_find(wifi->interface);
2533 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2535 connman_device_unref(device);
2536 reset_autoscan(device);
2541 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2544 struct connman_device *device = user_data;
2545 struct wifi_data *wifi = connman_device_get_data(device);
2547 DBG("result %d wifi %p", result, wifi);
2552 if (wifi->p2p_find_timeout) {
2553 g_source_remove(wifi->p2p_find_timeout);
2554 wifi->p2p_find_timeout = 0;
2560 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2561 p2p_find_stop, device);
2562 if (!wifi->p2p_find_timeout)
2567 p2p_find_stop(device);
2570 static int p2p_find(struct connman_device *device)
2572 struct wifi_data *wifi;
2577 if (!p2p_technology)
2580 wifi = connman_device_get_data(device);
2582 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2585 reset_autoscan(device);
2586 connman_device_ref(device);
2588 ret = g_supplicant_interface_p2p_find(wifi->interface,
2589 p2p_find_callback, device);
2591 connman_device_unref(device);
2592 start_autoscan(device);
2594 connman_device_set_scanning(device,
2595 CONNMAN_SERVICE_TYPE_P2P, true);
2601 #if defined TIZEN_EXT
2602 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2605 struct connman_device *device = user_data;
2606 struct wifi_data *wifi = connman_device_get_data(device);
2609 DBG("result %d wifi %p", result, wifi);
2611 if (wifi && wifi->scan_params) {
2612 g_supplicant_free_scan_params(wifi->scan_params);
2613 wifi->scan_params = NULL;
2616 scanning = connman_device_get_scanning(device);
2618 connman_device_set_scanning(device,
2619 CONNMAN_SERVICE_TYPE_WIFI, false);
2620 connman_device_unref(device);
2624 static int wifi_specific_scan(enum connman_service_type type,
2625 struct connman_device *device, int scan_type,
2626 GSList *specific_scan_list, void *user_data)
2628 GSList *list = NULL;
2630 struct wifi_data *wifi = connman_device_get_data(device);
2631 GSupplicantScanParams *scan_params = NULL;
2632 struct scan_ssid *scan_ssid = NULL;
2641 if (wifi->p2p_device)
2644 if (type == CONNMAN_SERVICE_TYPE_P2P)
2645 return p2p_find(device);
2647 if (wifi->tethering)
2650 scanning = connman_device_get_scanning(device);
2654 DBG("scan_type: %d", scan_type);
2655 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2656 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2658 DBG("Failed to allocate memory.");
2662 for (list = specific_scan_list; list; list = list->next) {
2663 ssid = (char *)list->data;
2664 int ssid_len = strlen(ssid);
2666 scan_ssid = g_try_new0(struct scan_ssid, 1);
2668 DBG("Failed to allocate memory.");
2669 g_supplicant_free_scan_params(scan_params);
2673 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2674 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2675 scan_ssid->ssid_len = ssid_len;
2676 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2679 scan_params->num_ssids = count;
2681 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2683 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2685 DBG("Failed to allocate memory.");
2689 guint num_freqs = g_slist_length(specific_scan_list);
2690 DBG("num_freqs: %d", num_freqs);
2692 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2693 if (!scan_params->freqs) {
2694 DBG("Failed to allocate memory.");
2695 g_free(scan_params);
2700 for (list = specific_scan_list; list; list = list->next) {
2701 freq = (int)list->data;
2703 scan_params->freqs[count] = freq;
2704 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2707 scan_params->num_freqs = count;
2709 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2710 int freq_count, ap_count;
2711 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2713 DBG("Failed to allocate memory.");
2717 guint size = g_slist_length(specific_scan_list);
2719 scan_params->freqs = g_try_new0(uint16_t, size/2);
2720 if (!scan_params->freqs) {
2721 DBG("Failed to allocate memory.");
2722 g_free(scan_params);
2726 ap_count = freq_count = 0;
2727 for (list = specific_scan_list; list; list = list->next) {
2728 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2729 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2730 int ssid_len = strlen(ssid);
2732 scan_ssid = g_try_new0(struct scan_ssid, 1);
2734 DBG("Failed to allocate memory.");
2735 g_supplicant_free_scan_params(scan_params);
2739 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2740 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2741 scan_ssid->ssid_len = ssid_len;
2742 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2746 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2747 scan_params->freqs[freq_count] = freq;
2748 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2752 scan_params->num_ssids = ap_count;
2753 scan_params->num_freqs = freq_count;
2755 DBG("Invalid scan");
2759 reset_autoscan(device);
2760 connman_device_ref(device);
2762 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2763 specific_scan_callback, device);
2766 connman_device_set_scanning(device,
2767 CONNMAN_SERVICE_TYPE_WIFI, true);
2769 g_supplicant_free_scan_params(scan_params);
2770 connman_device_unref(device);
2777 #if defined TIZEN_EXT_WIFI_MESH
2778 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2781 struct connman_device *device = user_data;
2782 struct wifi_data *wifi = connman_device_get_data(device);
2785 DBG("result %d wifi %p", result, wifi);
2787 scanning = connman_device_get_scanning(device);
2789 connman_device_set_scanning(device,
2790 CONNMAN_SERVICE_TYPE_MESH, false);
2793 connman_device_unref(device);
2796 static int mesh_scan(struct connman_device *device)
2798 struct wifi_data *wifi;
2799 struct wifi_mesh_info *mesh_info;
2804 wifi = connman_device_get_data(device);
2806 if (!wifi->mesh_interface)
2809 mesh_info = wifi->mesh_info;
2810 reset_autoscan(device);
2811 connman_device_ref(device);
2813 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2814 mesh_scan_callback, device);
2816 connman_device_unref(device);
2818 connman_device_set_scanning(device,
2819 CONNMAN_SERVICE_TYPE_MESH, true);
2824 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2827 struct connman_device *device = user_data;
2828 struct wifi_data *wifi = connman_device_get_data(device);
2830 DBG("result %d wifi %p", result, wifi);
2832 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2835 static int mesh_abort_scan(enum connman_service_type type,
2836 struct connman_device *device)
2838 struct wifi_data *wifi = connman_device_get_data(device);
2839 struct wifi_mesh_info *mesh_info;
2843 if (!wifi || !wifi->mesh_interface)
2846 if (type != CONNMAN_SERVICE_TYPE_MESH)
2849 mesh_info = wifi->mesh_info;
2851 scanning = connman_device_get_scanning(device);
2855 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2856 abort_scan_callback, device);
2861 static int mesh_specific_scan(enum connman_service_type type,
2862 struct connman_device *device, const char *ssid,
2863 unsigned int freq, void *user_data)
2865 struct wifi_data *wifi = connman_device_get_data(device);
2866 GSupplicantScanParams *scan_params = NULL;
2867 struct wifi_mesh_info *mesh_info;
2868 struct scan_ssid *scan_ssid;
2872 if (!wifi || !wifi->mesh_interface)
2875 if (type != CONNMAN_SERVICE_TYPE_MESH)
2878 if (wifi->p2p_device)
2881 mesh_info = wifi->mesh_info;
2883 scanning = connman_device_get_scanning(device);
2887 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2891 scan_ssid = g_try_new(struct scan_ssid, 1);
2893 g_free(scan_params);
2897 scan_ssid->ssid_len = strlen(ssid);
2898 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2899 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2900 scan_params->num_ssids = 1;
2902 scan_params->freqs = g_try_new(uint16_t, 1);
2903 if (!scan_params->freqs) {
2904 g_slist_free_full(scan_params->ssids, g_free);
2905 g_free(scan_params);
2909 scan_params->freqs[0] = freq;
2910 scan_params->num_freqs = 1;
2912 reset_autoscan(device);
2913 connman_device_ref(device);
2915 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2916 mesh_scan_callback, device);
2919 connman_device_set_scanning(device,
2920 CONNMAN_SERVICE_TYPE_MESH, true);
2922 g_supplicant_free_scan_params(scan_params);
2923 connman_device_unref(device);
2931 * Note that the hidden scan is only used when connecting to this specific
2932 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2934 static int wifi_scan(enum connman_service_type type,
2935 struct connman_device *device,
2936 const char *ssid, unsigned int ssid_len,
2937 const char *identity, const char* passphrase,
2938 const char *security, void *user_data)
2940 struct wifi_data *wifi = connman_device_get_data(device);
2941 GSupplicantScanParams *scan_params = NULL;
2942 struct scan_ssid *scan_ssid;
2943 struct hidden_params *hidden;
2945 int driver_max_ssids = 0;
2952 if (wifi->p2p_device)
2955 if (wifi->tethering)
2958 if (type == CONNMAN_SERVICE_TYPE_P2P)
2959 return p2p_find(device);
2961 #if defined TIZEN_EXT_WIFI_MESH
2962 if (type == CONNMAN_SERVICE_TYPE_MESH)
2963 return mesh_scan(device);
2966 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2968 scanning = connman_device_get_scanning(device);
2970 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2974 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2976 DBG("max ssids %d", driver_max_ssids);
2977 if (driver_max_ssids == 0)
2978 return wifi_scan_simple(device);
2982 if (scanning && wifi->hidden && wifi->postpone_hidden)
2988 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2993 scan_ssid = g_try_new(struct scan_ssid, 1);
2995 g_free(scan_params);
2999 memcpy(scan_ssid->ssid, ssid, ssid_len);
3000 scan_ssid->ssid_len = ssid_len;
3001 scan_params->ssids = g_slist_prepend(scan_params->ssids,
3003 scan_params->num_ssids = 1;
3005 hidden = g_try_new0(struct hidden_params, 1);
3007 g_supplicant_free_scan_params(scan_params);
3012 hidden_free(wifi->hidden);
3013 wifi->hidden = NULL;
3016 memcpy(hidden->ssid, ssid, ssid_len);
3017 hidden->ssid_len = ssid_len;
3018 hidden->identity = g_strdup(identity);
3019 hidden->passphrase = g_strdup(passphrase);
3020 hidden->security = g_strdup(security);
3021 hidden->user_data = user_data;
3022 wifi->hidden = hidden;
3025 /* Let's keep this active scan for later,
3026 * when current scan will be over. */
3027 wifi->postpone_hidden = TRUE;
3028 hidden->scan_params = scan_params;
3032 } else if (wifi->connected) {
3033 g_supplicant_free_scan_params(scan_params);
3034 return wifi_scan_simple(device);
3036 ret = get_latest_connections(driver_max_ssids, scan_params);
3038 g_supplicant_free_scan_params(scan_params);
3039 return wifi_scan_simple(device);
3043 connman_device_ref(device);
3045 reset_autoscan(device);
3047 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3048 scan_callback, device);
3051 connman_device_set_scanning(device,
3052 CONNMAN_SERVICE_TYPE_WIFI, true);
3053 #if defined TIZEN_EXT
3054 /*To allow the Full Scan after ssid based scan, set the flag here
3055 It is required because Tizen does not use the ConnMan specific
3056 backgroung Scan feature.Tizen has added the BG Scan feature in
3057 net-config. To sync with up ConnMan, we need to issue the Full Scan
3058 after SSID specific scan.*/
3059 wifi->allow_full_scan = TRUE;
3062 g_supplicant_free_scan_params(scan_params);
3063 connman_device_unref(device);
3066 hidden_free(wifi->hidden);
3067 wifi->hidden = NULL;
3074 static void wifi_regdom_callback(int result,
3078 struct connman_device *device = user_data;
3080 connman_device_regdom_notify(device, result, alpha2);
3082 connman_device_unref(device);
3085 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3087 struct wifi_data *wifi = connman_device_get_data(device);
3093 connman_device_ref(device);
3095 ret = g_supplicant_interface_set_country(wifi->interface,
3096 wifi_regdom_callback,
3099 connman_device_unref(device);
3104 static struct connman_device_driver wifi_ng_driver = {
3106 .type = CONNMAN_DEVICE_TYPE_WIFI,
3107 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3108 .probe = wifi_probe,
3109 .remove = wifi_remove,
3110 .enable = wifi_enable,
3111 .disable = wifi_disable,
3113 .set_regdom = wifi_set_regdom,
3114 #if defined TIZEN_EXT
3115 .specific_scan = wifi_specific_scan,
3117 #if defined TIZEN_EXT_WIFI_MESH
3118 .abort_scan = mesh_abort_scan,
3119 .mesh_specific_scan = mesh_specific_scan,
3123 static void system_ready(void)
3127 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3128 connman_error("Failed to register WiFi driver");
3131 static void system_killed(void)
3135 connman_device_driver_unregister(&wifi_ng_driver);
3138 static int network_probe(struct connman_network *network)
3140 DBG("network %p", network);
3145 static void network_remove(struct connman_network *network)
3147 struct connman_device *device = connman_network_get_device(network);
3148 struct wifi_data *wifi;
3150 DBG("network %p", network);
3152 wifi = connman_device_get_data(device);
3156 if (wifi->network != network)
3159 wifi->network = NULL;
3161 #if defined TIZEN_EXT
3162 wifi->disconnecting = false;
3164 if (wifi->pending_network == network)
3165 wifi->pending_network = NULL;
3167 if (wifi->scan_pending_network == network)
3168 wifi->scan_pending_network = NULL;
3172 static void connect_callback(int result, GSupplicantInterface *interface,
3175 #if defined TIZEN_EXT
3177 struct wifi_data *wifi;
3179 struct connman_network *network = user_data;
3181 DBG("network %p result %d", network, result);
3183 #if defined TIZEN_EXT
3184 set_connman_bssid(RESET_BSSID, NULL);
3186 for (list = iface_list; list; list = list->next) {
3189 if (wifi && wifi->network == network)
3193 /* wifi_data may be invalid because wifi is already disabled */
3198 if (result == -ENOKEY) {
3199 connman_network_set_error(network,
3200 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3201 } else if (result < 0) {
3202 connman_network_set_error(network,
3203 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3206 connman_network_unref(network);
3209 static GSupplicantSecurity network_security(const char *security)
3211 if (g_str_equal(security, "none"))
3212 return G_SUPPLICANT_SECURITY_NONE;
3213 else if (g_str_equal(security, "wep"))
3214 return G_SUPPLICANT_SECURITY_WEP;
3215 else if (g_str_equal(security, "psk"))
3216 return G_SUPPLICANT_SECURITY_PSK;
3217 else if (g_str_equal(security, "wpa"))
3218 return G_SUPPLICANT_SECURITY_PSK;
3219 else if (g_str_equal(security, "rsn"))
3220 return G_SUPPLICANT_SECURITY_PSK;
3221 else if (g_str_equal(security, "ieee8021x"))
3222 return G_SUPPLICANT_SECURITY_IEEE8021X;
3223 #if defined TIZEN_EXT
3224 else if (g_str_equal(security, "ft_psk") == TRUE)
3225 return G_SUPPLICANT_SECURITY_FT_PSK;
3226 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3227 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3228 else if (g_str_equal(security, "sae"))
3229 return G_SUPPLICANT_SECURITY_SAE;
3232 return G_SUPPLICANT_SECURITY_UNKNOWN;
3235 #if defined TIZEN_EXT
3236 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3238 if (security == NULL)
3239 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3241 if (g_str_equal(security, "FT") == TRUE)
3242 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3243 else if (g_str_equal(security, "CCKM") == TRUE)
3244 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3246 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3250 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3252 const char *security;
3253 #if defined TIZEN_EXT
3254 const void *ssid_data;
3257 memset(ssid, 0, sizeof(*ssid));
3258 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3259 #if defined TIZEN_EXT
3260 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3262 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3267 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3269 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3272 ssid->scan_ssid = 1;
3273 security = connman_network_get_string(network, "WiFi.Security");
3274 ssid->security = network_security(security);
3275 #if defined TIZEN_EXT
3276 ssid->ieee80211w = 1;
3278 ssid->passphrase = connman_network_get_string(network,
3280 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3283 * If our private key password is unset,
3284 * we use the supplied passphrase. That is needed
3285 * for PEAP where 2 passphrases (identity and client
3286 * cert may have to be provided.
3288 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3289 connman_network_set_string(network,
3290 "WiFi.PrivateKeyPassphrase",
3292 /* We must have an identity for both PEAP and TLS */
3293 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3295 /* Use agent provided identity as a fallback */
3296 if (!ssid->identity || strlen(ssid->identity) == 0)
3297 ssid->identity = connman_network_get_string(network,
3298 "WiFi.AgentIdentity");
3300 ssid->anonymous_identity = connman_network_get_string(network,
3301 "WiFi.AnonymousIdentity");
3302 ssid->ca_cert_path = connman_network_get_string(network,
3304 ssid->subject_match = connman_network_get_string(network,
3305 "WiFi.SubjectMatch");
3306 ssid->altsubject_match = connman_network_get_string(network,
3307 "WiFi.AltSubjectMatch");
3308 ssid->domain_suffix_match = connman_network_get_string(network,
3309 "WiFi.DomainSuffixMatch");
3310 ssid->domain_match = connman_network_get_string(network,
3311 "WiFi.DomainMatch");
3312 ssid->client_cert_path = connman_network_get_string(network,
3313 "WiFi.ClientCertFile");
3314 ssid->private_key_path = connman_network_get_string(network,
3315 "WiFi.PrivateKeyFile");
3316 ssid->private_key_passphrase = connman_network_get_string(network,
3317 "WiFi.PrivateKeyPassphrase");
3318 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3320 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3321 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3323 #if defined TIZEN_EXT
3324 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3325 ssid->bssid_for_connect_len = 6;
3326 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3327 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3328 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3329 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3330 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3332 ssid->freq = connman_network_get_frequency(network);
3335 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3336 if (bssid_list && g_slist_length(bssid_list) > 1) {
3338 /* If there are more than one bssid,
3339 * the user-specified bssid is tried only once at the beginning.
3340 * After that, the bssids in the list are tried in order.
3342 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3343 set_connman_bssid(RESET_BSSID, NULL);
3348 char buff[MAC_ADDRESS_LENGTH];
3349 for (list = bssid_list; list; list = list->next) {
3350 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3352 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3353 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3354 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3355 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3357 gchar *curr_bssid = g_strdup((const gchar *)buff);
3359 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3360 DBG("bssid match, try next bssid");
3364 g_hash_table_add(failed_bssids, curr_bssid);
3366 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3367 ssid->bssid = buff_bssid;
3368 ssid->freq = (unsigned int)bssids->frequency;
3374 ssid->bssid = connman_network_get_bssid(network);
3375 g_hash_table_remove_all(failed_bssids);
3378 ssid->bssid = connman_network_get_bssid(network);
3381 ssid->eap_keymgmt = network_eap_keymgmt(
3382 connman_network_get_string(network, "WiFi.KeymgmtType"));
3383 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3385 if(g_strcmp0(ssid->eap, "fast") == 0)
3386 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3389 if (connman_setting_get_bool("BackgroundScanning"))
3390 ssid->bgscan = BGSCAN_DEFAULT;
3393 static int network_connect(struct connman_network *network)
3395 struct connman_device *device = connman_network_get_device(network);
3396 struct wifi_data *wifi;
3397 GSupplicantInterface *interface;
3398 GSupplicantSSID *ssid;
3400 DBG("network %p", network);
3405 wifi = connman_device_get_data(device);
3409 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3413 interface = wifi->interface;
3415 ssid_init(ssid, network);
3417 if (wifi->disconnecting) {
3418 wifi->pending_network = network;
3419 #if defined TIZEN_EXT
3424 wifi->network = connman_network_ref(network);
3426 #if defined TIZEN_EXT
3427 wifi->scan_pending_network = NULL;
3430 return g_supplicant_interface_connect(interface, ssid,
3431 connect_callback, network);
3434 return -EINPROGRESS;
3437 static void disconnect_callback(int result, GSupplicantInterface *interface,
3440 #if defined TIZEN_EXT
3442 struct wifi_data *wifi;
3443 struct connman_network *network = user_data;
3445 DBG("network %p result %d", network, result);
3447 for (list = iface_list; list; list = list->next) {
3450 if (wifi->network == NULL && wifi->disconnecting == true)
3451 wifi->disconnecting = false;
3453 if (wifi->network == network)
3457 /* wifi_data may be invalid because wifi is already disabled */
3462 struct wifi_data *wifi = user_data;
3465 DBG("result %d supplicant interface %p wifi %p",
3466 result, interface, wifi);
3468 if (result == -ECONNABORTED) {
3469 DBG("wifi interface no longer available");
3473 if (wifi->network) {
3474 connman_network_set_connected(wifi->network, false);
3475 wifi->network = NULL;
3478 wifi->disconnecting = false;
3479 wifi->connected = false;
3481 if (wifi->pending_network) {
3482 network_connect(wifi->pending_network);
3483 wifi->pending_network = NULL;
3486 start_autoscan(wifi->device);
3489 static int network_disconnect(struct connman_network *network)
3491 struct connman_device *device = connman_network_get_device(network);
3492 struct wifi_data *wifi;
3494 #if defined TIZEN_EXT
3495 struct connman_service *service;
3498 DBG("network %p", network);
3500 wifi = connman_device_get_data(device);
3501 if (!wifi || !wifi->interface)
3504 #if defined TIZEN_EXT
3505 if (connman_network_get_associating(network) == true) {
3506 connman_network_clear_associating(network);
3507 connman_network_set_bool(network, "WiFi.UseWPS", false);
3509 service = connman_service_lookup_from_network(network);
3511 if (service != NULL &&
3512 (__connman_service_is_connected_state(service,
3513 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3514 __connman_service_is_connected_state(service,
3515 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3516 (connman_service_get_favorite(service) == false))
3517 __connman_service_set_passphrase(service, NULL);
3520 if (wifi->pending_network == network)
3521 wifi->pending_network = NULL;
3523 if (wifi->scan_pending_network == network)
3524 wifi->scan_pending_network = NULL;
3527 connman_network_set_associating(network, false);
3529 if (wifi->disconnecting)
3532 wifi->disconnecting = true;
3534 #if defined TIZEN_EXT
3535 err = g_supplicant_interface_disconnect(wifi->interface,
3536 disconnect_callback, network);
3538 err = g_supplicant_interface_disconnect(wifi->interface,
3539 disconnect_callback, wifi);
3543 wifi->disconnecting = false;
3548 #if defined TIZEN_EXT
3549 static void set_connection_mode(struct connman_network *network,
3552 ieee80211_modes_e phy_mode;
3553 connection_mode_e conn_mode;
3555 phy_mode = connman_network_get_phy_mode(network);
3557 case IEEE80211_MODE_B:
3558 if (linkspeed > 0 && linkspeed <= 11)
3559 conn_mode = CONNECTION_MODE_IEEE80211B;
3561 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3564 case IEEE80211_MODE_BG:
3565 if (linkspeed > 0 && linkspeed <= 11)
3566 conn_mode = CONNECTION_MODE_IEEE80211B;
3567 else if (linkspeed > 11 && linkspeed <= 54)
3568 conn_mode = CONNECTION_MODE_IEEE80211G;
3570 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3573 case IEEE80211_MODE_BGN:
3574 if (linkspeed > 0 && linkspeed <= 11)
3575 conn_mode = CONNECTION_MODE_IEEE80211B;
3576 else if (linkspeed > 11 && linkspeed <= 54)
3577 conn_mode = CONNECTION_MODE_IEEE80211G;
3578 else if (linkspeed > 54 && linkspeed <= 450)
3579 conn_mode = CONNECTION_MODE_IEEE80211N;
3581 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3584 case IEEE80211_MODE_A:
3585 if (linkspeed > 0 && linkspeed <= 54)
3586 conn_mode = CONNECTION_MODE_IEEE80211A;
3588 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3591 case IEEE80211_MODE_AN:
3592 if (linkspeed > 0 && linkspeed <= 54)
3593 conn_mode = CONNECTION_MODE_IEEE80211A;
3594 else if (linkspeed > 54 && linkspeed <= 450)
3595 conn_mode = CONNECTION_MODE_IEEE80211N;
3597 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3600 case IEEE80211_MODE_ANAC:
3601 if (linkspeed > 0 && linkspeed <= 54)
3602 conn_mode = CONNECTION_MODE_IEEE80211A;
3603 else if (linkspeed > 54 && linkspeed <= 450)
3604 conn_mode = CONNECTION_MODE_IEEE80211N;
3605 else if (linkspeed > 450 && linkspeed <= 1300)
3606 conn_mode = CONNECTION_MODE_IEEE80211AC;
3608 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3612 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3616 DBG("connection mode(%d)", conn_mode);
3617 connman_network_set_connection_mode(network, conn_mode);
3620 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3622 struct connman_network *network = user_data;
3625 DBG("Failed to get maxspeed from signalpoll !");
3629 DBG("maxspeed = %d", maxspeed);
3631 connman_network_set_maxspeed(network, maxspeed);
3632 set_connection_mode(network, maxspeed);
3636 static int network_signalpoll(struct wifi_data *wifi)
3638 GSupplicantInterface *interface;
3639 struct connman_network *network;
3641 if (!wifi || !wifi->network)
3644 interface = wifi->interface;
3645 network = wifi->network;
3647 DBG("network %p", network);
3649 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3652 static gboolean autosignalpoll_timeout(gpointer data)
3654 struct wifi_data *wifi = data;
3656 if (!wifi || !wifi->automaxspeed_timeout) {
3657 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3661 int ret = network_signalpoll(wifi);
3663 DBG("Fail to get max speed !!");
3664 wifi->automaxspeed_timeout = 0;
3672 static struct connman_network_driver network_driver = {
3674 .type = CONNMAN_NETWORK_TYPE_WIFI,
3675 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3676 .probe = network_probe,
3677 .remove = network_remove,
3678 .connect = network_connect,
3679 .disconnect = network_disconnect,
3682 static void interface_added(GSupplicantInterface *interface)
3684 const char *ifname = g_supplicant_interface_get_ifname(interface);
3685 const char *driver = g_supplicant_interface_get_driver(interface);
3686 #if defined TIZEN_EXT
3687 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3690 struct wifi_data *wifi;
3692 wifi = g_supplicant_interface_get_data(interface);
3694 wifi = get_pending_wifi_data(ifname);
3698 wifi->interface = interface;
3699 g_supplicant_interface_set_data(interface, wifi);
3700 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3701 wifi->p2p_device = true;
3704 DBG("ifname %s driver %s wifi %p tethering %d",
3705 ifname, driver, wifi, wifi->tethering);
3707 if (!wifi->device) {
3708 connman_error("WiFi device not set");
3712 connman_device_set_powered(wifi->device, true);
3713 #if defined TIZEN_EXT
3714 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3715 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3716 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3717 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3721 static bool is_idle(struct wifi_data *wifi)
3723 DBG("state %d", wifi->state);
3725 switch (wifi->state) {
3726 case G_SUPPLICANT_STATE_UNKNOWN:
3727 case G_SUPPLICANT_STATE_DISABLED:
3728 case G_SUPPLICANT_STATE_DISCONNECTED:
3729 case G_SUPPLICANT_STATE_INACTIVE:
3730 case G_SUPPLICANT_STATE_SCANNING:
3733 case G_SUPPLICANT_STATE_AUTHENTICATING:
3734 case G_SUPPLICANT_STATE_ASSOCIATING:
3735 case G_SUPPLICANT_STATE_ASSOCIATED:
3736 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3737 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3738 case G_SUPPLICANT_STATE_COMPLETED:
3745 static bool is_idle_wps(GSupplicantInterface *interface,
3746 struct wifi_data *wifi)
3748 /* First, let's check if WPS processing did not went wrong */
3749 if (g_supplicant_interface_get_wps_state(interface) ==
3750 G_SUPPLICANT_WPS_STATE_FAIL)
3753 /* Unlike normal connection, being associated while processing wps
3754 * actually means that we are idling. */
3755 switch (wifi->state) {
3756 case G_SUPPLICANT_STATE_UNKNOWN:
3757 case G_SUPPLICANT_STATE_DISABLED:
3758 case G_SUPPLICANT_STATE_DISCONNECTED:
3759 case G_SUPPLICANT_STATE_INACTIVE:
3760 case G_SUPPLICANT_STATE_SCANNING:
3761 case G_SUPPLICANT_STATE_ASSOCIATED:
3763 case G_SUPPLICANT_STATE_AUTHENTICATING:
3764 case G_SUPPLICANT_STATE_ASSOCIATING:
3765 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3766 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3767 case G_SUPPLICANT_STATE_COMPLETED:
3774 static bool handle_wps_completion(GSupplicantInterface *interface,
3775 struct connman_network *network,
3776 struct connman_device *device,
3777 struct wifi_data *wifi)
3781 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3783 const unsigned char *ssid, *wps_ssid;
3784 unsigned int ssid_len, wps_ssid_len;
3785 const char *wps_key;
3787 /* Checking if we got associated with requested
3789 ssid = connman_network_get_blob(network, "WiFi.SSID",
3792 wps_ssid = g_supplicant_interface_get_wps_ssid(
3793 interface, &wps_ssid_len);
3795 if (!wps_ssid || wps_ssid_len != ssid_len ||
3796 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3797 connman_network_set_associating(network, false);
3798 #if defined TIZEN_EXT
3799 g_supplicant_interface_disconnect(wifi->interface,
3800 disconnect_callback, wifi->network);
3802 connman_network_set_bool(network, "WiFi.UseWPS", false);
3803 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3805 g_supplicant_interface_disconnect(wifi->interface,
3806 disconnect_callback, wifi);
3811 wps_key = g_supplicant_interface_get_wps_key(interface);
3812 #if defined TIZEN_EXT
3813 /* Check the passphrase and encrypt it
3816 gchar *passphrase = g_strdup(wps_key);
3818 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3820 if (check_passphrase_ext(network, passphrase) < 0) {
3821 DBG("[WPS] Invalid passphrase");
3826 ret = send_encryption_request(passphrase, network);
3831 DBG("[WPS] Encryption request succeeded");
3833 DBG("[WPS] Encryption request failed %d", ret);
3836 connman_network_set_string(network, "WiFi.Passphrase",
3839 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3846 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3847 struct wifi_data *wifi)
3849 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3850 #if defined TIZEN_EXT
3851 wifi->assoc_code > 0 &&
3853 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3855 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3856 wifi->load_shaping_retries ++;
3859 wifi->load_shaping_retries = 0;
3863 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3864 struct connman_network *network,
3865 struct wifi_data *wifi)
3867 #if defined TIZEN_EXT
3868 const char *security;
3869 struct connman_service *service;
3871 if (wifi->connected)
3874 security = connman_network_get_string(network, "WiFi.Security");
3876 if (security && g_str_equal(security, "ieee8021x") == true &&
3877 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3879 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3884 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3887 struct connman_service *service;
3889 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3892 if (wifi->connected)
3896 service = connman_service_lookup_from_network(network);
3902 if (connman_service_get_favorite(service)) {
3903 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3908 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3913 #if defined TIZEN_EXT
3914 static bool handle_wifi_assoc_retry(struct connman_network *network,
3915 struct wifi_data *wifi)
3917 const char *security;
3919 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3920 connman_network_get_connecting(network) != true) {
3921 wifi->assoc_retry_count = 0;
3925 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3926 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3927 wifi->assoc_retry_count = 0;
3931 security = connman_network_get_string(network, "WiFi.Security");
3932 if (security && g_str_equal(security, "ieee8021x") == true &&
3933 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3934 wifi->assoc_retry_count = 0;
3938 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3939 wifi->assoc_retry_count = 0;
3941 /* Honestly it's not an invalid-key error,
3942 * however QA team recommends that the invalid-key error
3943 * might be better to display for user experience.
3945 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3954 static void interface_state(GSupplicantInterface *interface)
3956 struct connman_network *network;
3957 struct connman_device *device;
3958 struct wifi_data *wifi;
3959 GSupplicantState state = g_supplicant_interface_get_state(interface);
3963 wifi = g_supplicant_interface_get_data(interface);
3965 DBG("wifi %p interface state %d", wifi, state);
3970 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3971 if (wifi->tethering_param) {
3972 g_free(wifi->tethering_param->ssid);
3973 g_free(wifi->tethering_param);
3974 wifi->tethering_param = NULL;
3978 device = wifi->device;
3982 if (g_supplicant_interface_get_ready(interface) &&
3983 !wifi->interface_ready) {
3984 wifi->interface_ready = true;
3985 finalize_interface_creation(wifi);
3988 network = wifi->network;
3993 case G_SUPPLICANT_STATE_SCANNING:
3994 if (wifi->connected)
3995 connman_network_set_connected(network, false);
3999 case G_SUPPLICANT_STATE_AUTHENTICATING:
4000 case G_SUPPLICANT_STATE_ASSOCIATING:
4001 #if defined TIZEN_EXT
4002 reset_autoscan(device);
4004 stop_autoscan(device);
4007 if (!wifi->connected)
4008 connman_network_set_associating(network, true);
4012 case G_SUPPLICANT_STATE_COMPLETED:
4013 #if defined TIZEN_EXT
4014 /* though it should be already reset: */
4015 reset_autoscan(device);
4017 wifi->assoc_retry_count = 0;
4019 wifi->scan_pending_network = NULL;
4021 /* should be cleared scanning flag */
4022 bool scanning = connman_device_get_scanning(device);
4024 connman_device_set_scanning(device,
4025 CONNMAN_SERVICE_TYPE_WIFI, false);
4026 connman_device_unref(device);
4029 if (!wifi->automaxspeed_timeout) {
4030 DBG("Going to start signalpoll timer!!");
4031 int ret = network_signalpoll(wifi);
4033 DBG("Fail to get max speed !!");
4035 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
4038 g_hash_table_remove_all(failed_bssids);
4040 /* though it should be already stopped: */
4041 stop_autoscan(device);
4044 if (!handle_wps_completion(interface, network, device, wifi))
4047 connman_network_set_connected(network, true);
4049 wifi->disconnect_code = 0;
4050 wifi->assoc_code = 0;
4051 wifi->load_shaping_retries = 0;
4054 case G_SUPPLICANT_STATE_DISCONNECTED:
4055 #if defined TIZEN_EXT
4056 connman_network_set_maxspeed(network, 0);
4058 if (wifi->automaxspeed_timeout != 0) {
4059 g_source_remove(wifi->automaxspeed_timeout);
4060 wifi->automaxspeed_timeout = 0;
4061 DBG("Remove signalpoll timer!!");
4065 * If we're in one of the idle modes, we have
4066 * not started association yet and thus setting
4067 * those ones to FALSE could cancel an association
4070 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4072 if (is_idle_wps(interface, wifi))
4078 #if defined TIZEN_EXT
4079 if (handle_assoc_status_code(interface, wifi)) {
4080 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4081 guint bssid_length = 0;
4084 bssid_length = g_slist_length(bssid_list);
4086 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4087 network_connect(network);
4091 wifi->load_shaping_retries = 0;
4094 g_hash_table_remove_all(failed_bssids);
4096 if (handle_assoc_status_code(interface, wifi))
4100 /* If previous state was 4way-handshake, then
4101 * it's either: psk was incorrect and thus we retry
4102 * or if we reach the maximum retries we declare the
4104 if (handle_4way_handshake_failure(interface,
4108 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4109 switch (wifi->disconnect_code) {
4110 case 1: /* Unspecified reason */
4111 /* Let's assume it's because we got blocked */
4113 case 6: /* Class 2 frame received from nonauthenticated STA */
4114 connman_network_set_error(network,
4115 CONNMAN_NETWORK_ERROR_BLOCKED);
4122 #if defined TIZEN_EXT
4123 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4124 * Retry association until its retry count is expired */
4125 if (handle_wifi_assoc_retry(network, wifi) == true) {
4126 throw_wifi_scan(wifi->device, scan_callback);
4127 wifi->scan_pending_network = wifi->network;
4131 if(wifi->disconnect_code > 0){
4132 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4133 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4137 connman_network_set_connected(network, false);
4138 connman_network_set_associating(network, false);
4139 wifi->disconnecting = false;
4141 start_autoscan(device);
4145 case G_SUPPLICANT_STATE_INACTIVE:
4146 #if defined TIZEN_EXT
4147 if (handle_wps_completion(interface, network, device, wifi) == false)
4150 connman_network_set_associating(network, false);
4151 start_autoscan(device);
4155 case G_SUPPLICANT_STATE_UNKNOWN:
4156 case G_SUPPLICANT_STATE_DISABLED:
4157 case G_SUPPLICANT_STATE_ASSOCIATED:
4158 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4159 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4163 old_connected = wifi->connected;
4164 wifi->state = state;
4166 /* Saving wpa_s state policy:
4167 * If connected and if the state changes are roaming related:
4168 * --> We stay connected
4170 * --> We are connected
4172 * --> We are not connected
4175 case G_SUPPLICANT_STATE_AUTHENTICATING:
4176 case G_SUPPLICANT_STATE_ASSOCIATING:
4177 case G_SUPPLICANT_STATE_ASSOCIATED:
4178 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4179 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4180 if (wifi->connected)
4181 connman_warn("Probably roaming right now!"
4182 " Staying connected...");
4184 case G_SUPPLICANT_STATE_SCANNING:
4185 wifi->connected = false;
4188 start_autoscan(device);
4190 case G_SUPPLICANT_STATE_COMPLETED:
4191 wifi->connected = true;
4194 wifi->connected = false;
4201 static void interface_removed(GSupplicantInterface *interface)
4203 const char *ifname = g_supplicant_interface_get_ifname(interface);
4204 struct wifi_data *wifi;
4206 DBG("ifname %s", ifname);
4208 wifi = g_supplicant_interface_get_data(interface);
4210 #if defined TIZEN_EXT_WIFI_MESH
4211 if (wifi && wifi->mesh_interface) {
4212 DBG("Notify mesh interface remove");
4213 connman_mesh_notify_interface_remove(true);
4214 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4215 g_free(mesh_info->parent_ifname);
4216 g_free(mesh_info->ifname);
4217 g_free(mesh_info->identifier);
4219 wifi->mesh_interface = false;
4220 wifi->mesh_info = NULL;
4226 wifi->interface = NULL;
4228 if (wifi && wifi->tethering)
4231 if (!wifi || !wifi->device) {
4232 DBG("wifi interface already removed");
4236 connman_device_set_powered(wifi->device, false);
4238 check_p2p_technology();
4239 #if defined TIZEN_EXT_WIFI_MESH
4240 check_mesh_technology();
4244 static void set_device_type(const char *type, char dev_type[17])
4246 const char *oui = "0050F204";
4247 const char *category = "0001";
4248 const char *sub_category = "0000";
4250 if (!g_strcmp0(type, "handset")) {
4252 sub_category = "0005";
4253 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4254 sub_category = "0001";
4255 else if (!g_strcmp0(type, "server"))
4256 sub_category = "0002";
4257 else if (!g_strcmp0(type, "laptop"))
4258 sub_category = "0005";
4259 else if (!g_strcmp0(type, "desktop"))
4260 sub_category = "0006";
4261 else if (!g_strcmp0(type, "tablet"))
4262 sub_category = "0009";
4263 else if (!g_strcmp0(type, "watch"))
4266 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4269 static void p2p_support(GSupplicantInterface *interface)
4271 char dev_type[17] = {};
4272 const char *hostname;
4279 if (!g_supplicant_interface_has_p2p(interface))
4282 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4283 DBG("Could not register P2P technology driver");
4287 hostname = connman_utsname_get_hostname();
4289 hostname = "ConnMan";
4291 set_device_type(connman_machine_get_type(), dev_type);
4292 g_supplicant_interface_set_p2p_device_config(interface,
4293 hostname, dev_type);
4294 connman_peer_driver_register(&peer_driver);
4297 static void scan_started(GSupplicantInterface *interface)
4302 static void scan_finished(GSupplicantInterface *interface)
4304 #if defined TIZEN_EXT
4305 struct wifi_data *wifi;
4306 bool is_associating = false;
4307 static bool is_scanning = true;
4312 #if defined TIZEN_EXT
4313 wifi = g_supplicant_interface_get_data(interface);
4314 if (wifi && wifi->scan_pending_network) {
4315 network_connect(wifi->scan_pending_network);
4316 wifi->scan_pending_network = NULL;
4319 //service state - associating
4320 if(!wifi || !wifi->network)
4323 is_associating = connman_network_get_associating(wifi->network);
4324 if(is_associating && is_scanning){
4325 is_scanning = false;
4326 DBG("send scan for connecting");
4327 throw_wifi_scan(wifi->device, scan_callback);
4338 static void ap_create_fail(GSupplicantInterface *interface)
4340 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4343 if ((wifi->tethering) && (wifi->tethering_param)) {
4344 DBG("%s create AP fail \n",
4345 g_supplicant_interface_get_ifname(wifi->interface));
4347 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4348 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4349 wifi->tethering = false;
4351 ret = tech_set_tethering(wifi->tethering_param->technology,
4352 wifi->tethering_param->ssid->ssid,
4353 wifi->tethering_param->ssid->passphrase,
4354 wifi->bridge, true);
4356 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4357 connman_technology_tethering_notify(wifi_technology,false);
4360 g_free(wifi->tethering_param->ssid);
4361 g_free(wifi->tethering_param);
4362 wifi->tethering_param = NULL;
4368 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4370 unsigned char strength;
4372 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4374 #if !defined TIZEN_EXT
4381 #if defined TIZEN_EXT_WIFI_MESH
4382 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4384 GSupplicantInterface *interface;
4385 struct wifi_data *wifi;
4386 const char *name, *security;
4387 struct connman_mesh *connman_mesh;
4388 struct wifi_mesh_info *mesh_info;
4389 const unsigned char *bssid;
4390 const char *identifier;
4395 interface = g_supplicant_network_get_interface(supplicant_network);
4396 wifi = g_supplicant_interface_get_data(interface);
4397 if (!wifi || !wifi->mesh_interface) {
4398 DBG("Virtual Mesh interface not created");
4402 bssid = g_supplicant_network_get_bssid(supplicant_network);
4403 address = g_malloc0(19);
4404 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4405 bssid[2], bssid[3], bssid[4], bssid[5]);
4407 identifier = g_supplicant_network_get_identifier(supplicant_network);
4408 name = g_supplicant_network_get_name(supplicant_network);
4409 security = g_supplicant_network_get_security(supplicant_network);
4410 frequency = g_supplicant_network_get_frequency(supplicant_network);
4412 mesh_info = wifi->mesh_info;
4413 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4417 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4419 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4420 connman_mesh_set_name(connman_mesh, name);
4421 connman_mesh_set_security(connman_mesh, security);
4422 connman_mesh_set_frequency(connman_mesh, frequency);
4423 connman_mesh_set_address(connman_mesh, address);
4424 connman_mesh_set_index(connman_mesh, mesh_info->index);
4425 connman_mesh_set_strength(connman_mesh,
4426 calculate_strength(supplicant_network));
4427 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4429 ret = connman_mesh_register(connman_mesh);
4430 if (ret == -EALREADY)
4431 DBG("Mesh Peer is already registered");
4437 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4439 GSupplicantInterface *interface;
4440 struct wifi_data *wifi;
4441 struct connman_mesh *connman_mesh;
4442 struct wifi_mesh_info *mesh_info;
4443 const char *identifier;
4445 interface = g_supplicant_network_get_interface(supplicant_network);
4446 wifi = g_supplicant_interface_get_data(interface);
4447 if (!wifi || !wifi->mesh_interface) {
4448 DBG("Virtual Mesh interface not created");
4452 identifier = g_supplicant_network_get_identifier(supplicant_network);
4454 DBG("Failed to get Mesh Peer identifier");
4458 mesh_info = wifi->mesh_info;
4459 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4461 /* Do not unregister connected mesh peer */
4462 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4463 DBG("Mesh Peer %s is connected", identifier);
4466 DBG("Mesh Peer identifier %s removed", identifier);
4467 connman_mesh_unregister(connman_mesh);
4472 static void network_added(GSupplicantNetwork *supplicant_network)
4474 struct connman_network *network;
4475 GSupplicantInterface *interface;
4476 struct wifi_data *wifi;
4477 const char *name, *identifier, *security, *group, *mode;
4478 const unsigned char *ssid;
4479 unsigned int ssid_len;
4483 bool wps_advertizing;
4485 #if defined TIZEN_EXT
4486 GSList *vsie_list = NULL;
4487 const unsigned char *country_code;
4488 ieee80211_modes_e phy_mode;
4491 mode = g_supplicant_network_get_mode(supplicant_network);
4492 identifier = g_supplicant_network_get_identifier(supplicant_network);
4494 DBG("%s", identifier);
4496 if (!g_strcmp0(mode, "adhoc"))
4499 #if defined TIZEN_EXT_WIFI_MESH
4500 if (!g_strcmp0(mode, "mesh")) {
4501 mesh_peer_added(supplicant_network);
4506 interface = g_supplicant_network_get_interface(supplicant_network);
4507 wifi = g_supplicant_interface_get_data(interface);
4508 name = g_supplicant_network_get_name(supplicant_network);
4509 security = g_supplicant_network_get_security(supplicant_network);
4510 group = g_supplicant_network_get_identifier(supplicant_network);
4511 wps = g_supplicant_network_get_wps(supplicant_network);
4512 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4513 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4514 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4515 supplicant_network);
4520 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4522 network = connman_device_get_network(wifi->device, identifier);
4525 network = connman_network_create(identifier,
4526 CONNMAN_NETWORK_TYPE_WIFI);
4530 connman_network_set_index(network, wifi->index);
4532 if (connman_device_add_network(wifi->device, network) < 0) {
4533 connman_network_unref(network);
4537 wifi->networks = g_slist_prepend(wifi->networks, network);
4540 if (name && name[0] != '\0')
4541 connman_network_set_name(network, name);
4543 connman_network_set_blob(network, "WiFi.SSID",
4545 #if defined TIZEN_EXT
4546 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4548 connman_network_set_vsie_list(network, vsie_list);
4550 DBG("vsie_list is NULL");
4551 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4552 connman_network_set_countrycode(network, country_code);
4553 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4554 connman_network_set_phy_mode(network, phy_mode);
4556 connman_network_set_string(network, "WiFi.Security", security);
4557 connman_network_set_strength(network,
4558 calculate_strength(supplicant_network));
4559 connman_network_set_bool(network, "WiFi.WPS", wps);
4562 /* Is AP advertizing for WPS association?
4563 * If so, we decide to use WPS by default */
4564 if (wps_ready && wps_pbc &&
4566 #if !defined TIZEN_EXT
4567 connman_network_set_bool(network, "WiFi.UseWPS", true);
4569 DBG("wps is activating by ap but ignore it.");
4574 connman_network_set_frequency(network,
4575 g_supplicant_network_get_frequency(supplicant_network));
4576 #if defined TIZEN_EXT
4577 connman_network_set_bssid(network,
4578 g_supplicant_network_get_bssid(supplicant_network));
4579 connman_network_set_maxrate(network,
4580 g_supplicant_network_get_maxrate(supplicant_network));
4581 connman_network_set_enc_mode(network,
4582 g_supplicant_network_get_enc_mode(supplicant_network));
4583 connman_network_set_rsn_mode(network,
4584 g_supplicant_network_get_rsn_mode(supplicant_network));
4585 connman_network_set_keymgmt(network,
4586 g_supplicant_network_get_keymgmt(supplicant_network));
4587 connman_network_set_bool(network, "WiFi.HS20AP",
4588 g_supplicant_network_is_hs20AP(supplicant_network));
4589 connman_network_set_bssid_list(network,
4590 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4592 connman_network_set_available(network, true);
4593 connman_network_set_string(network, "WiFi.Mode", mode);
4595 #if defined TIZEN_EXT
4600 connman_network_set_group(network, group);
4602 #if defined TIZEN_EXT
4603 if (wifi_first_scan == true)
4604 found_with_first_scan = true;
4607 if (wifi->hidden && ssid) {
4608 #if defined TIZEN_EXT
4609 if (network_security(wifi->hidden->security) ==
4610 network_security(security) &&
4612 if (!g_strcmp0(wifi->hidden->security, security) &&
4614 wifi->hidden->ssid_len == ssid_len &&
4615 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4616 connman_network_connect_hidden(network,
4617 wifi->hidden->identity,
4618 wifi->hidden->passphrase,
4619 wifi->hidden->user_data);
4620 wifi->hidden->user_data = NULL;
4621 hidden_free(wifi->hidden);
4622 wifi->hidden = NULL;
4627 static void network_removed(GSupplicantNetwork *network)
4629 GSupplicantInterface *interface;
4630 struct wifi_data *wifi;
4631 const char *name, *identifier;
4632 struct connman_network *connman_network;
4634 #if defined TIZEN_EXT_WIFI_MESH
4636 mode = g_supplicant_network_get_mode(network);
4637 if (!g_strcmp0(mode, "mesh")) {
4638 mesh_peer_removed(network);
4643 interface = g_supplicant_network_get_interface(network);
4644 wifi = g_supplicant_interface_get_data(interface);
4645 identifier = g_supplicant_network_get_identifier(network);
4646 name = g_supplicant_network_get_name(network);
4648 DBG("name %s", name);
4653 connman_network = connman_device_get_network(wifi->device, identifier);
4654 if (!connman_network)
4657 #if defined TIZEN_EXT
4658 if (connman_network == wifi->scan_pending_network)
4659 wifi->scan_pending_network = NULL;
4661 if (connman_network == wifi->pending_network)
4662 wifi->pending_network = NULL;
4664 if(connman_network_get_connecting(connman_network) == true){
4665 connman_network_set_connected(connman_network, false);
4669 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4671 connman_device_remove_network(wifi->device, connman_network);
4672 connman_network_unref(connman_network);
4675 static void network_changed(GSupplicantNetwork *network, const char *property)
4677 GSupplicantInterface *interface;
4678 struct wifi_data *wifi;
4679 const char *name, *identifier;
4680 struct connman_network *connman_network;
4682 #if defined TIZEN_EXT
4683 const unsigned char *bssid;
4684 unsigned int maxrate;
4687 const unsigned char *country_code;
4688 ieee80211_modes_e phy_mode;
4692 interface = g_supplicant_network_get_interface(network);
4693 wifi = g_supplicant_interface_get_data(interface);
4694 identifier = g_supplicant_network_get_identifier(network);
4695 name = g_supplicant_network_get_name(network);
4697 DBG("name %s", name);
4702 connman_network = connman_device_get_network(wifi->device, identifier);
4703 if (!connman_network)
4706 if (g_str_equal(property, "Signal")) {
4707 connman_network_set_strength(connman_network,
4708 calculate_strength(network));
4709 connman_network_update(connman_network);
4712 #if defined TIZEN_EXT
4713 bssid = g_supplicant_network_get_bssid(network);
4714 maxrate = g_supplicant_network_get_maxrate(network);
4715 frequency = g_supplicant_network_get_frequency(network);
4716 wps = g_supplicant_network_get_wps(network);
4717 phy_mode = g_supplicant_network_get_phy_mode(network);
4719 connman_network_set_bssid(connman_network, bssid);
4720 connman_network_set_maxrate(connman_network, maxrate);
4721 connman_network_set_frequency(connman_network, frequency);
4722 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4723 country_code = g_supplicant_network_get_countrycode(network);
4724 connman_network_set_countrycode(connman_network, country_code);
4725 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4726 connman_network_set_bssid_list(connman_network, bssid_list);
4727 connman_network_set_phy_mode(connman_network, phy_mode);
4729 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4730 connman_network_get_associating(connman_network))
4731 network_connect(connman_network);
4735 static void network_associated(GSupplicantNetwork *network)
4737 GSupplicantInterface *interface;
4738 struct wifi_data *wifi;
4739 struct connman_network *connman_network;
4740 const char *identifier;
4744 interface = g_supplicant_network_get_interface(network);
4748 wifi = g_supplicant_interface_get_data(interface);
4752 identifier = g_supplicant_network_get_identifier(network);
4754 connman_network = connman_device_get_network(wifi->device, identifier);
4755 if (!connman_network)
4758 if (wifi->network) {
4759 if (wifi->network == connman_network)
4763 * This should never happen, we got associated with
4764 * a network different than the one we were expecting.
4766 DBG("Associated to %p while expecting %p",
4767 connman_network, wifi->network);
4769 connman_network_set_associating(wifi->network, false);
4772 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4774 wifi->network = connman_network_ref(connman_network);
4778 * Interface state changes callback (interface_state) is always
4779 * called before network_associated callback thus we need to call
4780 * interface_state again in order to process the new state now that
4781 * we have the network properly set.
4783 interface_state(interface);
4786 static void apply_peer_services(GSupplicantPeer *peer,
4787 struct connman_peer *connman_peer)
4789 const unsigned char *data;
4794 connman_peer_reset_services(connman_peer);
4796 data = g_supplicant_peer_get_widi_ies(peer, &length);
4798 connman_peer_add_service(connman_peer,
4799 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4803 static void add_station(const char *mac)
4805 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4809 static void remove_station(const char *mac)
4811 connman_technology_tethering_remove_station(mac);
4814 static void peer_found(GSupplicantPeer *peer)
4816 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4817 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4818 struct connman_peer *connman_peer;
4819 const char *identifier, *name;
4821 #if defined TIZEN_EXT
4825 identifier = g_supplicant_peer_get_identifier(peer);
4826 name = g_supplicant_peer_get_name(peer);
4828 DBG("ident: %s", identifier);
4830 connman_peer = connman_peer_get(wifi->device, identifier);
4834 connman_peer = connman_peer_create(identifier);
4835 connman_peer_set_name(connman_peer, name);
4836 connman_peer_set_device(connman_peer, wifi->device);
4837 apply_peer_services(peer, connman_peer);
4839 ret = connman_peer_register(connman_peer);
4840 if (ret < 0 && ret != -EALREADY)
4841 connman_peer_unref(connman_peer);
4843 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4846 static void peer_lost(GSupplicantPeer *peer)
4848 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4849 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4850 struct connman_peer *connman_peer;
4851 const char *identifier;
4856 identifier = g_supplicant_peer_get_identifier(peer);
4858 DBG("ident: %s", identifier);
4860 connman_peer = connman_peer_get(wifi->device, identifier);
4862 if (wifi->p2p_connecting &&
4863 wifi->pending_peer == connman_peer) {
4864 peer_connect_timeout(wifi);
4866 connman_peer_unregister(connman_peer);
4867 connman_peer_unref(connman_peer);
4870 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4873 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4875 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4876 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4877 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4878 struct connman_peer *connman_peer;
4879 const char *identifier;
4881 identifier = g_supplicant_peer_get_identifier(peer);
4883 DBG("ident: %s", identifier);
4888 connman_peer = connman_peer_get(wifi->device, identifier);
4893 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4894 apply_peer_services(peer, connman_peer);
4895 connman_peer_services_changed(connman_peer);
4897 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4898 if (!g_supplicant_peer_is_in_a_group(peer))
4899 p_state = CONNMAN_PEER_STATE_IDLE;
4901 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4903 case G_SUPPLICANT_PEER_GROUP_STARTED:
4905 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4906 p_state = CONNMAN_PEER_STATE_IDLE;
4908 case G_SUPPLICANT_PEER_GROUP_JOINED:
4909 connman_peer_set_iface_address(connman_peer,
4910 g_supplicant_peer_get_iface_address(peer));
4912 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4913 p_state = CONNMAN_PEER_STATE_IDLE;
4915 case G_SUPPLICANT_PEER_GROUP_FAILED:
4916 if (g_supplicant_peer_has_requested_connection(peer))
4917 p_state = CONNMAN_PEER_STATE_IDLE;
4919 p_state = CONNMAN_PEER_STATE_FAILURE;
4923 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4924 p_state == CONNMAN_PEER_STATE_FAILURE) {
4925 if (wifi->p2p_connecting
4926 && connman_peer == wifi->pending_peer)
4927 peer_cancel_timeout(wifi);
4929 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4932 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4935 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4936 GSupplicantInterface *g_iface;
4937 struct wifi_data *g_wifi;
4939 g_iface = g_supplicant_peer_get_group_interface(peer);
4943 g_wifi = g_supplicant_interface_get_data(g_iface);
4947 connman_peer_set_as_master(connman_peer,
4948 !g_supplicant_peer_is_client(peer));
4949 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4952 * If wpa_supplicant didn't create a dedicated p2p-group
4953 * interface then mark this interface as p2p_device to avoid
4954 * scan and auto-scan are launched on it while P2P is connected.
4956 if (!g_list_find(p2p_iface_list, g_wifi))
4957 wifi->p2p_device = true;
4960 connman_peer_set_state(connman_peer, p_state);
4963 static void peer_request(GSupplicantPeer *peer)
4965 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4966 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4967 struct connman_peer *connman_peer;
4968 const char *identifier;
4970 #if defined TIZEN_EXT
4975 identifier = g_supplicant_peer_get_identifier(peer);
4977 DBG("ident: %s", identifier);
4979 connman_peer = connman_peer_get(wifi->device, identifier);
4983 connman_peer_request_connection(connman_peer);
4986 #if defined TIZEN_EXT
4987 static void system_power_off(void)
4990 struct wifi_data *wifi;
4991 struct connman_service *service;
4992 struct connman_ipconfig *ipconfig_ipv4;
4994 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4995 for (list = iface_list; list; list = list->next) {
4998 if (wifi->network != NULL) {
4999 service = connman_service_lookup_from_network(wifi->network);
5000 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5001 __connman_dhcp_stop(ipconfig_ipv4);
5007 static void network_merged(GSupplicantNetwork *network)
5009 GSupplicantInterface *interface;
5010 GSupplicantState state;
5011 struct wifi_data *wifi;
5012 const char *identifier;
5013 struct connman_network *connman_network;
5017 interface = g_supplicant_network_get_interface(network);
5021 state = g_supplicant_interface_get_state(interface);
5022 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5025 wifi = g_supplicant_interface_get_data(interface);
5029 identifier = g_supplicant_network_get_identifier(network);
5031 connman_network = connman_device_get_network(wifi->device, identifier);
5032 if (!connman_network)
5035 DBG("merged identifier %s", identifier);
5037 if (wifi->connected == FALSE) {
5039 case G_SUPPLICANT_STATE_AUTHENTICATING:
5040 case G_SUPPLICANT_STATE_ASSOCIATING:
5041 case G_SUPPLICANT_STATE_ASSOCIATED:
5042 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5043 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5044 connman_network_set_associating(connman_network, TRUE);
5046 case G_SUPPLICANT_STATE_COMPLETED:
5047 connman_network_set_connected(connman_network, TRUE);
5050 DBG("Not handled the state : %d", state);
5055 ishs20AP = g_supplicant_network_is_hs20AP(network);
5058 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5059 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5060 connman_network_set_string(connman_network, "WiFi.EAP",
5062 connman_network_set_string(connman_network, "WiFi.Identity",
5063 g_supplicant_network_get_identity(network));
5064 connman_network_set_string(connman_network, "WiFi.Phase2",
5065 g_supplicant_network_get_phase2(network));
5070 wifi->network = connman_network;
5073 static void assoc_failed(void *user_data)
5075 struct connman_network *network = user_data;
5076 connman_network_set_associating(network, false);
5080 static void debug(const char *str)
5082 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5083 connman_debug("%s", str);
5086 static void disconnect_reasoncode(GSupplicantInterface *interface,
5089 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5092 wifi->disconnect_code = reasoncode;
5096 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5098 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5101 wifi->assoc_code = status_code;
5105 static const GSupplicantCallbacks callbacks = {
5106 .system_ready = system_ready,
5107 .system_killed = system_killed,
5108 .interface_added = interface_added,
5109 .interface_state = interface_state,
5110 .interface_removed = interface_removed,
5111 .p2p_support = p2p_support,
5112 .scan_started = scan_started,
5113 .scan_finished = scan_finished,
5114 .ap_create_fail = ap_create_fail,
5115 .network_added = network_added,
5116 .network_removed = network_removed,
5117 .network_changed = network_changed,
5118 .network_associated = network_associated,
5119 .add_station = add_station,
5120 .remove_station = remove_station,
5121 .peer_found = peer_found,
5122 .peer_lost = peer_lost,
5123 .peer_changed = peer_changed,
5124 .peer_request = peer_request,
5125 #if defined TIZEN_EXT
5126 .system_power_off = system_power_off,
5127 .network_merged = network_merged,
5128 .assoc_failed = assoc_failed,
5131 .disconnect_reasoncode = disconnect_reasoncode,
5132 .assoc_status_code = assoc_status_code,
5133 #if defined TIZEN_EXT_WIFI_MESH
5134 .mesh_support = mesh_support,
5135 .mesh_group_started = mesh_group_started,
5136 .mesh_group_removed = mesh_group_removed,
5137 .mesh_peer_connected = mesh_peer_connected,
5138 .mesh_peer_disconnected = mesh_peer_disconnected,
5143 static int tech_probe(struct connman_technology *technology)
5145 wifi_technology = technology;
5150 static void tech_remove(struct connman_technology *technology)
5152 wifi_technology = NULL;
5155 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5156 const char *passphrase)
5158 GSupplicantSSID *ap;
5160 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5164 ap->mode = G_SUPPLICANT_MODE_MASTER;
5165 #if defined TIZEN_EXT
5166 ap->ssid = (void *) ssid;
5170 ap->ssid_len = strlen(ssid);
5174 if (!passphrase || strlen(passphrase) == 0) {
5175 ap->security = G_SUPPLICANT_SECURITY_NONE;
5176 ap->passphrase = NULL;
5178 ap->security = G_SUPPLICANT_SECURITY_PSK;
5179 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5180 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5181 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5182 ap->passphrase = passphrase;
5188 static void ap_start_callback(int result, GSupplicantInterface *interface,
5191 struct wifi_tethering_info *info = user_data;
5193 DBG("result %d index %d bridge %s",
5194 result, info->wifi->index, info->wifi->bridge);
5196 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5197 connman_inet_remove_from_bridge(info->wifi->index,
5198 info->wifi->bridge);
5200 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5201 connman_technology_tethering_notify(info->technology, false);
5202 g_free(info->wifi->tethering_param->ssid);
5203 g_free(info->wifi->tethering_param);
5204 info->wifi->tethering_param = NULL;
5208 g_free(info->ifname);
5212 static void ap_create_callback(int result,
5213 GSupplicantInterface *interface,
5216 struct wifi_tethering_info *info = user_data;
5218 DBG("result %d ifname %s", result,
5219 g_supplicant_interface_get_ifname(interface));
5221 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5222 connman_inet_remove_from_bridge(info->wifi->index,
5223 info->wifi->bridge);
5225 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5226 connman_technology_tethering_notify(info->technology, false);
5227 g_free(info->wifi->tethering_param->ssid);
5228 g_free(info->wifi->tethering_param);
5229 info->wifi->tethering_param = NULL;
5233 g_free(info->ifname);
5239 info->wifi->interface = interface;
5240 g_supplicant_interface_set_data(interface, info->wifi);
5242 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5243 connman_error("Failed to set interface ap_scan property");
5245 g_supplicant_interface_connect(interface, info->ssid,
5246 ap_start_callback, info);
5249 static void sta_remove_callback(int result,
5250 GSupplicantInterface *interface,
5253 struct wifi_tethering_info *info = user_data;
5254 const char *driver = connman_option_get_string("wifi");
5256 DBG("ifname %s result %d ", info->ifname, result);
5258 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5259 info->wifi->tethering = false;
5260 connman_technology_tethering_notify(info->technology, false);
5262 g_free(info->ifname);
5266 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5267 g_free(info->wifi->tethering_param->ssid);
5268 g_free(info->wifi->tethering_param);
5269 info->wifi->tethering_param = NULL;
5274 info->wifi->interface = NULL;
5276 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5281 static int enable_wifi_tethering(struct connman_technology *technology,
5282 const char *bridge, const char *identifier,
5283 const char *passphrase, bool available)
5286 GSupplicantInterface *interface;
5287 struct wifi_data *wifi;
5288 struct wifi_tethering_info *info;
5293 for (list = iface_list; list; list = list->next) {
5296 DBG("wifi %p network %p pending_network %p", wifi,
5297 wifi->network, wifi->pending_network);
5299 interface = wifi->interface;
5304 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5307 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5309 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5310 DBG("%s does not support AP mode (detected)", ifname);
5314 mode = g_supplicant_interface_get_mode(interface);
5315 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5316 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5317 DBG("%s does not support AP mode (capability)", ifname);
5321 if (wifi->network && available)
5324 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5328 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5329 if (!wifi->tethering_param) {
5335 info->technology = technology;
5336 info->wifi->bridge = bridge;
5337 info->ssid = ssid_ap_init(identifier, passphrase);
5341 info->ifname = g_strdup(ifname);
5345 wifi->tethering_param->technology = technology;
5346 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5347 if (!wifi->tethering_param->ssid)
5350 info->wifi->tethering = true;
5351 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5353 berr = connman_technology_tethering_notify(technology, true);
5357 err = g_supplicant_interface_remove(interface,
5358 sta_remove_callback,
5361 DBG("tethering wifi %p ifname %s", wifi, ifname);
5366 g_free(info->ifname);
5369 g_free(wifi->tethering_param);
5370 wifi->tethering_param = NULL;
5373 * Remove bridge if it was correctly created but remove
5374 * operation failed. Instead, if bridge creation failed then
5375 * break out and do not try again on another interface,
5376 * bridge set-up does not depend on it.
5379 connman_technology_tethering_notify(technology, false);
5387 static int tech_set_tethering(struct connman_technology *technology,
5388 const char *identifier, const char *passphrase,
5389 const char *bridge, bool enabled)
5392 struct wifi_data *wifi;
5398 for (list = iface_list; list; list = list->next) {
5401 if (wifi->tethering) {
5402 wifi->tethering = false;
5404 connman_inet_remove_from_bridge(wifi->index,
5406 wifi->bridged = false;
5410 connman_technology_tethering_notify(technology, false);
5415 DBG("trying tethering for available devices");
5416 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5420 DBG("trying tethering for any device");
5421 err = enable_wifi_tethering(technology, bridge, identifier,
5428 static void regdom_callback(int result, const char *alpha2, void *user_data)
5432 if (!wifi_technology)
5438 connman_technology_regdom_notify(wifi_technology, alpha2);
5441 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5443 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5446 static struct connman_technology_driver tech_driver = {
5448 .type = CONNMAN_SERVICE_TYPE_WIFI,
5449 .probe = tech_probe,
5450 .remove = tech_remove,
5451 .set_tethering = tech_set_tethering,
5452 .set_regdom = tech_set_regdom,
5455 static int wifi_init(void)
5459 err = connman_network_driver_register(&network_driver);
5463 err = g_supplicant_register(&callbacks);
5465 connman_network_driver_unregister(&network_driver);
5469 err = connman_technology_driver_register(&tech_driver);
5471 g_supplicant_unregister(&callbacks);
5472 connman_network_driver_unregister(&network_driver);
5476 #if defined TIZEN_EXT
5477 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5482 static void wifi_exit(void)
5486 connman_technology_driver_unregister(&tech_driver);
5488 g_supplicant_unregister(&callbacks);
5490 connman_network_driver_unregister(&network_driver);
5492 #if defined TIZEN_EXT
5493 g_hash_table_unref(failed_bssids);
5497 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5498 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)