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;
3230 else if (g_str_equal(security, "owe"))
3231 return G_SUPPLICANT_SECURITY_OWE;
3234 return G_SUPPLICANT_SECURITY_UNKNOWN;
3237 #if defined TIZEN_EXT
3238 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3240 if (security == NULL)
3241 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3243 if (g_str_equal(security, "FT") == TRUE)
3244 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3245 else if (g_str_equal(security, "CCKM") == TRUE)
3246 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3248 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3252 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3254 const char *security;
3255 #if defined TIZEN_EXT
3256 const void *ssid_data;
3259 memset(ssid, 0, sizeof(*ssid));
3260 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3261 #if defined TIZEN_EXT
3262 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3264 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3269 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3271 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3274 ssid->scan_ssid = 1;
3275 security = connman_network_get_string(network, "WiFi.Security");
3276 ssid->security = network_security(security);
3277 #if defined TIZEN_EXT
3278 ssid->ieee80211w = 1;
3280 ssid->passphrase = connman_network_get_string(network,
3282 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3285 * If our private key password is unset,
3286 * we use the supplied passphrase. That is needed
3287 * for PEAP where 2 passphrases (identity and client
3288 * cert may have to be provided.
3290 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3291 connman_network_set_string(network,
3292 "WiFi.PrivateKeyPassphrase",
3294 /* We must have an identity for both PEAP and TLS */
3295 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3297 /* Use agent provided identity as a fallback */
3298 if (!ssid->identity || strlen(ssid->identity) == 0)
3299 ssid->identity = connman_network_get_string(network,
3300 "WiFi.AgentIdentity");
3302 ssid->anonymous_identity = connman_network_get_string(network,
3303 "WiFi.AnonymousIdentity");
3304 ssid->ca_cert_path = connman_network_get_string(network,
3306 ssid->subject_match = connman_network_get_string(network,
3307 "WiFi.SubjectMatch");
3308 ssid->altsubject_match = connman_network_get_string(network,
3309 "WiFi.AltSubjectMatch");
3310 ssid->domain_suffix_match = connman_network_get_string(network,
3311 "WiFi.DomainSuffixMatch");
3312 ssid->domain_match = connman_network_get_string(network,
3313 "WiFi.DomainMatch");
3314 ssid->client_cert_path = connman_network_get_string(network,
3315 "WiFi.ClientCertFile");
3316 ssid->private_key_path = connman_network_get_string(network,
3317 "WiFi.PrivateKeyFile");
3318 ssid->private_key_passphrase = connman_network_get_string(network,
3319 "WiFi.PrivateKeyPassphrase");
3320 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3322 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3323 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3325 #if defined TIZEN_EXT
3326 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3327 ssid->bssid_for_connect_len = 6;
3328 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3329 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3330 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3331 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3332 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3334 ssid->freq = connman_network_get_frequency(network);
3337 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3338 if (bssid_list && g_slist_length(bssid_list) > 1) {
3340 /* If there are more than one bssid,
3341 * the user-specified bssid is tried only once at the beginning.
3342 * After that, the bssids in the list are tried in order.
3344 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3345 set_connman_bssid(RESET_BSSID, NULL);
3350 char buff[MAC_ADDRESS_LENGTH];
3351 for (list = bssid_list; list; list = list->next) {
3352 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3354 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3355 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3356 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3357 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3359 gchar *curr_bssid = g_strdup((const gchar *)buff);
3361 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3362 DBG("bssid match, try next bssid");
3366 g_hash_table_add(failed_bssids, curr_bssid);
3368 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3369 ssid->bssid = buff_bssid;
3370 ssid->freq = (unsigned int)bssids->frequency;
3376 ssid->bssid = connman_network_get_bssid(network);
3377 g_hash_table_remove_all(failed_bssids);
3380 ssid->bssid = connman_network_get_bssid(network);
3383 ssid->eap_keymgmt = network_eap_keymgmt(
3384 connman_network_get_string(network, "WiFi.KeymgmtType"));
3385 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3387 if(g_strcmp0(ssid->eap, "fast") == 0)
3388 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3391 if (connman_setting_get_bool("BackgroundScanning"))
3392 ssid->bgscan = BGSCAN_DEFAULT;
3395 static int network_connect(struct connman_network *network)
3397 struct connman_device *device = connman_network_get_device(network);
3398 struct wifi_data *wifi;
3399 GSupplicantInterface *interface;
3400 GSupplicantSSID *ssid;
3402 DBG("network %p", network);
3407 wifi = connman_device_get_data(device);
3411 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3415 interface = wifi->interface;
3417 ssid_init(ssid, network);
3419 if (wifi->disconnecting) {
3420 wifi->pending_network = network;
3421 #if defined TIZEN_EXT
3426 wifi->network = connman_network_ref(network);
3428 #if defined TIZEN_EXT
3429 wifi->scan_pending_network = NULL;
3432 return g_supplicant_interface_connect(interface, ssid,
3433 connect_callback, network);
3436 return -EINPROGRESS;
3439 static void disconnect_callback(int result, GSupplicantInterface *interface,
3442 #if defined TIZEN_EXT
3444 struct wifi_data *wifi;
3445 struct connman_network *network = user_data;
3447 DBG("network %p result %d", network, result);
3449 for (list = iface_list; list; list = list->next) {
3452 if (wifi->network == NULL && wifi->disconnecting == true)
3453 wifi->disconnecting = false;
3455 if (wifi->network == network)
3459 /* wifi_data may be invalid because wifi is already disabled */
3464 struct wifi_data *wifi = user_data;
3467 DBG("result %d supplicant interface %p wifi %p",
3468 result, interface, wifi);
3470 if (result == -ECONNABORTED) {
3471 DBG("wifi interface no longer available");
3475 if (wifi->network) {
3476 connman_network_set_connected(wifi->network, false);
3477 wifi->network = NULL;
3480 wifi->disconnecting = false;
3481 wifi->connected = false;
3483 if (wifi->pending_network) {
3484 network_connect(wifi->pending_network);
3485 wifi->pending_network = NULL;
3488 start_autoscan(wifi->device);
3491 static int network_disconnect(struct connman_network *network)
3493 struct connman_device *device = connman_network_get_device(network);
3494 struct wifi_data *wifi;
3496 #if defined TIZEN_EXT
3497 struct connman_service *service;
3500 DBG("network %p", network);
3502 wifi = connman_device_get_data(device);
3503 if (!wifi || !wifi->interface)
3506 #if defined TIZEN_EXT
3507 if (connman_network_get_associating(network) == true) {
3508 connman_network_clear_associating(network);
3509 connman_network_set_bool(network, "WiFi.UseWPS", false);
3511 service = connman_service_lookup_from_network(network);
3513 if (service != NULL &&
3514 (__connman_service_is_connected_state(service,
3515 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3516 __connman_service_is_connected_state(service,
3517 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3518 (connman_service_get_favorite(service) == false))
3519 __connman_service_set_passphrase(service, NULL);
3522 if (wifi->pending_network == network)
3523 wifi->pending_network = NULL;
3525 if (wifi->scan_pending_network == network)
3526 wifi->scan_pending_network = NULL;
3529 connman_network_set_associating(network, false);
3531 if (wifi->disconnecting)
3534 wifi->disconnecting = true;
3536 #if defined TIZEN_EXT
3537 err = g_supplicant_interface_disconnect(wifi->interface,
3538 disconnect_callback, network);
3540 err = g_supplicant_interface_disconnect(wifi->interface,
3541 disconnect_callback, wifi);
3545 wifi->disconnecting = false;
3550 #if defined TIZEN_EXT
3551 static void set_connection_mode(struct connman_network *network,
3554 ieee80211_modes_e phy_mode;
3555 connection_mode_e conn_mode;
3557 phy_mode = connman_network_get_phy_mode(network);
3559 case IEEE80211_MODE_B:
3560 if (linkspeed > 0 && linkspeed <= 11)
3561 conn_mode = CONNECTION_MODE_IEEE80211B;
3563 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3566 case IEEE80211_MODE_BG:
3567 if (linkspeed > 0 && linkspeed <= 11)
3568 conn_mode = CONNECTION_MODE_IEEE80211B;
3569 else if (linkspeed > 11 && linkspeed <= 54)
3570 conn_mode = CONNECTION_MODE_IEEE80211G;
3572 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3575 case IEEE80211_MODE_BGN:
3576 if (linkspeed > 0 && linkspeed <= 11)
3577 conn_mode = CONNECTION_MODE_IEEE80211B;
3578 else if (linkspeed > 11 && linkspeed <= 54)
3579 conn_mode = CONNECTION_MODE_IEEE80211G;
3580 else if (linkspeed > 54 && linkspeed <= 450)
3581 conn_mode = CONNECTION_MODE_IEEE80211N;
3583 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3586 case IEEE80211_MODE_A:
3587 if (linkspeed > 0 && linkspeed <= 54)
3588 conn_mode = CONNECTION_MODE_IEEE80211A;
3590 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3593 case IEEE80211_MODE_AN:
3594 if (linkspeed > 0 && linkspeed <= 54)
3595 conn_mode = CONNECTION_MODE_IEEE80211A;
3596 else if (linkspeed > 54 && linkspeed <= 450)
3597 conn_mode = CONNECTION_MODE_IEEE80211N;
3599 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3602 case IEEE80211_MODE_ANAC:
3603 if (linkspeed > 0 && linkspeed <= 54)
3604 conn_mode = CONNECTION_MODE_IEEE80211A;
3605 else if (linkspeed > 54 && linkspeed <= 450)
3606 conn_mode = CONNECTION_MODE_IEEE80211N;
3607 else if (linkspeed > 450 && linkspeed <= 1300)
3608 conn_mode = CONNECTION_MODE_IEEE80211AC;
3610 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3614 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3618 DBG("connection mode(%d)", conn_mode);
3619 connman_network_set_connection_mode(network, conn_mode);
3622 static void signalpoll_callback(int result, int maxspeed, uint8_t strength,
3625 struct connman_network *network = user_data;
3628 DBG("Failed to get maxspeed from signalpoll !");
3636 DBG("maxspeed = %d, strength = %d", maxspeed, strength);
3638 connman_network_set_strength(network, strength);
3639 connman_network_set_maxspeed(network, maxspeed);
3640 set_connection_mode(network, maxspeed);
3644 static int network_signalpoll(struct wifi_data *wifi)
3646 GSupplicantInterface *interface;
3647 struct connman_network *network;
3649 if (!wifi || !wifi->network)
3652 interface = wifi->interface;
3653 network = wifi->network;
3655 DBG("network %p", network);
3657 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3660 static gboolean autosignalpoll_timeout(gpointer data)
3662 struct wifi_data *wifi = data;
3664 if (!wifi || !wifi->automaxspeed_timeout) {
3665 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3669 int ret = network_signalpoll(wifi);
3671 DBG("Fail to get max speed !!");
3672 wifi->automaxspeed_timeout = 0;
3680 static struct connman_network_driver network_driver = {
3682 .type = CONNMAN_NETWORK_TYPE_WIFI,
3683 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3684 .probe = network_probe,
3685 .remove = network_remove,
3686 .connect = network_connect,
3687 .disconnect = network_disconnect,
3690 static void interface_added(GSupplicantInterface *interface)
3692 const char *ifname = g_supplicant_interface_get_ifname(interface);
3693 const char *driver = g_supplicant_interface_get_driver(interface);
3694 #if defined TIZEN_EXT
3695 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3698 struct wifi_data *wifi;
3700 wifi = g_supplicant_interface_get_data(interface);
3702 wifi = get_pending_wifi_data(ifname);
3706 wifi->interface = interface;
3707 g_supplicant_interface_set_data(interface, wifi);
3708 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3709 wifi->p2p_device = true;
3712 DBG("ifname %s driver %s wifi %p tethering %d",
3713 ifname, driver, wifi, wifi->tethering);
3715 if (!wifi->device) {
3716 connman_error("WiFi device not set");
3720 connman_device_set_powered(wifi->device, true);
3721 #if defined TIZEN_EXT
3722 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3723 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3724 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3725 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3729 static bool is_idle(struct wifi_data *wifi)
3731 DBG("state %d", wifi->state);
3733 switch (wifi->state) {
3734 case G_SUPPLICANT_STATE_UNKNOWN:
3735 case G_SUPPLICANT_STATE_DISABLED:
3736 case G_SUPPLICANT_STATE_DISCONNECTED:
3737 case G_SUPPLICANT_STATE_INACTIVE:
3738 case G_SUPPLICANT_STATE_SCANNING:
3741 case G_SUPPLICANT_STATE_AUTHENTICATING:
3742 case G_SUPPLICANT_STATE_ASSOCIATING:
3743 case G_SUPPLICANT_STATE_ASSOCIATED:
3744 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3745 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3746 case G_SUPPLICANT_STATE_COMPLETED:
3753 static bool is_idle_wps(GSupplicantInterface *interface,
3754 struct wifi_data *wifi)
3756 /* First, let's check if WPS processing did not went wrong */
3757 if (g_supplicant_interface_get_wps_state(interface) ==
3758 G_SUPPLICANT_WPS_STATE_FAIL)
3761 /* Unlike normal connection, being associated while processing wps
3762 * actually means that we are idling. */
3763 switch (wifi->state) {
3764 case G_SUPPLICANT_STATE_UNKNOWN:
3765 case G_SUPPLICANT_STATE_DISABLED:
3766 case G_SUPPLICANT_STATE_DISCONNECTED:
3767 case G_SUPPLICANT_STATE_INACTIVE:
3768 case G_SUPPLICANT_STATE_SCANNING:
3769 case G_SUPPLICANT_STATE_ASSOCIATED:
3771 case G_SUPPLICANT_STATE_AUTHENTICATING:
3772 case G_SUPPLICANT_STATE_ASSOCIATING:
3773 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3774 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3775 case G_SUPPLICANT_STATE_COMPLETED:
3782 static bool handle_wps_completion(GSupplicantInterface *interface,
3783 struct connman_network *network,
3784 struct connman_device *device,
3785 struct wifi_data *wifi)
3789 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3791 const unsigned char *ssid, *wps_ssid;
3792 unsigned int ssid_len, wps_ssid_len;
3793 const char *wps_key;
3795 /* Checking if we got associated with requested
3797 ssid = connman_network_get_blob(network, "WiFi.SSID",
3800 wps_ssid = g_supplicant_interface_get_wps_ssid(
3801 interface, &wps_ssid_len);
3803 if (!wps_ssid || wps_ssid_len != ssid_len ||
3804 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3805 connman_network_set_associating(network, false);
3806 #if defined TIZEN_EXT
3807 g_supplicant_interface_disconnect(wifi->interface,
3808 disconnect_callback, wifi->network);
3810 connman_network_set_bool(network, "WiFi.UseWPS", false);
3811 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3813 g_supplicant_interface_disconnect(wifi->interface,
3814 disconnect_callback, wifi);
3819 wps_key = g_supplicant_interface_get_wps_key(interface);
3820 #if defined TIZEN_EXT
3821 /* Check the passphrase and encrypt it
3824 gchar *passphrase = g_strdup(wps_key);
3826 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3828 if (check_passphrase_ext(network, passphrase) < 0) {
3829 DBG("[WPS] Invalid passphrase");
3834 ret = send_encryption_request(passphrase, network);
3839 DBG("[WPS] Encryption request succeeded");
3841 DBG("[WPS] Encryption request failed %d", ret);
3844 connman_network_set_string(network, "WiFi.Passphrase",
3847 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3854 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3855 struct wifi_data *wifi)
3857 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3858 #if defined TIZEN_EXT
3859 wifi->assoc_code > 0 &&
3861 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3863 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3864 wifi->load_shaping_retries ++;
3867 wifi->load_shaping_retries = 0;
3871 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3872 struct connman_network *network,
3873 struct wifi_data *wifi)
3875 #if defined TIZEN_EXT
3876 const char *security;
3877 struct connman_service *service;
3879 if (wifi->connected)
3882 security = connman_network_get_string(network, "WiFi.Security");
3884 if (security && g_str_equal(security, "ieee8021x") == true &&
3885 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3887 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3892 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3895 struct connman_service *service;
3897 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3900 if (wifi->connected)
3904 service = connman_service_lookup_from_network(network);
3910 if (connman_service_get_favorite(service)) {
3911 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3916 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3921 #if defined TIZEN_EXT
3922 static bool handle_wifi_assoc_retry(struct connman_network *network,
3923 struct wifi_data *wifi)
3925 const char *security;
3927 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3928 connman_network_get_connecting(network) != true) {
3929 wifi->assoc_retry_count = 0;
3933 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3934 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3935 wifi->assoc_retry_count = 0;
3939 security = connman_network_get_string(network, "WiFi.Security");
3940 if (security && g_str_equal(security, "ieee8021x") == true &&
3941 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3942 wifi->assoc_retry_count = 0;
3946 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3947 wifi->assoc_retry_count = 0;
3949 /* Honestly it's not an invalid-key error,
3950 * however QA team recommends that the invalid-key error
3951 * might be better to display for user experience.
3953 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3962 static void interface_state(GSupplicantInterface *interface)
3964 struct connman_network *network;
3965 struct connman_device *device;
3966 struct wifi_data *wifi;
3967 GSupplicantState state = g_supplicant_interface_get_state(interface);
3971 wifi = g_supplicant_interface_get_data(interface);
3973 DBG("wifi %p interface state %d", wifi, state);
3978 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3979 if (wifi->tethering_param) {
3980 g_free(wifi->tethering_param->ssid);
3981 g_free(wifi->tethering_param);
3982 wifi->tethering_param = NULL;
3986 device = wifi->device;
3990 if (g_supplicant_interface_get_ready(interface) &&
3991 !wifi->interface_ready) {
3992 wifi->interface_ready = true;
3993 finalize_interface_creation(wifi);
3996 network = wifi->network;
4001 case G_SUPPLICANT_STATE_SCANNING:
4002 if (wifi->connected)
4003 connman_network_set_connected(network, false);
4007 case G_SUPPLICANT_STATE_AUTHENTICATING:
4008 case G_SUPPLICANT_STATE_ASSOCIATING:
4009 #if defined TIZEN_EXT
4010 reset_autoscan(device);
4012 stop_autoscan(device);
4015 if (!wifi->connected)
4016 connman_network_set_associating(network, true);
4020 case G_SUPPLICANT_STATE_COMPLETED:
4021 #if defined TIZEN_EXT
4022 /* though it should be already reset: */
4023 reset_autoscan(device);
4025 wifi->assoc_retry_count = 0;
4027 wifi->scan_pending_network = NULL;
4029 /* should be cleared scanning flag */
4030 bool scanning = connman_device_get_scanning(device);
4032 connman_device_set_scanning(device,
4033 CONNMAN_SERVICE_TYPE_WIFI, false);
4034 connman_device_unref(device);
4037 if (!wifi->automaxspeed_timeout) {
4038 DBG("Going to start signalpoll timer!!");
4039 int ret = network_signalpoll(wifi);
4041 DBG("Fail to get max speed !!");
4043 wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
4046 g_hash_table_remove_all(failed_bssids);
4048 /* though it should be already stopped: */
4049 stop_autoscan(device);
4052 if (!handle_wps_completion(interface, network, device, wifi))
4055 connman_network_set_connected(network, true);
4057 wifi->disconnect_code = 0;
4058 wifi->assoc_code = 0;
4059 wifi->load_shaping_retries = 0;
4062 case G_SUPPLICANT_STATE_DISCONNECTED:
4063 #if defined TIZEN_EXT
4064 connman_network_set_strength(network, 0);
4065 connman_network_set_maxspeed(network, 0);
4067 if (wifi->automaxspeed_timeout != 0) {
4068 g_source_remove(wifi->automaxspeed_timeout);
4069 wifi->automaxspeed_timeout = 0;
4070 DBG("Remove signalpoll timer!!");
4074 * If we're in one of the idle modes, we have
4075 * not started association yet and thus setting
4076 * those ones to FALSE could cancel an association
4079 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4081 if (is_idle_wps(interface, wifi))
4087 #if defined TIZEN_EXT
4088 if (handle_assoc_status_code(interface, wifi)) {
4089 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4090 guint bssid_length = 0;
4093 bssid_length = g_slist_length(bssid_list);
4095 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4096 network_connect(network);
4100 wifi->load_shaping_retries = 0;
4103 g_hash_table_remove_all(failed_bssids);
4105 if (handle_assoc_status_code(interface, wifi))
4109 /* If previous state was 4way-handshake, then
4110 * it's either: psk was incorrect and thus we retry
4111 * or if we reach the maximum retries we declare the
4113 if (handle_4way_handshake_failure(interface,
4117 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4118 switch (wifi->disconnect_code) {
4119 case 1: /* Unspecified reason */
4120 /* Let's assume it's because we got blocked */
4122 case 6: /* Class 2 frame received from nonauthenticated STA */
4123 connman_network_set_error(network,
4124 CONNMAN_NETWORK_ERROR_BLOCKED);
4131 #if defined TIZEN_EXT
4132 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4133 * Retry association until its retry count is expired */
4134 if (handle_wifi_assoc_retry(network, wifi) == true) {
4135 throw_wifi_scan(wifi->device, scan_callback);
4136 wifi->scan_pending_network = wifi->network;
4140 if(wifi->disconnect_code > 0){
4141 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4142 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4146 connman_network_set_connected(network, false);
4147 connman_network_set_associating(network, false);
4148 wifi->disconnecting = false;
4150 start_autoscan(device);
4154 case G_SUPPLICANT_STATE_INACTIVE:
4155 #if defined TIZEN_EXT
4156 if (handle_wps_completion(interface, network, device, wifi) == false)
4159 connman_network_set_associating(network, false);
4160 start_autoscan(device);
4164 case G_SUPPLICANT_STATE_UNKNOWN:
4165 case G_SUPPLICANT_STATE_DISABLED:
4166 case G_SUPPLICANT_STATE_ASSOCIATED:
4167 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4168 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4172 old_connected = wifi->connected;
4173 wifi->state = state;
4175 /* Saving wpa_s state policy:
4176 * If connected and if the state changes are roaming related:
4177 * --> We stay connected
4179 * --> We are connected
4181 * --> We are not connected
4184 case G_SUPPLICANT_STATE_AUTHENTICATING:
4185 case G_SUPPLICANT_STATE_ASSOCIATING:
4186 case G_SUPPLICANT_STATE_ASSOCIATED:
4187 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4188 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4189 if (wifi->connected)
4190 connman_warn("Probably roaming right now!"
4191 " Staying connected...");
4193 case G_SUPPLICANT_STATE_SCANNING:
4194 wifi->connected = false;
4197 start_autoscan(device);
4199 case G_SUPPLICANT_STATE_COMPLETED:
4200 wifi->connected = true;
4203 wifi->connected = false;
4210 static void interface_removed(GSupplicantInterface *interface)
4212 const char *ifname = g_supplicant_interface_get_ifname(interface);
4213 struct wifi_data *wifi;
4215 DBG("ifname %s", ifname);
4217 wifi = g_supplicant_interface_get_data(interface);
4219 #if defined TIZEN_EXT_WIFI_MESH
4220 if (wifi && wifi->mesh_interface) {
4221 DBG("Notify mesh interface remove");
4222 connman_mesh_notify_interface_remove(true);
4223 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4224 g_free(mesh_info->parent_ifname);
4225 g_free(mesh_info->ifname);
4226 g_free(mesh_info->identifier);
4228 wifi->mesh_interface = false;
4229 wifi->mesh_info = NULL;
4235 wifi->interface = NULL;
4237 if (wifi && wifi->tethering)
4240 if (!wifi || !wifi->device) {
4241 DBG("wifi interface already removed");
4245 connman_device_set_powered(wifi->device, false);
4247 check_p2p_technology();
4248 #if defined TIZEN_EXT_WIFI_MESH
4249 check_mesh_technology();
4253 static void set_device_type(const char *type, char dev_type[17])
4255 const char *oui = "0050F204";
4256 const char *category = "0001";
4257 const char *sub_category = "0000";
4259 if (!g_strcmp0(type, "handset")) {
4261 sub_category = "0005";
4262 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4263 sub_category = "0001";
4264 else if (!g_strcmp0(type, "server"))
4265 sub_category = "0002";
4266 else if (!g_strcmp0(type, "laptop"))
4267 sub_category = "0005";
4268 else if (!g_strcmp0(type, "desktop"))
4269 sub_category = "0006";
4270 else if (!g_strcmp0(type, "tablet"))
4271 sub_category = "0009";
4272 else if (!g_strcmp0(type, "watch"))
4275 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4278 static void p2p_support(GSupplicantInterface *interface)
4280 char dev_type[17] = {};
4281 const char *hostname;
4288 if (!g_supplicant_interface_has_p2p(interface))
4291 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4292 DBG("Could not register P2P technology driver");
4296 hostname = connman_utsname_get_hostname();
4298 hostname = "ConnMan";
4300 set_device_type(connman_machine_get_type(), dev_type);
4301 g_supplicant_interface_set_p2p_device_config(interface,
4302 hostname, dev_type);
4303 connman_peer_driver_register(&peer_driver);
4306 static void scan_started(GSupplicantInterface *interface)
4311 static void scan_finished(GSupplicantInterface *interface)
4313 #if defined TIZEN_EXT
4314 struct wifi_data *wifi;
4315 bool is_associating = false;
4316 static bool is_scanning = true;
4321 #if defined TIZEN_EXT
4322 wifi = g_supplicant_interface_get_data(interface);
4323 if (wifi && wifi->scan_pending_network) {
4324 network_connect(wifi->scan_pending_network);
4325 wifi->scan_pending_network = NULL;
4328 //service state - associating
4329 if(!wifi || !wifi->network)
4332 is_associating = connman_network_get_associating(wifi->network);
4333 if(is_associating && is_scanning){
4334 is_scanning = false;
4335 DBG("send scan for connecting");
4336 throw_wifi_scan(wifi->device, scan_callback);
4347 static void ap_create_fail(GSupplicantInterface *interface)
4349 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4352 if ((wifi->tethering) && (wifi->tethering_param)) {
4353 DBG("%s create AP fail \n",
4354 g_supplicant_interface_get_ifname(wifi->interface));
4356 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4357 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4358 wifi->tethering = false;
4360 ret = tech_set_tethering(wifi->tethering_param->technology,
4361 wifi->tethering_param->ssid->ssid,
4362 wifi->tethering_param->ssid->passphrase,
4363 wifi->bridge, true);
4365 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4366 connman_technology_tethering_notify(wifi_technology,false);
4369 g_free(wifi->tethering_param->ssid);
4370 g_free(wifi->tethering_param);
4371 wifi->tethering_param = NULL;
4377 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4379 unsigned char strength;
4381 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4383 #if !defined TIZEN_EXT
4390 #if defined TIZEN_EXT_WIFI_MESH
4391 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4393 GSupplicantInterface *interface;
4394 struct wifi_data *wifi;
4395 const char *name, *security;
4396 struct connman_mesh *connman_mesh;
4397 struct wifi_mesh_info *mesh_info;
4398 const unsigned char *bssid;
4399 const char *identifier;
4404 interface = g_supplicant_network_get_interface(supplicant_network);
4405 wifi = g_supplicant_interface_get_data(interface);
4406 if (!wifi || !wifi->mesh_interface) {
4407 DBG("Virtual Mesh interface not created");
4411 bssid = g_supplicant_network_get_bssid(supplicant_network);
4412 address = g_malloc0(19);
4413 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4414 bssid[2], bssid[3], bssid[4], bssid[5]);
4416 identifier = g_supplicant_network_get_identifier(supplicant_network);
4417 name = g_supplicant_network_get_name(supplicant_network);
4418 security = g_supplicant_network_get_security(supplicant_network);
4419 frequency = g_supplicant_network_get_frequency(supplicant_network);
4421 mesh_info = wifi->mesh_info;
4422 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4426 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4428 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4429 connman_mesh_set_name(connman_mesh, name);
4430 connman_mesh_set_security(connman_mesh, security);
4431 connman_mesh_set_frequency(connman_mesh, frequency);
4432 connman_mesh_set_address(connman_mesh, address);
4433 connman_mesh_set_index(connman_mesh, mesh_info->index);
4434 connman_mesh_set_strength(connman_mesh,
4435 calculate_strength(supplicant_network));
4436 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4438 ret = connman_mesh_register(connman_mesh);
4439 if (ret == -EALREADY)
4440 DBG("Mesh Peer is already registered");
4446 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4448 GSupplicantInterface *interface;
4449 struct wifi_data *wifi;
4450 struct connman_mesh *connman_mesh;
4451 struct wifi_mesh_info *mesh_info;
4452 const char *identifier;
4454 interface = g_supplicant_network_get_interface(supplicant_network);
4455 wifi = g_supplicant_interface_get_data(interface);
4456 if (!wifi || !wifi->mesh_interface) {
4457 DBG("Virtual Mesh interface not created");
4461 identifier = g_supplicant_network_get_identifier(supplicant_network);
4463 DBG("Failed to get Mesh Peer identifier");
4467 mesh_info = wifi->mesh_info;
4468 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4470 /* Do not unregister connected mesh peer */
4471 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4472 DBG("Mesh Peer %s is connected", identifier);
4475 DBG("Mesh Peer identifier %s removed", identifier);
4476 connman_mesh_unregister(connman_mesh);
4481 static void network_added(GSupplicantNetwork *supplicant_network)
4483 struct connman_network *network;
4484 GSupplicantInterface *interface;
4485 struct wifi_data *wifi;
4486 const char *name, *identifier, *security, *group, *mode;
4487 const unsigned char *ssid;
4488 unsigned int ssid_len;
4492 bool wps_advertizing;
4494 #if defined TIZEN_EXT
4495 GSList *vsie_list = NULL;
4496 const unsigned char *country_code;
4497 ieee80211_modes_e phy_mode;
4500 mode = g_supplicant_network_get_mode(supplicant_network);
4501 identifier = g_supplicant_network_get_identifier(supplicant_network);
4503 DBG("%s", identifier);
4505 if (!g_strcmp0(mode, "adhoc"))
4508 #if defined TIZEN_EXT_WIFI_MESH
4509 if (!g_strcmp0(mode, "mesh")) {
4510 mesh_peer_added(supplicant_network);
4515 interface = g_supplicant_network_get_interface(supplicant_network);
4516 wifi = g_supplicant_interface_get_data(interface);
4517 name = g_supplicant_network_get_name(supplicant_network);
4518 security = g_supplicant_network_get_security(supplicant_network);
4519 group = g_supplicant_network_get_identifier(supplicant_network);
4520 wps = g_supplicant_network_get_wps(supplicant_network);
4521 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4522 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4523 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4524 supplicant_network);
4529 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4531 network = connman_device_get_network(wifi->device, identifier);
4534 network = connman_network_create(identifier,
4535 CONNMAN_NETWORK_TYPE_WIFI);
4539 connman_network_set_index(network, wifi->index);
4541 if (connman_device_add_network(wifi->device, network) < 0) {
4542 connman_network_unref(network);
4546 wifi->networks = g_slist_prepend(wifi->networks, network);
4549 if (name && name[0] != '\0')
4550 connman_network_set_name(network, name);
4552 connman_network_set_blob(network, "WiFi.SSID",
4554 #if defined TIZEN_EXT
4555 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4557 connman_network_set_vsie_list(network, vsie_list);
4559 DBG("vsie_list is NULL");
4560 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4561 connman_network_set_countrycode(network, country_code);
4562 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4563 connman_network_set_phy_mode(network, phy_mode);
4565 connman_network_set_string(network, "WiFi.Security", security);
4566 connman_network_set_strength(network,
4567 calculate_strength(supplicant_network));
4568 connman_network_set_bool(network, "WiFi.WPS", wps);
4571 /* Is AP advertizing for WPS association?
4572 * If so, we decide to use WPS by default */
4573 if (wps_ready && wps_pbc &&
4575 #if !defined TIZEN_EXT
4576 connman_network_set_bool(network, "WiFi.UseWPS", true);
4578 DBG("wps is activating by ap but ignore it.");
4583 connman_network_set_frequency(network,
4584 g_supplicant_network_get_frequency(supplicant_network));
4585 #if defined TIZEN_EXT
4586 connman_network_set_bssid(network,
4587 g_supplicant_network_get_bssid(supplicant_network));
4588 connman_network_set_maxrate(network,
4589 g_supplicant_network_get_maxrate(supplicant_network));
4590 connman_network_set_enc_mode(network,
4591 g_supplicant_network_get_enc_mode(supplicant_network));
4592 connman_network_set_rsn_mode(network,
4593 g_supplicant_network_get_rsn_mode(supplicant_network));
4594 connman_network_set_keymgmt(network,
4595 g_supplicant_network_get_keymgmt(supplicant_network));
4596 connman_network_set_bool(network, "WiFi.HS20AP",
4597 g_supplicant_network_is_hs20AP(supplicant_network));
4598 connman_network_set_bssid_list(network,
4599 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4601 connman_network_set_available(network, true);
4602 connman_network_set_string(network, "WiFi.Mode", mode);
4604 #if defined TIZEN_EXT
4609 connman_network_set_group(network, group);
4611 #if defined TIZEN_EXT
4612 if (wifi_first_scan == true)
4613 found_with_first_scan = true;
4616 if (wifi->hidden && ssid) {
4617 #if defined TIZEN_EXT
4618 if (network_security(wifi->hidden->security) ==
4619 network_security(security) &&
4621 if (!g_strcmp0(wifi->hidden->security, security) &&
4623 wifi->hidden->ssid_len == ssid_len &&
4624 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4625 connman_network_connect_hidden(network,
4626 wifi->hidden->identity,
4627 wifi->hidden->passphrase,
4628 wifi->hidden->user_data);
4629 wifi->hidden->user_data = NULL;
4630 hidden_free(wifi->hidden);
4631 wifi->hidden = NULL;
4636 static void network_removed(GSupplicantNetwork *network)
4638 GSupplicantInterface *interface;
4639 struct wifi_data *wifi;
4640 const char *name, *identifier;
4641 struct connman_network *connman_network;
4643 #if defined TIZEN_EXT_WIFI_MESH
4645 mode = g_supplicant_network_get_mode(network);
4646 if (!g_strcmp0(mode, "mesh")) {
4647 mesh_peer_removed(network);
4652 interface = g_supplicant_network_get_interface(network);
4653 wifi = g_supplicant_interface_get_data(interface);
4654 identifier = g_supplicant_network_get_identifier(network);
4655 name = g_supplicant_network_get_name(network);
4657 DBG("name %s", name);
4662 connman_network = connman_device_get_network(wifi->device, identifier);
4663 if (!connman_network)
4666 #if defined TIZEN_EXT
4667 if (connman_network == wifi->scan_pending_network)
4668 wifi->scan_pending_network = NULL;
4670 if (connman_network == wifi->pending_network)
4671 wifi->pending_network = NULL;
4673 if(connman_network_get_connecting(connman_network) == true){
4674 connman_network_set_connected(connman_network, false);
4678 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4680 connman_device_remove_network(wifi->device, connman_network);
4681 connman_network_unref(connman_network);
4684 static void network_changed(GSupplicantNetwork *network, const char *property)
4686 GSupplicantInterface *interface;
4687 struct wifi_data *wifi;
4688 const char *name, *identifier;
4689 struct connman_network *connman_network;
4691 #if defined TIZEN_EXT
4692 const unsigned char *bssid;
4693 unsigned int maxrate;
4696 const unsigned char *country_code;
4697 ieee80211_modes_e phy_mode;
4701 interface = g_supplicant_network_get_interface(network);
4702 wifi = g_supplicant_interface_get_data(interface);
4703 identifier = g_supplicant_network_get_identifier(network);
4704 name = g_supplicant_network_get_name(network);
4706 DBG("name %s", name);
4711 connman_network = connman_device_get_network(wifi->device, identifier);
4712 if (!connman_network)
4715 if (g_str_equal(property, "Signal")) {
4716 connman_network_set_strength(connman_network,
4717 calculate_strength(network));
4718 connman_network_update(connman_network);
4721 #if defined TIZEN_EXT
4722 bssid = g_supplicant_network_get_bssid(network);
4723 maxrate = g_supplicant_network_get_maxrate(network);
4724 frequency = g_supplicant_network_get_frequency(network);
4725 wps = g_supplicant_network_get_wps(network);
4726 phy_mode = g_supplicant_network_get_phy_mode(network);
4728 connman_network_set_bssid(connman_network, bssid);
4729 connman_network_set_maxrate(connman_network, maxrate);
4730 connman_network_set_frequency(connman_network, frequency);
4731 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4732 country_code = g_supplicant_network_get_countrycode(network);
4733 connman_network_set_countrycode(connman_network, country_code);
4734 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4735 connman_network_set_bssid_list(connman_network, bssid_list);
4736 connman_network_set_phy_mode(connman_network, phy_mode);
4738 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4739 connman_network_get_associating(connman_network))
4740 network_connect(connman_network);
4744 static void network_associated(GSupplicantNetwork *network)
4746 GSupplicantInterface *interface;
4747 struct wifi_data *wifi;
4748 struct connman_network *connman_network;
4749 const char *identifier;
4753 interface = g_supplicant_network_get_interface(network);
4757 wifi = g_supplicant_interface_get_data(interface);
4761 identifier = g_supplicant_network_get_identifier(network);
4763 connman_network = connman_device_get_network(wifi->device, identifier);
4764 if (!connman_network)
4767 if (wifi->network) {
4768 if (wifi->network == connman_network)
4772 * This should never happen, we got associated with
4773 * a network different than the one we were expecting.
4775 DBG("Associated to %p while expecting %p",
4776 connman_network, wifi->network);
4778 connman_network_set_associating(wifi->network, false);
4781 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4783 wifi->network = connman_network_ref(connman_network);
4787 * Interface state changes callback (interface_state) is always
4788 * called before network_associated callback thus we need to call
4789 * interface_state again in order to process the new state now that
4790 * we have the network properly set.
4792 interface_state(interface);
4795 static void apply_peer_services(GSupplicantPeer *peer,
4796 struct connman_peer *connman_peer)
4798 const unsigned char *data;
4803 connman_peer_reset_services(connman_peer);
4805 data = g_supplicant_peer_get_widi_ies(peer, &length);
4807 connman_peer_add_service(connman_peer,
4808 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4812 static void add_station(const char *mac)
4814 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4818 static void remove_station(const char *mac)
4820 connman_technology_tethering_remove_station(mac);
4823 static void peer_found(GSupplicantPeer *peer)
4825 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4826 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4827 struct connman_peer *connman_peer;
4828 const char *identifier, *name;
4830 #if defined TIZEN_EXT
4834 identifier = g_supplicant_peer_get_identifier(peer);
4835 name = g_supplicant_peer_get_name(peer);
4837 DBG("ident: %s", identifier);
4839 connman_peer = connman_peer_get(wifi->device, identifier);
4843 connman_peer = connman_peer_create(identifier);
4844 connman_peer_set_name(connman_peer, name);
4845 connman_peer_set_device(connman_peer, wifi->device);
4846 apply_peer_services(peer, connman_peer);
4848 ret = connman_peer_register(connman_peer);
4849 if (ret < 0 && ret != -EALREADY)
4850 connman_peer_unref(connman_peer);
4852 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4855 static void peer_lost(GSupplicantPeer *peer)
4857 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4858 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4859 struct connman_peer *connman_peer;
4860 const char *identifier;
4865 identifier = g_supplicant_peer_get_identifier(peer);
4867 DBG("ident: %s", identifier);
4869 connman_peer = connman_peer_get(wifi->device, identifier);
4871 if (wifi->p2p_connecting &&
4872 wifi->pending_peer == connman_peer) {
4873 peer_connect_timeout(wifi);
4875 connman_peer_unregister(connman_peer);
4876 connman_peer_unref(connman_peer);
4879 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4882 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4884 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4885 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4886 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4887 struct connman_peer *connman_peer;
4888 const char *identifier;
4890 identifier = g_supplicant_peer_get_identifier(peer);
4892 DBG("ident: %s", identifier);
4897 connman_peer = connman_peer_get(wifi->device, identifier);
4902 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4903 apply_peer_services(peer, connman_peer);
4904 connman_peer_services_changed(connman_peer);
4906 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4907 if (!g_supplicant_peer_is_in_a_group(peer))
4908 p_state = CONNMAN_PEER_STATE_IDLE;
4910 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4912 case G_SUPPLICANT_PEER_GROUP_STARTED:
4914 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4915 p_state = CONNMAN_PEER_STATE_IDLE;
4917 case G_SUPPLICANT_PEER_GROUP_JOINED:
4918 connman_peer_set_iface_address(connman_peer,
4919 g_supplicant_peer_get_iface_address(peer));
4921 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4922 p_state = CONNMAN_PEER_STATE_IDLE;
4924 case G_SUPPLICANT_PEER_GROUP_FAILED:
4925 if (g_supplicant_peer_has_requested_connection(peer))
4926 p_state = CONNMAN_PEER_STATE_IDLE;
4928 p_state = CONNMAN_PEER_STATE_FAILURE;
4932 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4933 p_state == CONNMAN_PEER_STATE_FAILURE) {
4934 if (wifi->p2p_connecting
4935 && connman_peer == wifi->pending_peer)
4936 peer_cancel_timeout(wifi);
4938 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4941 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4944 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4945 GSupplicantInterface *g_iface;
4946 struct wifi_data *g_wifi;
4948 g_iface = g_supplicant_peer_get_group_interface(peer);
4952 g_wifi = g_supplicant_interface_get_data(g_iface);
4956 connman_peer_set_as_master(connman_peer,
4957 !g_supplicant_peer_is_client(peer));
4958 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4961 * If wpa_supplicant didn't create a dedicated p2p-group
4962 * interface then mark this interface as p2p_device to avoid
4963 * scan and auto-scan are launched on it while P2P is connected.
4965 if (!g_list_find(p2p_iface_list, g_wifi))
4966 wifi->p2p_device = true;
4969 connman_peer_set_state(connman_peer, p_state);
4972 static void peer_request(GSupplicantPeer *peer)
4974 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4975 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4976 struct connman_peer *connman_peer;
4977 const char *identifier;
4979 #if defined TIZEN_EXT
4984 identifier = g_supplicant_peer_get_identifier(peer);
4986 DBG("ident: %s", identifier);
4988 connman_peer = connman_peer_get(wifi->device, identifier);
4992 connman_peer_request_connection(connman_peer);
4995 #if defined TIZEN_EXT
4996 static void system_power_off(void)
4999 struct wifi_data *wifi;
5000 struct connman_service *service;
5001 struct connman_ipconfig *ipconfig_ipv4;
5003 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
5004 for (list = iface_list; list; list = list->next) {
5007 if (wifi->network != NULL) {
5008 service = connman_service_lookup_from_network(wifi->network);
5009 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5010 __connman_dhcp_stop(ipconfig_ipv4);
5016 static void network_merged(GSupplicantNetwork *network)
5018 GSupplicantInterface *interface;
5019 GSupplicantState state;
5020 struct wifi_data *wifi;
5021 const char *identifier;
5022 struct connman_network *connman_network;
5026 interface = g_supplicant_network_get_interface(network);
5030 state = g_supplicant_interface_get_state(interface);
5031 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5034 wifi = g_supplicant_interface_get_data(interface);
5038 identifier = g_supplicant_network_get_identifier(network);
5040 connman_network = connman_device_get_network(wifi->device, identifier);
5041 if (!connman_network)
5044 DBG("merged identifier %s", identifier);
5046 if (wifi->connected == FALSE) {
5048 case G_SUPPLICANT_STATE_AUTHENTICATING:
5049 case G_SUPPLICANT_STATE_ASSOCIATING:
5050 case G_SUPPLICANT_STATE_ASSOCIATED:
5051 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5052 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5053 connman_network_set_associating(connman_network, TRUE);
5055 case G_SUPPLICANT_STATE_COMPLETED:
5056 connman_network_set_connected(connman_network, TRUE);
5059 DBG("Not handled the state : %d", state);
5064 ishs20AP = g_supplicant_network_is_hs20AP(network);
5067 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5068 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5069 connman_network_set_string(connman_network, "WiFi.EAP",
5071 connman_network_set_string(connman_network, "WiFi.Identity",
5072 g_supplicant_network_get_identity(network));
5073 connman_network_set_string(connman_network, "WiFi.Phase2",
5074 g_supplicant_network_get_phase2(network));
5079 wifi->network = connman_network;
5082 static void assoc_failed(void *user_data)
5084 struct connman_network *network = user_data;
5085 connman_network_set_associating(network, false);
5089 static void debug(const char *str)
5091 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5092 connman_debug("%s", str);
5095 static void disconnect_reasoncode(GSupplicantInterface *interface,
5098 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5101 wifi->disconnect_code = reasoncode;
5105 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5107 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5110 wifi->assoc_code = status_code;
5114 static const GSupplicantCallbacks callbacks = {
5115 .system_ready = system_ready,
5116 .system_killed = system_killed,
5117 .interface_added = interface_added,
5118 .interface_state = interface_state,
5119 .interface_removed = interface_removed,
5120 .p2p_support = p2p_support,
5121 .scan_started = scan_started,
5122 .scan_finished = scan_finished,
5123 .ap_create_fail = ap_create_fail,
5124 .network_added = network_added,
5125 .network_removed = network_removed,
5126 .network_changed = network_changed,
5127 .network_associated = network_associated,
5128 .add_station = add_station,
5129 .remove_station = remove_station,
5130 .peer_found = peer_found,
5131 .peer_lost = peer_lost,
5132 .peer_changed = peer_changed,
5133 .peer_request = peer_request,
5134 #if defined TIZEN_EXT
5135 .system_power_off = system_power_off,
5136 .network_merged = network_merged,
5137 .assoc_failed = assoc_failed,
5140 .disconnect_reasoncode = disconnect_reasoncode,
5141 .assoc_status_code = assoc_status_code,
5142 #if defined TIZEN_EXT_WIFI_MESH
5143 .mesh_support = mesh_support,
5144 .mesh_group_started = mesh_group_started,
5145 .mesh_group_removed = mesh_group_removed,
5146 .mesh_peer_connected = mesh_peer_connected,
5147 .mesh_peer_disconnected = mesh_peer_disconnected,
5152 static int tech_probe(struct connman_technology *technology)
5154 wifi_technology = technology;
5159 static void tech_remove(struct connman_technology *technology)
5161 wifi_technology = NULL;
5164 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5165 const char *passphrase)
5167 GSupplicantSSID *ap;
5169 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5173 ap->mode = G_SUPPLICANT_MODE_MASTER;
5174 #if defined TIZEN_EXT
5175 ap->ssid = (void *) ssid;
5179 ap->ssid_len = strlen(ssid);
5183 if (!passphrase || strlen(passphrase) == 0) {
5184 ap->security = G_SUPPLICANT_SECURITY_NONE;
5185 ap->passphrase = NULL;
5187 ap->security = G_SUPPLICANT_SECURITY_PSK;
5188 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5189 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5190 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5191 ap->passphrase = passphrase;
5197 static void ap_start_callback(int result, GSupplicantInterface *interface,
5200 struct wifi_tethering_info *info = user_data;
5202 DBG("result %d index %d bridge %s",
5203 result, info->wifi->index, info->wifi->bridge);
5205 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5206 connman_inet_remove_from_bridge(info->wifi->index,
5207 info->wifi->bridge);
5209 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5210 connman_technology_tethering_notify(info->technology, false);
5211 g_free(info->wifi->tethering_param->ssid);
5212 g_free(info->wifi->tethering_param);
5213 info->wifi->tethering_param = NULL;
5217 g_free(info->ifname);
5221 static void ap_create_callback(int result,
5222 GSupplicantInterface *interface,
5225 struct wifi_tethering_info *info = user_data;
5227 DBG("result %d ifname %s", result,
5228 g_supplicant_interface_get_ifname(interface));
5230 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5231 connman_inet_remove_from_bridge(info->wifi->index,
5232 info->wifi->bridge);
5234 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5235 connman_technology_tethering_notify(info->technology, false);
5236 g_free(info->wifi->tethering_param->ssid);
5237 g_free(info->wifi->tethering_param);
5238 info->wifi->tethering_param = NULL;
5242 g_free(info->ifname);
5248 info->wifi->interface = interface;
5249 g_supplicant_interface_set_data(interface, info->wifi);
5251 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5252 connman_error("Failed to set interface ap_scan property");
5254 g_supplicant_interface_connect(interface, info->ssid,
5255 ap_start_callback, info);
5258 static void sta_remove_callback(int result,
5259 GSupplicantInterface *interface,
5262 struct wifi_tethering_info *info = user_data;
5263 const char *driver = connman_option_get_string("wifi");
5265 DBG("ifname %s result %d ", info->ifname, result);
5267 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5268 info->wifi->tethering = false;
5269 connman_technology_tethering_notify(info->technology, false);
5271 g_free(info->ifname);
5275 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5276 g_free(info->wifi->tethering_param->ssid);
5277 g_free(info->wifi->tethering_param);
5278 info->wifi->tethering_param = NULL;
5283 info->wifi->interface = NULL;
5285 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5290 static int enable_wifi_tethering(struct connman_technology *technology,
5291 const char *bridge, const char *identifier,
5292 const char *passphrase, bool available)
5295 GSupplicantInterface *interface;
5296 struct wifi_data *wifi;
5297 struct wifi_tethering_info *info;
5302 for (list = iface_list; list; list = list->next) {
5305 DBG("wifi %p network %p pending_network %p", wifi,
5306 wifi->network, wifi->pending_network);
5308 interface = wifi->interface;
5313 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5316 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5318 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5319 DBG("%s does not support AP mode (detected)", ifname);
5323 mode = g_supplicant_interface_get_mode(interface);
5324 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5325 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5326 DBG("%s does not support AP mode (capability)", ifname);
5330 if (wifi->network && available)
5333 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5337 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5338 if (!wifi->tethering_param) {
5344 info->technology = technology;
5345 info->wifi->bridge = bridge;
5346 info->ssid = ssid_ap_init(identifier, passphrase);
5350 info->ifname = g_strdup(ifname);
5354 wifi->tethering_param->technology = technology;
5355 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5356 if (!wifi->tethering_param->ssid)
5359 info->wifi->tethering = true;
5360 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5362 berr = connman_technology_tethering_notify(technology, true);
5366 err = g_supplicant_interface_remove(interface,
5367 sta_remove_callback,
5370 DBG("tethering wifi %p ifname %s", wifi, ifname);
5375 g_free(info->ifname);
5378 g_free(wifi->tethering_param);
5379 wifi->tethering_param = NULL;
5382 * Remove bridge if it was correctly created but remove
5383 * operation failed. Instead, if bridge creation failed then
5384 * break out and do not try again on another interface,
5385 * bridge set-up does not depend on it.
5388 connman_technology_tethering_notify(technology, false);
5396 static int tech_set_tethering(struct connman_technology *technology,
5397 const char *identifier, const char *passphrase,
5398 const char *bridge, bool enabled)
5401 struct wifi_data *wifi;
5407 for (list = iface_list; list; list = list->next) {
5410 if (wifi->tethering) {
5411 wifi->tethering = false;
5413 connman_inet_remove_from_bridge(wifi->index,
5415 wifi->bridged = false;
5419 connman_technology_tethering_notify(technology, false);
5424 DBG("trying tethering for available devices");
5425 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5429 DBG("trying tethering for any device");
5430 err = enable_wifi_tethering(technology, bridge, identifier,
5437 static void regdom_callback(int result, const char *alpha2, void *user_data)
5441 if (!wifi_technology)
5447 connman_technology_regdom_notify(wifi_technology, alpha2);
5450 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5452 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5455 static struct connman_technology_driver tech_driver = {
5457 .type = CONNMAN_SERVICE_TYPE_WIFI,
5458 .probe = tech_probe,
5459 .remove = tech_remove,
5460 .set_tethering = tech_set_tethering,
5461 .set_regdom = tech_set_regdom,
5464 static int wifi_init(void)
5468 err = connman_network_driver_register(&network_driver);
5472 err = g_supplicant_register(&callbacks);
5474 connman_network_driver_unregister(&network_driver);
5478 err = connman_technology_driver_register(&tech_driver);
5480 g_supplicant_unregister(&callbacks);
5481 connman_network_driver_unregister(&network_driver);
5485 #if defined TIZEN_EXT
5486 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5491 static void wifi_exit(void)
5495 connman_technology_driver_unregister(&tech_driver);
5497 g_supplicant_unregister(&callbacks);
5499 connman_network_driver_unregister(&network_driver);
5501 #if defined TIZEN_EXT
5502 g_hash_table_unref(failed_bssids);
5506 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5507 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)