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, void *user_data)
3624 struct connman_network *network = user_data;
3627 DBG("Failed to get maxspeed from signalpoll !");
3631 DBG("maxspeed = %d", maxspeed);
3633 connman_network_set_maxspeed(network, maxspeed);
3634 set_connection_mode(network, maxspeed);
3638 static int network_signalpoll(struct wifi_data *wifi)
3640 GSupplicantInterface *interface;
3641 struct connman_network *network;
3643 if (!wifi || !wifi->network)
3646 interface = wifi->interface;
3647 network = wifi->network;
3649 DBG("network %p", network);
3651 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3654 static gboolean autosignalpoll_timeout(gpointer data)
3656 struct wifi_data *wifi = data;
3658 if (!wifi || !wifi->automaxspeed_timeout) {
3659 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3663 int ret = network_signalpoll(wifi);
3665 DBG("Fail to get max speed !!");
3666 wifi->automaxspeed_timeout = 0;
3674 static struct connman_network_driver network_driver = {
3676 .type = CONNMAN_NETWORK_TYPE_WIFI,
3677 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3678 .probe = network_probe,
3679 .remove = network_remove,
3680 .connect = network_connect,
3681 .disconnect = network_disconnect,
3684 static void interface_added(GSupplicantInterface *interface)
3686 const char *ifname = g_supplicant_interface_get_ifname(interface);
3687 const char *driver = g_supplicant_interface_get_driver(interface);
3688 #if defined TIZEN_EXT
3689 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3692 struct wifi_data *wifi;
3694 wifi = g_supplicant_interface_get_data(interface);
3696 wifi = get_pending_wifi_data(ifname);
3700 wifi->interface = interface;
3701 g_supplicant_interface_set_data(interface, wifi);
3702 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3703 wifi->p2p_device = true;
3706 DBG("ifname %s driver %s wifi %p tethering %d",
3707 ifname, driver, wifi, wifi->tethering);
3709 if (!wifi->device) {
3710 connman_error("WiFi device not set");
3714 connman_device_set_powered(wifi->device, true);
3715 #if defined TIZEN_EXT
3716 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3717 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3718 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3719 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3723 static bool is_idle(struct wifi_data *wifi)
3725 DBG("state %d", wifi->state);
3727 switch (wifi->state) {
3728 case G_SUPPLICANT_STATE_UNKNOWN:
3729 case G_SUPPLICANT_STATE_DISABLED:
3730 case G_SUPPLICANT_STATE_DISCONNECTED:
3731 case G_SUPPLICANT_STATE_INACTIVE:
3732 case G_SUPPLICANT_STATE_SCANNING:
3735 case G_SUPPLICANT_STATE_AUTHENTICATING:
3736 case G_SUPPLICANT_STATE_ASSOCIATING:
3737 case G_SUPPLICANT_STATE_ASSOCIATED:
3738 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3739 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3740 case G_SUPPLICANT_STATE_COMPLETED:
3747 static bool is_idle_wps(GSupplicantInterface *interface,
3748 struct wifi_data *wifi)
3750 /* First, let's check if WPS processing did not went wrong */
3751 if (g_supplicant_interface_get_wps_state(interface) ==
3752 G_SUPPLICANT_WPS_STATE_FAIL)
3755 /* Unlike normal connection, being associated while processing wps
3756 * actually means that we are idling. */
3757 switch (wifi->state) {
3758 case G_SUPPLICANT_STATE_UNKNOWN:
3759 case G_SUPPLICANT_STATE_DISABLED:
3760 case G_SUPPLICANT_STATE_DISCONNECTED:
3761 case G_SUPPLICANT_STATE_INACTIVE:
3762 case G_SUPPLICANT_STATE_SCANNING:
3763 case G_SUPPLICANT_STATE_ASSOCIATED:
3765 case G_SUPPLICANT_STATE_AUTHENTICATING:
3766 case G_SUPPLICANT_STATE_ASSOCIATING:
3767 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3768 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3769 case G_SUPPLICANT_STATE_COMPLETED:
3776 static bool handle_wps_completion(GSupplicantInterface *interface,
3777 struct connman_network *network,
3778 struct connman_device *device,
3779 struct wifi_data *wifi)
3783 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3785 const unsigned char *ssid, *wps_ssid;
3786 unsigned int ssid_len, wps_ssid_len;
3787 const char *wps_key;
3789 /* Checking if we got associated with requested
3791 ssid = connman_network_get_blob(network, "WiFi.SSID",
3794 wps_ssid = g_supplicant_interface_get_wps_ssid(
3795 interface, &wps_ssid_len);
3797 if (!wps_ssid || wps_ssid_len != ssid_len ||
3798 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3799 connman_network_set_associating(network, false);
3800 #if defined TIZEN_EXT
3801 g_supplicant_interface_disconnect(wifi->interface,
3802 disconnect_callback, wifi->network);
3804 connman_network_set_bool(network, "WiFi.UseWPS", false);
3805 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3807 g_supplicant_interface_disconnect(wifi->interface,
3808 disconnect_callback, wifi);
3813 wps_key = g_supplicant_interface_get_wps_key(interface);
3814 #if defined TIZEN_EXT
3815 /* Check the passphrase and encrypt it
3818 gchar *passphrase = g_strdup(wps_key);
3820 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3822 if (check_passphrase_ext(network, passphrase) < 0) {
3823 DBG("[WPS] Invalid passphrase");
3828 ret = send_encryption_request(passphrase, network);
3833 DBG("[WPS] Encryption request succeeded");
3835 DBG("[WPS] Encryption request failed %d", ret);
3838 connman_network_set_string(network, "WiFi.Passphrase",
3841 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3848 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3849 struct wifi_data *wifi)
3851 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3852 #if defined TIZEN_EXT
3853 wifi->assoc_code > 0 &&
3855 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3857 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3858 wifi->load_shaping_retries ++;
3861 wifi->load_shaping_retries = 0;
3865 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3866 struct connman_network *network,
3867 struct wifi_data *wifi)
3869 #if defined TIZEN_EXT
3870 const char *security;
3871 struct connman_service *service;
3873 if (wifi->connected)
3876 security = connman_network_get_string(network, "WiFi.Security");
3878 if (security && g_str_equal(security, "ieee8021x") == true &&
3879 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3881 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3886 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3889 struct connman_service *service;
3891 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3894 if (wifi->connected)
3898 service = connman_service_lookup_from_network(network);
3904 if (connman_service_get_favorite(service)) {
3905 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3910 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3915 #if defined TIZEN_EXT
3916 static bool handle_wifi_assoc_retry(struct connman_network *network,
3917 struct wifi_data *wifi)
3919 const char *security;
3921 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3922 connman_network_get_connecting(network) != true) {
3923 wifi->assoc_retry_count = 0;
3927 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3928 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3929 wifi->assoc_retry_count = 0;
3933 security = connman_network_get_string(network, "WiFi.Security");
3934 if (security && g_str_equal(security, "ieee8021x") == true &&
3935 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3936 wifi->assoc_retry_count = 0;
3940 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3941 wifi->assoc_retry_count = 0;
3943 /* Honestly it's not an invalid-key error,
3944 * however QA team recommends that the invalid-key error
3945 * might be better to display for user experience.
3947 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3956 static void interface_state(GSupplicantInterface *interface)
3958 struct connman_network *network;
3959 struct connman_device *device;
3960 struct wifi_data *wifi;
3961 GSupplicantState state = g_supplicant_interface_get_state(interface);
3965 wifi = g_supplicant_interface_get_data(interface);
3967 DBG("wifi %p interface state %d", wifi, state);
3972 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3973 if (wifi->tethering_param) {
3974 g_free(wifi->tethering_param->ssid);
3975 g_free(wifi->tethering_param);
3976 wifi->tethering_param = NULL;
3980 device = wifi->device;
3984 if (g_supplicant_interface_get_ready(interface) &&
3985 !wifi->interface_ready) {
3986 wifi->interface_ready = true;
3987 finalize_interface_creation(wifi);
3990 network = wifi->network;
3995 case G_SUPPLICANT_STATE_SCANNING:
3996 if (wifi->connected)
3997 connman_network_set_connected(network, false);
4001 case G_SUPPLICANT_STATE_AUTHENTICATING:
4002 case G_SUPPLICANT_STATE_ASSOCIATING:
4003 #if defined TIZEN_EXT
4004 reset_autoscan(device);
4006 stop_autoscan(device);
4009 if (!wifi->connected)
4010 connman_network_set_associating(network, true);
4014 case G_SUPPLICANT_STATE_COMPLETED:
4015 #if defined TIZEN_EXT
4016 /* though it should be already reset: */
4017 reset_autoscan(device);
4019 wifi->assoc_retry_count = 0;
4021 wifi->scan_pending_network = NULL;
4023 /* should be cleared scanning flag */
4024 bool scanning = connman_device_get_scanning(device);
4026 connman_device_set_scanning(device,
4027 CONNMAN_SERVICE_TYPE_WIFI, false);
4028 connman_device_unref(device);
4031 if (!wifi->automaxspeed_timeout) {
4032 DBG("Going to start signalpoll timer!!");
4033 int ret = network_signalpoll(wifi);
4035 DBG("Fail to get max speed !!");
4037 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
4040 g_hash_table_remove_all(failed_bssids);
4042 /* though it should be already stopped: */
4043 stop_autoscan(device);
4046 if (!handle_wps_completion(interface, network, device, wifi))
4049 connman_network_set_connected(network, true);
4051 wifi->disconnect_code = 0;
4052 wifi->assoc_code = 0;
4053 wifi->load_shaping_retries = 0;
4056 case G_SUPPLICANT_STATE_DISCONNECTED:
4057 #if defined TIZEN_EXT
4058 connman_network_set_maxspeed(network, 0);
4060 if (wifi->automaxspeed_timeout != 0) {
4061 g_source_remove(wifi->automaxspeed_timeout);
4062 wifi->automaxspeed_timeout = 0;
4063 DBG("Remove signalpoll timer!!");
4067 * If we're in one of the idle modes, we have
4068 * not started association yet and thus setting
4069 * those ones to FALSE could cancel an association
4072 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4074 if (is_idle_wps(interface, wifi))
4080 #if defined TIZEN_EXT
4081 if (handle_assoc_status_code(interface, wifi)) {
4082 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4083 guint bssid_length = 0;
4086 bssid_length = g_slist_length(bssid_list);
4088 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4089 network_connect(network);
4093 wifi->load_shaping_retries = 0;
4096 g_hash_table_remove_all(failed_bssids);
4098 if (handle_assoc_status_code(interface, wifi))
4102 /* If previous state was 4way-handshake, then
4103 * it's either: psk was incorrect and thus we retry
4104 * or if we reach the maximum retries we declare the
4106 if (handle_4way_handshake_failure(interface,
4110 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4111 switch (wifi->disconnect_code) {
4112 case 1: /* Unspecified reason */
4113 /* Let's assume it's because we got blocked */
4115 case 6: /* Class 2 frame received from nonauthenticated STA */
4116 connman_network_set_error(network,
4117 CONNMAN_NETWORK_ERROR_BLOCKED);
4124 #if defined TIZEN_EXT
4125 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4126 * Retry association until its retry count is expired */
4127 if (handle_wifi_assoc_retry(network, wifi) == true) {
4128 throw_wifi_scan(wifi->device, scan_callback);
4129 wifi->scan_pending_network = wifi->network;
4133 if(wifi->disconnect_code > 0){
4134 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4135 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4139 connman_network_set_connected(network, false);
4140 connman_network_set_associating(network, false);
4141 wifi->disconnecting = false;
4143 start_autoscan(device);
4147 case G_SUPPLICANT_STATE_INACTIVE:
4148 #if defined TIZEN_EXT
4149 if (handle_wps_completion(interface, network, device, wifi) == false)
4152 connman_network_set_associating(network, false);
4153 start_autoscan(device);
4157 case G_SUPPLICANT_STATE_UNKNOWN:
4158 case G_SUPPLICANT_STATE_DISABLED:
4159 case G_SUPPLICANT_STATE_ASSOCIATED:
4160 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4161 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4165 old_connected = wifi->connected;
4166 wifi->state = state;
4168 /* Saving wpa_s state policy:
4169 * If connected and if the state changes are roaming related:
4170 * --> We stay connected
4172 * --> We are connected
4174 * --> We are not connected
4177 case G_SUPPLICANT_STATE_AUTHENTICATING:
4178 case G_SUPPLICANT_STATE_ASSOCIATING:
4179 case G_SUPPLICANT_STATE_ASSOCIATED:
4180 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4181 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4182 if (wifi->connected)
4183 connman_warn("Probably roaming right now!"
4184 " Staying connected...");
4186 case G_SUPPLICANT_STATE_SCANNING:
4187 wifi->connected = false;
4190 start_autoscan(device);
4192 case G_SUPPLICANT_STATE_COMPLETED:
4193 wifi->connected = true;
4196 wifi->connected = false;
4203 static void interface_removed(GSupplicantInterface *interface)
4205 const char *ifname = g_supplicant_interface_get_ifname(interface);
4206 struct wifi_data *wifi;
4208 DBG("ifname %s", ifname);
4210 wifi = g_supplicant_interface_get_data(interface);
4212 #if defined TIZEN_EXT_WIFI_MESH
4213 if (wifi && wifi->mesh_interface) {
4214 DBG("Notify mesh interface remove");
4215 connman_mesh_notify_interface_remove(true);
4216 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4217 g_free(mesh_info->parent_ifname);
4218 g_free(mesh_info->ifname);
4219 g_free(mesh_info->identifier);
4221 wifi->mesh_interface = false;
4222 wifi->mesh_info = NULL;
4228 wifi->interface = NULL;
4230 if (wifi && wifi->tethering)
4233 if (!wifi || !wifi->device) {
4234 DBG("wifi interface already removed");
4238 connman_device_set_powered(wifi->device, false);
4240 check_p2p_technology();
4241 #if defined TIZEN_EXT_WIFI_MESH
4242 check_mesh_technology();
4246 static void set_device_type(const char *type, char dev_type[17])
4248 const char *oui = "0050F204";
4249 const char *category = "0001";
4250 const char *sub_category = "0000";
4252 if (!g_strcmp0(type, "handset")) {
4254 sub_category = "0005";
4255 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4256 sub_category = "0001";
4257 else if (!g_strcmp0(type, "server"))
4258 sub_category = "0002";
4259 else if (!g_strcmp0(type, "laptop"))
4260 sub_category = "0005";
4261 else if (!g_strcmp0(type, "desktop"))
4262 sub_category = "0006";
4263 else if (!g_strcmp0(type, "tablet"))
4264 sub_category = "0009";
4265 else if (!g_strcmp0(type, "watch"))
4268 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4271 static void p2p_support(GSupplicantInterface *interface)
4273 char dev_type[17] = {};
4274 const char *hostname;
4281 if (!g_supplicant_interface_has_p2p(interface))
4284 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4285 DBG("Could not register P2P technology driver");
4289 hostname = connman_utsname_get_hostname();
4291 hostname = "ConnMan";
4293 set_device_type(connman_machine_get_type(), dev_type);
4294 g_supplicant_interface_set_p2p_device_config(interface,
4295 hostname, dev_type);
4296 connman_peer_driver_register(&peer_driver);
4299 static void scan_started(GSupplicantInterface *interface)
4304 static void scan_finished(GSupplicantInterface *interface)
4306 #if defined TIZEN_EXT
4307 struct wifi_data *wifi;
4308 bool is_associating = false;
4309 static bool is_scanning = true;
4314 #if defined TIZEN_EXT
4315 wifi = g_supplicant_interface_get_data(interface);
4316 if (wifi && wifi->scan_pending_network) {
4317 network_connect(wifi->scan_pending_network);
4318 wifi->scan_pending_network = NULL;
4321 //service state - associating
4322 if(!wifi || !wifi->network)
4325 is_associating = connman_network_get_associating(wifi->network);
4326 if(is_associating && is_scanning){
4327 is_scanning = false;
4328 DBG("send scan for connecting");
4329 throw_wifi_scan(wifi->device, scan_callback);
4340 static void ap_create_fail(GSupplicantInterface *interface)
4342 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4345 if ((wifi->tethering) && (wifi->tethering_param)) {
4346 DBG("%s create AP fail \n",
4347 g_supplicant_interface_get_ifname(wifi->interface));
4349 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4350 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4351 wifi->tethering = false;
4353 ret = tech_set_tethering(wifi->tethering_param->technology,
4354 wifi->tethering_param->ssid->ssid,
4355 wifi->tethering_param->ssid->passphrase,
4356 wifi->bridge, true);
4358 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4359 connman_technology_tethering_notify(wifi_technology,false);
4362 g_free(wifi->tethering_param->ssid);
4363 g_free(wifi->tethering_param);
4364 wifi->tethering_param = NULL;
4370 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4372 unsigned char strength;
4374 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4376 #if !defined TIZEN_EXT
4383 #if defined TIZEN_EXT_WIFI_MESH
4384 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4386 GSupplicantInterface *interface;
4387 struct wifi_data *wifi;
4388 const char *name, *security;
4389 struct connman_mesh *connman_mesh;
4390 struct wifi_mesh_info *mesh_info;
4391 const unsigned char *bssid;
4392 const char *identifier;
4397 interface = g_supplicant_network_get_interface(supplicant_network);
4398 wifi = g_supplicant_interface_get_data(interface);
4399 if (!wifi || !wifi->mesh_interface) {
4400 DBG("Virtual Mesh interface not created");
4404 bssid = g_supplicant_network_get_bssid(supplicant_network);
4405 address = g_malloc0(19);
4406 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4407 bssid[2], bssid[3], bssid[4], bssid[5]);
4409 identifier = g_supplicant_network_get_identifier(supplicant_network);
4410 name = g_supplicant_network_get_name(supplicant_network);
4411 security = g_supplicant_network_get_security(supplicant_network);
4412 frequency = g_supplicant_network_get_frequency(supplicant_network);
4414 mesh_info = wifi->mesh_info;
4415 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4419 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4421 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4422 connman_mesh_set_name(connman_mesh, name);
4423 connman_mesh_set_security(connman_mesh, security);
4424 connman_mesh_set_frequency(connman_mesh, frequency);
4425 connman_mesh_set_address(connman_mesh, address);
4426 connman_mesh_set_index(connman_mesh, mesh_info->index);
4427 connman_mesh_set_strength(connman_mesh,
4428 calculate_strength(supplicant_network));
4429 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4431 ret = connman_mesh_register(connman_mesh);
4432 if (ret == -EALREADY)
4433 DBG("Mesh Peer is already registered");
4439 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4441 GSupplicantInterface *interface;
4442 struct wifi_data *wifi;
4443 struct connman_mesh *connman_mesh;
4444 struct wifi_mesh_info *mesh_info;
4445 const char *identifier;
4447 interface = g_supplicant_network_get_interface(supplicant_network);
4448 wifi = g_supplicant_interface_get_data(interface);
4449 if (!wifi || !wifi->mesh_interface) {
4450 DBG("Virtual Mesh interface not created");
4454 identifier = g_supplicant_network_get_identifier(supplicant_network);
4456 DBG("Failed to get Mesh Peer identifier");
4460 mesh_info = wifi->mesh_info;
4461 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4463 /* Do not unregister connected mesh peer */
4464 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4465 DBG("Mesh Peer %s is connected", identifier);
4468 DBG("Mesh Peer identifier %s removed", identifier);
4469 connman_mesh_unregister(connman_mesh);
4474 static void network_added(GSupplicantNetwork *supplicant_network)
4476 struct connman_network *network;
4477 GSupplicantInterface *interface;
4478 struct wifi_data *wifi;
4479 const char *name, *identifier, *security, *group, *mode;
4480 const unsigned char *ssid;
4481 unsigned int ssid_len;
4485 bool wps_advertizing;
4487 #if defined TIZEN_EXT
4488 GSList *vsie_list = NULL;
4489 const unsigned char *country_code;
4490 ieee80211_modes_e phy_mode;
4493 mode = g_supplicant_network_get_mode(supplicant_network);
4494 identifier = g_supplicant_network_get_identifier(supplicant_network);
4496 DBG("%s", identifier);
4498 if (!g_strcmp0(mode, "adhoc"))
4501 #if defined TIZEN_EXT_WIFI_MESH
4502 if (!g_strcmp0(mode, "mesh")) {
4503 mesh_peer_added(supplicant_network);
4508 interface = g_supplicant_network_get_interface(supplicant_network);
4509 wifi = g_supplicant_interface_get_data(interface);
4510 name = g_supplicant_network_get_name(supplicant_network);
4511 security = g_supplicant_network_get_security(supplicant_network);
4512 group = g_supplicant_network_get_identifier(supplicant_network);
4513 wps = g_supplicant_network_get_wps(supplicant_network);
4514 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4515 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4516 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4517 supplicant_network);
4522 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4524 network = connman_device_get_network(wifi->device, identifier);
4527 network = connman_network_create(identifier,
4528 CONNMAN_NETWORK_TYPE_WIFI);
4532 connman_network_set_index(network, wifi->index);
4534 if (connman_device_add_network(wifi->device, network) < 0) {
4535 connman_network_unref(network);
4539 wifi->networks = g_slist_prepend(wifi->networks, network);
4542 if (name && name[0] != '\0')
4543 connman_network_set_name(network, name);
4545 connman_network_set_blob(network, "WiFi.SSID",
4547 #if defined TIZEN_EXT
4548 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4550 connman_network_set_vsie_list(network, vsie_list);
4552 DBG("vsie_list is NULL");
4553 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4554 connman_network_set_countrycode(network, country_code);
4555 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4556 connman_network_set_phy_mode(network, phy_mode);
4558 connman_network_set_string(network, "WiFi.Security", security);
4559 connman_network_set_strength(network,
4560 calculate_strength(supplicant_network));
4561 connman_network_set_bool(network, "WiFi.WPS", wps);
4564 /* Is AP advertizing for WPS association?
4565 * If so, we decide to use WPS by default */
4566 if (wps_ready && wps_pbc &&
4568 #if !defined TIZEN_EXT
4569 connman_network_set_bool(network, "WiFi.UseWPS", true);
4571 DBG("wps is activating by ap but ignore it.");
4576 connman_network_set_frequency(network,
4577 g_supplicant_network_get_frequency(supplicant_network));
4578 #if defined TIZEN_EXT
4579 connman_network_set_bssid(network,
4580 g_supplicant_network_get_bssid(supplicant_network));
4581 connman_network_set_maxrate(network,
4582 g_supplicant_network_get_maxrate(supplicant_network));
4583 connman_network_set_enc_mode(network,
4584 g_supplicant_network_get_enc_mode(supplicant_network));
4585 connman_network_set_rsn_mode(network,
4586 g_supplicant_network_get_rsn_mode(supplicant_network));
4587 connman_network_set_keymgmt(network,
4588 g_supplicant_network_get_keymgmt(supplicant_network));
4589 connman_network_set_bool(network, "WiFi.HS20AP",
4590 g_supplicant_network_is_hs20AP(supplicant_network));
4591 connman_network_set_bssid_list(network,
4592 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4594 connman_network_set_available(network, true);
4595 connman_network_set_string(network, "WiFi.Mode", mode);
4597 #if defined TIZEN_EXT
4602 connman_network_set_group(network, group);
4604 #if defined TIZEN_EXT
4605 if (wifi_first_scan == true)
4606 found_with_first_scan = true;
4609 if (wifi->hidden && ssid) {
4610 #if defined TIZEN_EXT
4611 if (network_security(wifi->hidden->security) ==
4612 network_security(security) &&
4614 if (!g_strcmp0(wifi->hidden->security, security) &&
4616 wifi->hidden->ssid_len == ssid_len &&
4617 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4618 connman_network_connect_hidden(network,
4619 wifi->hidden->identity,
4620 wifi->hidden->passphrase,
4621 wifi->hidden->user_data);
4622 wifi->hidden->user_data = NULL;
4623 hidden_free(wifi->hidden);
4624 wifi->hidden = NULL;
4629 static void network_removed(GSupplicantNetwork *network)
4631 GSupplicantInterface *interface;
4632 struct wifi_data *wifi;
4633 const char *name, *identifier;
4634 struct connman_network *connman_network;
4636 #if defined TIZEN_EXT_WIFI_MESH
4638 mode = g_supplicant_network_get_mode(network);
4639 if (!g_strcmp0(mode, "mesh")) {
4640 mesh_peer_removed(network);
4645 interface = g_supplicant_network_get_interface(network);
4646 wifi = g_supplicant_interface_get_data(interface);
4647 identifier = g_supplicant_network_get_identifier(network);
4648 name = g_supplicant_network_get_name(network);
4650 DBG("name %s", name);
4655 connman_network = connman_device_get_network(wifi->device, identifier);
4656 if (!connman_network)
4659 #if defined TIZEN_EXT
4660 if (connman_network == wifi->scan_pending_network)
4661 wifi->scan_pending_network = NULL;
4663 if (connman_network == wifi->pending_network)
4664 wifi->pending_network = NULL;
4666 if(connman_network_get_connecting(connman_network) == true){
4667 connman_network_set_connected(connman_network, false);
4671 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4673 connman_device_remove_network(wifi->device, connman_network);
4674 connman_network_unref(connman_network);
4677 static void network_changed(GSupplicantNetwork *network, const char *property)
4679 GSupplicantInterface *interface;
4680 struct wifi_data *wifi;
4681 const char *name, *identifier;
4682 struct connman_network *connman_network;
4684 #if defined TIZEN_EXT
4685 const unsigned char *bssid;
4686 unsigned int maxrate;
4689 const unsigned char *country_code;
4690 ieee80211_modes_e phy_mode;
4694 interface = g_supplicant_network_get_interface(network);
4695 wifi = g_supplicant_interface_get_data(interface);
4696 identifier = g_supplicant_network_get_identifier(network);
4697 name = g_supplicant_network_get_name(network);
4699 DBG("name %s", name);
4704 connman_network = connman_device_get_network(wifi->device, identifier);
4705 if (!connman_network)
4708 if (g_str_equal(property, "Signal")) {
4709 connman_network_set_strength(connman_network,
4710 calculate_strength(network));
4711 connman_network_update(connman_network);
4714 #if defined TIZEN_EXT
4715 bssid = g_supplicant_network_get_bssid(network);
4716 maxrate = g_supplicant_network_get_maxrate(network);
4717 frequency = g_supplicant_network_get_frequency(network);
4718 wps = g_supplicant_network_get_wps(network);
4719 phy_mode = g_supplicant_network_get_phy_mode(network);
4721 connman_network_set_bssid(connman_network, bssid);
4722 connman_network_set_maxrate(connman_network, maxrate);
4723 connman_network_set_frequency(connman_network, frequency);
4724 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4725 country_code = g_supplicant_network_get_countrycode(network);
4726 connman_network_set_countrycode(connman_network, country_code);
4727 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4728 connman_network_set_bssid_list(connman_network, bssid_list);
4729 connman_network_set_phy_mode(connman_network, phy_mode);
4731 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4732 connman_network_get_associating(connman_network))
4733 network_connect(connman_network);
4737 static void network_associated(GSupplicantNetwork *network)
4739 GSupplicantInterface *interface;
4740 struct wifi_data *wifi;
4741 struct connman_network *connman_network;
4742 const char *identifier;
4746 interface = g_supplicant_network_get_interface(network);
4750 wifi = g_supplicant_interface_get_data(interface);
4754 identifier = g_supplicant_network_get_identifier(network);
4756 connman_network = connman_device_get_network(wifi->device, identifier);
4757 if (!connman_network)
4760 if (wifi->network) {
4761 if (wifi->network == connman_network)
4765 * This should never happen, we got associated with
4766 * a network different than the one we were expecting.
4768 DBG("Associated to %p while expecting %p",
4769 connman_network, wifi->network);
4771 connman_network_set_associating(wifi->network, false);
4774 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4776 wifi->network = connman_network_ref(connman_network);
4780 * Interface state changes callback (interface_state) is always
4781 * called before network_associated callback thus we need to call
4782 * interface_state again in order to process the new state now that
4783 * we have the network properly set.
4785 interface_state(interface);
4788 static void apply_peer_services(GSupplicantPeer *peer,
4789 struct connman_peer *connman_peer)
4791 const unsigned char *data;
4796 connman_peer_reset_services(connman_peer);
4798 data = g_supplicant_peer_get_widi_ies(peer, &length);
4800 connman_peer_add_service(connman_peer,
4801 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4805 static void add_station(const char *mac)
4807 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4811 static void remove_station(const char *mac)
4813 connman_technology_tethering_remove_station(mac);
4816 static void peer_found(GSupplicantPeer *peer)
4818 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4819 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4820 struct connman_peer *connman_peer;
4821 const char *identifier, *name;
4823 #if defined TIZEN_EXT
4827 identifier = g_supplicant_peer_get_identifier(peer);
4828 name = g_supplicant_peer_get_name(peer);
4830 DBG("ident: %s", identifier);
4832 connman_peer = connman_peer_get(wifi->device, identifier);
4836 connman_peer = connman_peer_create(identifier);
4837 connman_peer_set_name(connman_peer, name);
4838 connman_peer_set_device(connman_peer, wifi->device);
4839 apply_peer_services(peer, connman_peer);
4841 ret = connman_peer_register(connman_peer);
4842 if (ret < 0 && ret != -EALREADY)
4843 connman_peer_unref(connman_peer);
4845 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4848 static void peer_lost(GSupplicantPeer *peer)
4850 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4851 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4852 struct connman_peer *connman_peer;
4853 const char *identifier;
4858 identifier = g_supplicant_peer_get_identifier(peer);
4860 DBG("ident: %s", identifier);
4862 connman_peer = connman_peer_get(wifi->device, identifier);
4864 if (wifi->p2p_connecting &&
4865 wifi->pending_peer == connman_peer) {
4866 peer_connect_timeout(wifi);
4868 connman_peer_unregister(connman_peer);
4869 connman_peer_unref(connman_peer);
4872 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4875 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4877 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4878 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4879 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4880 struct connman_peer *connman_peer;
4881 const char *identifier;
4883 identifier = g_supplicant_peer_get_identifier(peer);
4885 DBG("ident: %s", identifier);
4890 connman_peer = connman_peer_get(wifi->device, identifier);
4895 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4896 apply_peer_services(peer, connman_peer);
4897 connman_peer_services_changed(connman_peer);
4899 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4900 if (!g_supplicant_peer_is_in_a_group(peer))
4901 p_state = CONNMAN_PEER_STATE_IDLE;
4903 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4905 case G_SUPPLICANT_PEER_GROUP_STARTED:
4907 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4908 p_state = CONNMAN_PEER_STATE_IDLE;
4910 case G_SUPPLICANT_PEER_GROUP_JOINED:
4911 connman_peer_set_iface_address(connman_peer,
4912 g_supplicant_peer_get_iface_address(peer));
4914 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4915 p_state = CONNMAN_PEER_STATE_IDLE;
4917 case G_SUPPLICANT_PEER_GROUP_FAILED:
4918 if (g_supplicant_peer_has_requested_connection(peer))
4919 p_state = CONNMAN_PEER_STATE_IDLE;
4921 p_state = CONNMAN_PEER_STATE_FAILURE;
4925 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4926 p_state == CONNMAN_PEER_STATE_FAILURE) {
4927 if (wifi->p2p_connecting
4928 && connman_peer == wifi->pending_peer)
4929 peer_cancel_timeout(wifi);
4931 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4934 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4937 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4938 GSupplicantInterface *g_iface;
4939 struct wifi_data *g_wifi;
4941 g_iface = g_supplicant_peer_get_group_interface(peer);
4945 g_wifi = g_supplicant_interface_get_data(g_iface);
4949 connman_peer_set_as_master(connman_peer,
4950 !g_supplicant_peer_is_client(peer));
4951 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4954 * If wpa_supplicant didn't create a dedicated p2p-group
4955 * interface then mark this interface as p2p_device to avoid
4956 * scan and auto-scan are launched on it while P2P is connected.
4958 if (!g_list_find(p2p_iface_list, g_wifi))
4959 wifi->p2p_device = true;
4962 connman_peer_set_state(connman_peer, p_state);
4965 static void peer_request(GSupplicantPeer *peer)
4967 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4968 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4969 struct connman_peer *connman_peer;
4970 const char *identifier;
4972 #if defined TIZEN_EXT
4977 identifier = g_supplicant_peer_get_identifier(peer);
4979 DBG("ident: %s", identifier);
4981 connman_peer = connman_peer_get(wifi->device, identifier);
4985 connman_peer_request_connection(connman_peer);
4988 #if defined TIZEN_EXT
4989 static void system_power_off(void)
4992 struct wifi_data *wifi;
4993 struct connman_service *service;
4994 struct connman_ipconfig *ipconfig_ipv4;
4996 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4997 for (list = iface_list; list; list = list->next) {
5000 if (wifi->network != NULL) {
5001 service = connman_service_lookup_from_network(wifi->network);
5002 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5003 __connman_dhcp_stop(ipconfig_ipv4);
5009 static void network_merged(GSupplicantNetwork *network)
5011 GSupplicantInterface *interface;
5012 GSupplicantState state;
5013 struct wifi_data *wifi;
5014 const char *identifier;
5015 struct connman_network *connman_network;
5019 interface = g_supplicant_network_get_interface(network);
5023 state = g_supplicant_interface_get_state(interface);
5024 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5027 wifi = g_supplicant_interface_get_data(interface);
5031 identifier = g_supplicant_network_get_identifier(network);
5033 connman_network = connman_device_get_network(wifi->device, identifier);
5034 if (!connman_network)
5037 DBG("merged identifier %s", identifier);
5039 if (wifi->connected == FALSE) {
5041 case G_SUPPLICANT_STATE_AUTHENTICATING:
5042 case G_SUPPLICANT_STATE_ASSOCIATING:
5043 case G_SUPPLICANT_STATE_ASSOCIATED:
5044 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5045 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5046 connman_network_set_associating(connman_network, TRUE);
5048 case G_SUPPLICANT_STATE_COMPLETED:
5049 connman_network_set_connected(connman_network, TRUE);
5052 DBG("Not handled the state : %d", state);
5057 ishs20AP = g_supplicant_network_is_hs20AP(network);
5060 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5061 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5062 connman_network_set_string(connman_network, "WiFi.EAP",
5064 connman_network_set_string(connman_network, "WiFi.Identity",
5065 g_supplicant_network_get_identity(network));
5066 connman_network_set_string(connman_network, "WiFi.Phase2",
5067 g_supplicant_network_get_phase2(network));
5072 wifi->network = connman_network;
5075 static void assoc_failed(void *user_data)
5077 struct connman_network *network = user_data;
5078 connman_network_set_associating(network, false);
5082 static void debug(const char *str)
5084 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5085 connman_debug("%s", str);
5088 static void disconnect_reasoncode(GSupplicantInterface *interface,
5091 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5094 wifi->disconnect_code = reasoncode;
5098 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5100 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5103 wifi->assoc_code = status_code;
5107 static const GSupplicantCallbacks callbacks = {
5108 .system_ready = system_ready,
5109 .system_killed = system_killed,
5110 .interface_added = interface_added,
5111 .interface_state = interface_state,
5112 .interface_removed = interface_removed,
5113 .p2p_support = p2p_support,
5114 .scan_started = scan_started,
5115 .scan_finished = scan_finished,
5116 .ap_create_fail = ap_create_fail,
5117 .network_added = network_added,
5118 .network_removed = network_removed,
5119 .network_changed = network_changed,
5120 .network_associated = network_associated,
5121 .add_station = add_station,
5122 .remove_station = remove_station,
5123 .peer_found = peer_found,
5124 .peer_lost = peer_lost,
5125 .peer_changed = peer_changed,
5126 .peer_request = peer_request,
5127 #if defined TIZEN_EXT
5128 .system_power_off = system_power_off,
5129 .network_merged = network_merged,
5130 .assoc_failed = assoc_failed,
5133 .disconnect_reasoncode = disconnect_reasoncode,
5134 .assoc_status_code = assoc_status_code,
5135 #if defined TIZEN_EXT_WIFI_MESH
5136 .mesh_support = mesh_support,
5137 .mesh_group_started = mesh_group_started,
5138 .mesh_group_removed = mesh_group_removed,
5139 .mesh_peer_connected = mesh_peer_connected,
5140 .mesh_peer_disconnected = mesh_peer_disconnected,
5145 static int tech_probe(struct connman_technology *technology)
5147 wifi_technology = technology;
5152 static void tech_remove(struct connman_technology *technology)
5154 wifi_technology = NULL;
5157 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5158 const char *passphrase)
5160 GSupplicantSSID *ap;
5162 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5166 ap->mode = G_SUPPLICANT_MODE_MASTER;
5167 #if defined TIZEN_EXT
5168 ap->ssid = (void *) ssid;
5172 ap->ssid_len = strlen(ssid);
5176 if (!passphrase || strlen(passphrase) == 0) {
5177 ap->security = G_SUPPLICANT_SECURITY_NONE;
5178 ap->passphrase = NULL;
5180 ap->security = G_SUPPLICANT_SECURITY_PSK;
5181 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5182 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5183 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5184 ap->passphrase = passphrase;
5190 static void ap_start_callback(int result, GSupplicantInterface *interface,
5193 struct wifi_tethering_info *info = user_data;
5195 DBG("result %d index %d bridge %s",
5196 result, info->wifi->index, info->wifi->bridge);
5198 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5199 connman_inet_remove_from_bridge(info->wifi->index,
5200 info->wifi->bridge);
5202 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5203 connman_technology_tethering_notify(info->technology, false);
5204 g_free(info->wifi->tethering_param->ssid);
5205 g_free(info->wifi->tethering_param);
5206 info->wifi->tethering_param = NULL;
5210 g_free(info->ifname);
5214 static void ap_create_callback(int result,
5215 GSupplicantInterface *interface,
5218 struct wifi_tethering_info *info = user_data;
5220 DBG("result %d ifname %s", result,
5221 g_supplicant_interface_get_ifname(interface));
5223 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5224 connman_inet_remove_from_bridge(info->wifi->index,
5225 info->wifi->bridge);
5227 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5228 connman_technology_tethering_notify(info->technology, false);
5229 g_free(info->wifi->tethering_param->ssid);
5230 g_free(info->wifi->tethering_param);
5231 info->wifi->tethering_param = NULL;
5235 g_free(info->ifname);
5241 info->wifi->interface = interface;
5242 g_supplicant_interface_set_data(interface, info->wifi);
5244 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5245 connman_error("Failed to set interface ap_scan property");
5247 g_supplicant_interface_connect(interface, info->ssid,
5248 ap_start_callback, info);
5251 static void sta_remove_callback(int result,
5252 GSupplicantInterface *interface,
5255 struct wifi_tethering_info *info = user_data;
5256 const char *driver = connman_option_get_string("wifi");
5258 DBG("ifname %s result %d ", info->ifname, result);
5260 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5261 info->wifi->tethering = false;
5262 connman_technology_tethering_notify(info->technology, false);
5264 g_free(info->ifname);
5268 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5269 g_free(info->wifi->tethering_param->ssid);
5270 g_free(info->wifi->tethering_param);
5271 info->wifi->tethering_param = NULL;
5276 info->wifi->interface = NULL;
5278 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5283 static int enable_wifi_tethering(struct connman_technology *technology,
5284 const char *bridge, const char *identifier,
5285 const char *passphrase, bool available)
5288 GSupplicantInterface *interface;
5289 struct wifi_data *wifi;
5290 struct wifi_tethering_info *info;
5295 for (list = iface_list; list; list = list->next) {
5298 DBG("wifi %p network %p pending_network %p", wifi,
5299 wifi->network, wifi->pending_network);
5301 interface = wifi->interface;
5306 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5309 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5311 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5312 DBG("%s does not support AP mode (detected)", ifname);
5316 mode = g_supplicant_interface_get_mode(interface);
5317 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5318 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5319 DBG("%s does not support AP mode (capability)", ifname);
5323 if (wifi->network && available)
5326 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5330 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5331 if (!wifi->tethering_param) {
5337 info->technology = technology;
5338 info->wifi->bridge = bridge;
5339 info->ssid = ssid_ap_init(identifier, passphrase);
5343 info->ifname = g_strdup(ifname);
5347 wifi->tethering_param->technology = technology;
5348 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5349 if (!wifi->tethering_param->ssid)
5352 info->wifi->tethering = true;
5353 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5355 berr = connman_technology_tethering_notify(technology, true);
5359 err = g_supplicant_interface_remove(interface,
5360 sta_remove_callback,
5363 DBG("tethering wifi %p ifname %s", wifi, ifname);
5368 g_free(info->ifname);
5371 g_free(wifi->tethering_param);
5372 wifi->tethering_param = NULL;
5375 * Remove bridge if it was correctly created but remove
5376 * operation failed. Instead, if bridge creation failed then
5377 * break out and do not try again on another interface,
5378 * bridge set-up does not depend on it.
5381 connman_technology_tethering_notify(technology, false);
5389 static int tech_set_tethering(struct connman_technology *technology,
5390 const char *identifier, const char *passphrase,
5391 const char *bridge, bool enabled)
5394 struct wifi_data *wifi;
5400 for (list = iface_list; list; list = list->next) {
5403 if (wifi->tethering) {
5404 wifi->tethering = false;
5406 connman_inet_remove_from_bridge(wifi->index,
5408 wifi->bridged = false;
5412 connman_technology_tethering_notify(technology, false);
5417 DBG("trying tethering for available devices");
5418 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5422 DBG("trying tethering for any device");
5423 err = enable_wifi_tethering(technology, bridge, identifier,
5430 static void regdom_callback(int result, const char *alpha2, void *user_data)
5434 if (!wifi_technology)
5440 connman_technology_regdom_notify(wifi_technology, alpha2);
5443 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5445 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5448 static struct connman_technology_driver tech_driver = {
5450 .type = CONNMAN_SERVICE_TYPE_WIFI,
5451 .probe = tech_probe,
5452 .remove = tech_remove,
5453 .set_tethering = tech_set_tethering,
5454 .set_regdom = tech_set_regdom,
5457 static int wifi_init(void)
5461 err = connman_network_driver_register(&network_driver);
5465 err = g_supplicant_register(&callbacks);
5467 connman_network_driver_unregister(&network_driver);
5471 err = connman_technology_driver_register(&tech_driver);
5473 g_supplicant_unregister(&callbacks);
5474 connman_network_driver_unregister(&network_driver);
5478 #if defined TIZEN_EXT
5479 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5484 static void wifi_exit(void)
5488 connman_technology_driver_unregister(&tech_driver);
5490 g_supplicant_unregister(&callbacks);
5492 connman_network_driver_unregister(&network_driver);
5494 #if defined TIZEN_EXT
5495 g_hash_table_unref(failed_bssids);
5499 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5500 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)