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 struct last_connected {
1538 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1540 GTimeVal *aval = (GTimeVal *)a;
1541 GTimeVal *bval = (GTimeVal *)b;
1543 /* Note that the sort order is descending */
1544 if (aval->tv_sec < bval->tv_sec)
1547 if (aval->tv_sec > bval->tv_sec)
1553 static void free_entry(gpointer data)
1555 struct last_connected *entry = data;
1557 g_free(entry->ssid);
1561 static void wifi_remove(struct connman_device *device)
1563 struct wifi_data *wifi = connman_device_get_data(device);
1565 DBG("device %p wifi %p", device, wifi);
1570 stop_autoscan(device);
1572 if (wifi->p2p_device)
1573 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1575 iface_list = g_list_remove(iface_list, wifi);
1577 check_p2p_technology();
1578 #if defined TIZEN_EXT_WIFI_MESH
1579 check_mesh_technology();
1582 remove_pending_wifi_device(wifi);
1584 if (wifi->p2p_find_timeout) {
1585 g_source_remove(wifi->p2p_find_timeout);
1586 connman_device_unref(wifi->device);
1589 if (wifi->p2p_connection_timeout)
1590 g_source_remove(wifi->p2p_connection_timeout);
1592 #if defined TIZEN_EXT
1593 if (wifi->automaxspeed_timeout != 0) {
1594 g_source_remove(wifi->automaxspeed_timeout);
1595 wifi->automaxspeed_timeout = 0;
1599 remove_networks(device, wifi);
1602 connman_device_set_powered(device, false);
1603 connman_device_set_data(device, NULL);
1604 connman_device_unref(wifi->device);
1605 connman_rtnl_remove_watch(wifi->watch);
1607 g_supplicant_interface_set_data(wifi->interface, NULL);
1609 g_supplicant_interface_cancel(wifi->interface);
1611 if (wifi->scan_params)
1612 g_supplicant_free_scan_params(wifi->scan_params);
1613 #if defined TIZEN_EXT
1614 if (wifi->hidden_scan_params) {
1615 while (wifi->hidden_scan_params->ssids) {
1616 struct scan_ssid *ssid;
1617 ssid = wifi->hidden_scan_params->ssids->data;
1618 wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
1620 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1624 g_free(wifi->autoscan);
1625 g_free(wifi->identifier);
1629 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1633 for (iter = list; iter; iter = g_slist_next(iter)) {
1634 struct scan_ssid *scan_ssid = iter->data;
1636 if (ssid_len == scan_ssid->ssid_len &&
1637 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1644 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1645 int freq, GSupplicantScanParams *scan_data,
1646 int driver_max_scan_ssids, char *ssid_name)
1649 struct scan_ssid *scan_ssid;
1651 if ((driver_max_scan_ssids == 0 ||
1652 driver_max_scan_ssids > scan_data->num_ssids) &&
1653 (hex_ssid || raw_ssid)) {
1655 unsigned int j = 0, hex;
1658 size_t hex_ssid_len = strlen(hex_ssid);
1660 ssid = g_try_malloc0(hex_ssid_len / 2);
1664 for (i = 0; i < hex_ssid_len; i += 2) {
1665 sscanf(hex_ssid + i, "%02x", &hex);
1674 * If we have already added hidden AP to the list,
1675 * then do not do it again. This might happen if you have
1676 * used or are using multiple wifi cards, so in that case
1677 * you might have multiple service files for same AP.
1679 if (is_duplicate(scan_data->ssids, ssid, j)) {
1685 scan_ssid = g_try_new(struct scan_ssid, 1);
1692 memcpy(scan_ssid->ssid, ssid, j);
1693 scan_ssid->ssid_len = j;
1694 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1697 scan_data->num_ssids++;
1699 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1700 scan_data->num_ssids);
1707 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1709 if (!scan_data->freqs) {
1710 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1711 if (!scan_data->freqs) {
1712 g_slist_free_full(scan_data->ssids, g_free);
1716 scan_data->num_freqs = 1;
1717 scan_data->freqs[0] = freq;
1719 bool duplicate = false;
1721 /* Don't add duplicate entries */
1722 for (i = 0; i < scan_data->num_freqs; i++) {
1723 if (scan_data->freqs[i] == freq) {
1730 scan_data->num_freqs++;
1731 scan_data->freqs = g_try_realloc(scan_data->freqs,
1732 sizeof(uint16_t) * scan_data->num_freqs);
1733 if (!scan_data->freqs) {
1734 g_slist_free_full(scan_data->ssids, g_free);
1737 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1744 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1746 struct connman_config_entry **entries;
1752 int num_ssids = 0, add_param_failed = 0;
1753 #if defined TIZEN_EXT
1754 GSequenceIter *iter;
1755 GSequence *latest_list;
1756 struct last_connected *entry;
1759 latest_list = g_sequence_new(free_entry);
1763 services = connman_storage_get_services();
1764 for (i = 0; services && services[i]; i++) {
1765 if (strncmp(services[i], "wifi_", 5) != 0)
1768 keyfile = connman_storage_load_service(services[i]);
1772 value = g_key_file_get_boolean(keyfile,
1773 services[i], "Hidden", NULL);
1775 g_key_file_free(keyfile);
1779 value = g_key_file_get_boolean(keyfile,
1780 services[i], "Favorite", NULL);
1782 g_key_file_free(keyfile);
1786 #if defined TIZEN_EXT
1787 value = g_key_file_get_boolean(keyfile,
1788 services[i], "AutoConnect", NULL);
1790 g_key_file_free(keyfile);
1794 gchar *str = g_key_file_get_string(keyfile,
1795 services[i], "Modified", NULL);
1797 g_key_file_free(keyfile);
1800 g_time_val_from_iso8601(str, &modified);
1804 ssid = g_key_file_get_string(keyfile,
1805 services[i], "SSID", NULL);
1807 name = g_key_file_get_string(keyfile, services[i], "Name",
1810 #if defined TIZEN_EXT
1811 entry = g_try_new(struct last_connected, 1);
1813 g_sequence_free(latest_list);
1816 g_key_file_free(keyfile);
1820 entry->modified = modified;
1823 g_sequence_insert_sorted(latest_list, entry,
1826 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1835 g_key_file_free(keyfile);
1838 #if defined TIZEN_EXT
1839 gint length = g_sequence_get_length(latest_list);
1840 iter = g_sequence_get_begin_iter(latest_list);
1842 for (i = 0; i < length; i++) {
1843 entry = g_sequence_get(iter);
1845 ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid);
1851 iter = g_sequence_iter_next(iter);
1854 g_sequence_free(latest_list);
1858 * Check if there are any hidden AP that needs to be provisioned.
1860 entries = connman_config_get_entries("wifi");
1861 for (i = 0; entries && entries[i]; i++) {
1864 if (!entries[i]->hidden)
1867 if (!entries[i]->ssid) {
1868 ssid = entries[i]->name;
1871 ssid = entries[i]->ssid;
1872 len = entries[i]->ssid_len;
1878 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1885 connman_config_free_entries(entries);
1887 if (add_param_failed > 0)
1888 DBG("Unable to scan %d out of %d SSIDs",
1889 add_param_failed, num_ssids);
1891 g_strfreev(services);
1896 static int get_hidden_connections_params(struct wifi_data *wifi,
1897 GSupplicantScanParams *scan_params)
1899 int driver_max_ssids, i;
1900 GSupplicantScanParams *orig_params;
1903 * Scan hidden networks so that we can autoconnect to them.
1904 * We will assume 1 as a default number of ssid to scan.
1906 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1908 if (driver_max_ssids == 0)
1909 driver_max_ssids = 1;
1911 DBG("max ssids %d", driver_max_ssids);
1913 #if defined TIZEN_EXT
1914 if (!wifi->hidden_scan_params) {
1915 wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1916 if (!wifi->hidden_scan_params)
1919 if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
1920 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1921 wifi->hidden_scan_params = NULL;
1927 orig_params = wifi->hidden_scan_params;
1929 if (!wifi->scan_params) {
1930 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1931 if (!wifi->scan_params)
1934 if (get_hidden_connections(wifi->scan_params) == 0) {
1935 g_supplicant_free_scan_params(wifi->scan_params);
1936 wifi->scan_params = NULL;
1942 orig_params = wifi->scan_params;
1945 /* Let's transfer driver_max_ssids params */
1946 for (i = 0; i < driver_max_ssids; i++) {
1947 struct scan_ssid *ssid;
1949 #if defined TIZEN_EXT
1950 if (!wifi->hidden_scan_params->ssids)
1952 if (!wifi->scan_params->ssids)
1956 ssid = orig_params->ssids->data;
1957 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1958 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1962 scan_params->num_ssids = i;
1963 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1965 scan_params->freqs = g_memdup(orig_params->freqs,
1966 sizeof(uint16_t) * orig_params->num_freqs);
1967 if (!scan_params->freqs)
1970 scan_params->num_freqs = orig_params->num_freqs;
1975 orig_params->num_ssids -= scan_params->num_ssids;
1977 return scan_params->num_ssids;
1980 g_slist_free_full(scan_params->ssids, g_free);
1981 #if defined TIZEN_EXT
1982 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1983 wifi->hidden_scan_params = NULL;
1985 g_supplicant_free_scan_params(wifi->scan_params);
1986 wifi->scan_params = NULL;
1992 static int throw_wifi_scan(struct connman_device *device,
1993 GSupplicantInterfaceCallback callback)
1995 struct wifi_data *wifi = connman_device_get_data(device);
2001 DBG("device %p %p", device, wifi->interface);
2003 if (wifi->tethering)
2005 #if defined TIZEN_EXT
2006 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
2008 if (connman_device_get_scanning(device))
2012 connman_device_ref(device);
2014 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2017 connman_device_set_scanning(device,
2018 CONNMAN_SERVICE_TYPE_WIFI, true);
2020 connman_device_unref(device);
2025 static void hidden_free(struct hidden_params *hidden)
2030 if (hidden->scan_params)
2031 g_supplicant_free_scan_params(hidden->scan_params);
2032 g_free(hidden->identity);
2033 g_free(hidden->passphrase);
2034 g_free(hidden->security);
2038 #if defined TIZEN_EXT
2039 static void service_state_changed(struct connman_service *service,
2040 enum connman_service_state state);
2042 static int network_connect(struct connman_network *network);
2044 static struct connman_notifier notifier = {
2046 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
2047 .service_state_changed = service_state_changed,
2050 static void service_state_changed(struct connman_service *service,
2051 enum connman_service_state state)
2053 enum connman_service_type type;
2055 type = connman_service_get_type(service);
2056 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2059 DBG("service %p state %d", service, state);
2062 case CONNMAN_SERVICE_STATE_READY:
2063 case CONNMAN_SERVICE_STATE_ONLINE:
2064 case CONNMAN_SERVICE_STATE_FAILURE:
2065 connman_notifier_unregister(¬ifier);
2066 is_wifi_notifier_registered = FALSE;
2068 __connman_device_request_scan(type);
2076 static void scan_callback_hidden(int result,
2077 GSupplicantInterface *interface, void *user_data);
2080 static void scan_callback(int result, GSupplicantInterface *interface,
2083 struct connman_device *device = user_data;
2084 struct wifi_data *wifi = connman_device_get_data(device);
2087 DBG("result %d wifi %p", result, wifi);
2090 if (wifi->hidden && !wifi->postpone_hidden) {
2091 connman_network_clear_hidden(wifi->hidden->user_data);
2092 hidden_free(wifi->hidden);
2093 wifi->hidden = NULL;
2096 if (wifi->scan_params) {
2097 g_supplicant_free_scan_params(wifi->scan_params);
2098 wifi->scan_params = NULL;
2101 #if defined TIZEN_EXT
2102 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2103 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2104 wifi->hidden_scan_params = NULL;
2110 connman_device_reset_scanning(device);
2112 /* User is connecting to a hidden AP, let's wait for finished event */
2113 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2114 GSupplicantScanParams *scan_params;
2117 wifi->postpone_hidden = false;
2118 scan_params = wifi->hidden->scan_params;
2119 wifi->hidden->scan_params = NULL;
2121 reset_autoscan(device);
2123 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2124 scan_callback, device);
2128 /* On error, let's recall scan_callback, which will cleanup */
2129 return scan_callback(ret, interface, user_data);
2132 #if defined TIZEN_EXT
2133 if (wifi && wifi->allow_full_scan) {
2135 DBG("Trigger Full Channel Scan");
2136 wifi->allow_full_scan = FALSE;
2138 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2139 scan_callback_hidden, device);
2143 /* On error, let's recall scan_callback, which will cleanup */
2144 return scan_callback(ret, interface, user_data);
2148 scanning = connman_device_get_scanning(device);
2150 connman_device_set_scanning(device,
2151 CONNMAN_SERVICE_TYPE_WIFI, false);
2153 if (result != -ENOLINK)
2154 #if defined TIZEN_EXT
2157 start_autoscan(device);
2160 * If we are here then we were scanning; however, if we are
2161 * also mid-flight disabling the interface, then wifi_disable
2162 * has already cleared the device scanning state and
2163 * unreferenced the device, obviating the need to do it here.
2167 connman_device_unref(device);
2169 #if defined TIZEN_EXT
2170 if (wifi && wifi->scan_pending_network && result != -EIO) {
2171 network_connect(wifi->scan_pending_network);
2172 wifi->scan_pending_network = NULL;
2173 connman_network_set_connecting(wifi->network);
2176 if (is_wifi_notifier_registered != true &&
2177 wifi_first_scan == true && found_with_first_scan == true) {
2178 wifi_first_scan = false;
2179 found_with_first_scan = false;
2181 connman_notifier_register(¬ifier);
2182 is_wifi_notifier_registered = true;
2187 static void scan_callback_hidden(int result,
2188 GSupplicantInterface *interface, void *user_data)
2190 struct connman_device *device = user_data;
2191 struct wifi_data *wifi = connman_device_get_data(device);
2192 GSupplicantScanParams *scan_params;
2195 DBG("result %d wifi %p", result, wifi);
2200 /* User is trying to connect to a hidden AP */
2201 if (wifi->hidden && wifi->postpone_hidden)
2204 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2208 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2209 ret = g_supplicant_interface_scan(wifi->interface,
2211 #if defined TIZEN_EXT
2214 scan_callback_hidden,
2222 g_supplicant_free_scan_params(scan_params);
2225 scan_callback(result, interface, user_data);
2228 static gboolean autoscan_timeout(gpointer data)
2230 struct connman_device *device = data;
2231 struct wifi_data *wifi = connman_device_get_data(device);
2232 struct autoscan_params *autoscan;
2238 autoscan = wifi->autoscan;
2240 if (autoscan->interval <= 0) {
2241 interval = autoscan->base;
2244 interval = autoscan->interval * autoscan->base;
2246 #if defined TIZEN_EXT
2247 if (autoscan->interval >= autoscan->limit)
2249 if (interval > autoscan->limit)
2251 interval = autoscan->limit;
2253 throw_wifi_scan(wifi->device, scan_callback_hidden);
2256 DBG("interval %d", interval);
2258 autoscan->interval = interval;
2260 autoscan->timeout = g_timeout_add_seconds(interval,
2261 autoscan_timeout, device);
2266 static void start_autoscan(struct connman_device *device)
2268 struct wifi_data *wifi = connman_device_get_data(device);
2269 struct autoscan_params *autoscan;
2276 if (wifi->p2p_device)
2279 if (wifi->connected)
2282 autoscan = wifi->autoscan;
2286 if (autoscan->timeout > 0 || autoscan->interval > 0)
2289 connman_device_ref(device);
2291 autoscan_timeout(device);
2294 static struct autoscan_params *parse_autoscan_params(const char *params)
2296 struct autoscan_params *autoscan;
2301 DBG("Emulating autoscan");
2303 list_params = g_strsplit(params, ":", 0);
2304 if (list_params == 0)
2307 if (g_strv_length(list_params) < 3) {
2308 g_strfreev(list_params);
2312 base = atoi(list_params[1]);
2313 limit = atoi(list_params[2]);
2315 g_strfreev(list_params);
2317 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2319 DBG("Could not allocate memory for autoscan");
2323 DBG("base %d - limit %d", base, limit);
2324 autoscan->base = base;
2325 autoscan->limit = limit;
2330 static void setup_autoscan(struct wifi_data *wifi)
2332 if (!wifi->autoscan)
2333 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2335 start_autoscan(wifi->device);
2338 static void finalize_interface_creation(struct wifi_data *wifi)
2340 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2342 if (!wifi->device) {
2343 connman_error("WiFi device not set");
2347 connman_device_set_powered(wifi->device, true);
2349 if (!connman_setting_get_bool("BackgroundScanning"))
2352 if (wifi->p2p_device)
2355 setup_autoscan(wifi);
2358 static void interface_create_callback(int result,
2359 GSupplicantInterface *interface,
2362 struct wifi_data *wifi = user_data;
2364 DBG("result %d ifname %s, wifi %p", result,
2365 g_supplicant_interface_get_ifname(interface),
2368 if (result < 0 || !wifi)
2371 wifi->interface = interface;
2372 g_supplicant_interface_set_data(interface, wifi);
2374 if (g_supplicant_interface_get_ready(interface)) {
2375 wifi->interface_ready = true;
2376 finalize_interface_creation(wifi);
2380 static int wifi_enable(struct connman_device *device)
2382 struct wifi_data *wifi = connman_device_get_data(device);
2385 const char *driver = connman_option_get_string("wifi");
2388 DBG("device %p %p", device, wifi);
2390 index = connman_device_get_index(device);
2391 if (!wifi || index < 0)
2394 if (is_p2p_connecting())
2395 return -EINPROGRESS;
2397 interface = connman_inet_ifname(index);
2398 ret = g_supplicant_interface_create(interface, driver, NULL,
2399 interface_create_callback,
2406 return -EINPROGRESS;
2409 static int wifi_disable(struct connman_device *device)
2411 struct wifi_data *wifi = connman_device_get_data(device);
2414 DBG("device %p wifi %p", device, wifi);
2419 wifi->connected = false;
2420 wifi->disconnecting = false;
2422 if (wifi->pending_network)
2423 wifi->pending_network = NULL;
2425 stop_autoscan(device);
2427 if (wifi->p2p_find_timeout) {
2428 g_source_remove(wifi->p2p_find_timeout);
2429 wifi->p2p_find_timeout = 0;
2430 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2431 connman_device_unref(wifi->device);
2434 #if defined TIZEN_EXT
2435 if (wifi->automaxspeed_timeout != 0) {
2436 g_source_remove(wifi->automaxspeed_timeout);
2437 wifi->automaxspeed_timeout = 0;
2441 /* In case of a user scan, device is still referenced */
2442 if (connman_device_get_scanning(device)) {
2443 connman_device_set_scanning(device,
2444 CONNMAN_SERVICE_TYPE_WIFI, false);
2445 connman_device_unref(wifi->device);
2448 remove_networks(device, wifi);
2451 #if defined TIZEN_EXT
2452 wifi->scan_pending_network = NULL;
2454 if (is_wifi_notifier_registered == true) {
2455 connman_notifier_unregister(¬ifier);
2456 is_wifi_notifier_registered = false;
2460 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2464 return -EINPROGRESS;
2467 static int get_latest_connections(int max_ssids,
2468 GSupplicantScanParams *scan_data)
2470 GSequenceIter *iter;
2471 GSequence *latest_list;
2472 struct last_connected *entry;
2481 latest_list = g_sequence_new(free_entry);
2485 services = connman_storage_get_services();
2486 for (i = 0; services && services[i]; i++) {
2487 if (strncmp(services[i], "wifi_", 5) != 0)
2490 keyfile = connman_storage_load_service(services[i]);
2494 str = g_key_file_get_string(keyfile,
2495 services[i], "Favorite", NULL);
2496 if (!str || g_strcmp0(str, "true")) {
2498 g_key_file_free(keyfile);
2503 str = g_key_file_get_string(keyfile,
2504 services[i], "AutoConnect", NULL);
2505 if (!str || g_strcmp0(str, "true")) {
2507 g_key_file_free(keyfile);
2512 str = g_key_file_get_string(keyfile,
2513 services[i], "Modified", NULL);
2515 g_key_file_free(keyfile);
2518 g_time_val_from_iso8601(str, &modified);
2521 ssid = g_key_file_get_string(keyfile,
2522 services[i], "SSID", NULL);
2524 freq = g_key_file_get_integer(keyfile, services[i],
2527 entry = g_try_new(struct last_connected, 1);
2529 g_sequence_free(latest_list);
2530 g_key_file_free(keyfile);
2536 entry->modified = modified;
2539 g_sequence_insert_sorted(latest_list, entry,
2545 g_key_file_free(keyfile);
2548 g_strfreev(services);
2550 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2552 iter = g_sequence_get_begin_iter(latest_list);
2554 for (i = 0; i < num_ssids; i++) {
2555 entry = g_sequence_get(iter);
2557 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2558 entry->modified.tv_sec);
2560 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2561 max_ssids, entry->ssid);
2563 iter = g_sequence_iter_next(iter);
2566 g_sequence_free(latest_list);
2570 static int wifi_scan_simple(struct connman_device *device)
2572 reset_autoscan(device);
2574 return throw_wifi_scan(device, scan_callback_hidden);
2577 static gboolean p2p_find_stop(gpointer data)
2579 struct connman_device *device = data;
2580 struct wifi_data *wifi = connman_device_get_data(device);
2585 wifi->p2p_find_timeout = 0;
2587 g_supplicant_interface_p2p_stop_find(wifi->interface);
2590 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2592 connman_device_unref(device);
2593 reset_autoscan(device);
2598 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2601 struct connman_device *device = user_data;
2602 struct wifi_data *wifi = connman_device_get_data(device);
2604 DBG("result %d wifi %p", result, wifi);
2609 if (wifi->p2p_find_timeout) {
2610 g_source_remove(wifi->p2p_find_timeout);
2611 wifi->p2p_find_timeout = 0;
2617 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2618 p2p_find_stop, device);
2619 if (!wifi->p2p_find_timeout)
2624 p2p_find_stop(device);
2627 static int p2p_find(struct connman_device *device)
2629 struct wifi_data *wifi;
2634 if (!p2p_technology)
2637 wifi = connman_device_get_data(device);
2639 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2642 reset_autoscan(device);
2643 connman_device_ref(device);
2645 ret = g_supplicant_interface_p2p_find(wifi->interface,
2646 p2p_find_callback, device);
2648 connman_device_unref(device);
2649 start_autoscan(device);
2651 connman_device_set_scanning(device,
2652 CONNMAN_SERVICE_TYPE_P2P, true);
2658 #if defined TIZEN_EXT
2659 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2662 struct connman_device *device = user_data;
2663 struct wifi_data *wifi = connman_device_get_data(device);
2666 DBG("result %d wifi %p", result, wifi);
2668 if (wifi && wifi->scan_params) {
2669 g_supplicant_free_scan_params(wifi->scan_params);
2670 wifi->scan_params = NULL;
2673 scanning = connman_device_get_scanning(device);
2675 connman_device_set_scanning(device,
2676 CONNMAN_SERVICE_TYPE_WIFI, false);
2677 connman_device_unref(device);
2681 static int wifi_specific_scan(enum connman_service_type type,
2682 struct connman_device *device, int scan_type,
2683 GSList *specific_scan_list, void *user_data)
2685 GSList *list = NULL;
2687 struct wifi_data *wifi = connman_device_get_data(device);
2688 GSupplicantScanParams *scan_params = NULL;
2689 struct scan_ssid *scan_ssid = NULL;
2698 if (wifi->p2p_device)
2701 if (type == CONNMAN_SERVICE_TYPE_P2P)
2702 return p2p_find(device);
2704 if (wifi->tethering)
2707 scanning = connman_device_get_scanning(device);
2711 DBG("scan_type: %d", scan_type);
2712 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2713 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2715 DBG("Failed to allocate memory.");
2719 for (list = specific_scan_list; list; list = list->next) {
2720 ssid = (char *)list->data;
2721 int ssid_len = strlen(ssid);
2723 scan_ssid = g_try_new0(struct scan_ssid, 1);
2725 DBG("Failed to allocate memory.");
2726 g_supplicant_free_scan_params(scan_params);
2730 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2731 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2732 scan_ssid->ssid_len = ssid_len;
2733 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2736 scan_params->num_ssids = count;
2738 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2740 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2742 DBG("Failed to allocate memory.");
2746 guint num_freqs = g_slist_length(specific_scan_list);
2747 DBG("num_freqs: %d", num_freqs);
2749 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2750 if (!scan_params->freqs) {
2751 DBG("Failed to allocate memory.");
2752 g_free(scan_params);
2757 for (list = specific_scan_list; list; list = list->next) {
2758 freq = (int)list->data;
2760 scan_params->freqs[count] = freq;
2761 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2764 scan_params->num_freqs = count;
2766 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2767 int freq_count, ap_count;
2768 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2770 DBG("Failed to allocate memory.");
2774 guint size = g_slist_length(specific_scan_list);
2776 scan_params->freqs = g_try_new0(uint16_t, size/2);
2777 if (!scan_params->freqs) {
2778 DBG("Failed to allocate memory.");
2779 g_free(scan_params);
2783 ap_count = freq_count = 0;
2784 for (list = specific_scan_list; list; list = list->next) {
2785 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2786 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2787 int ssid_len = strlen(ssid);
2789 scan_ssid = g_try_new0(struct scan_ssid, 1);
2791 DBG("Failed to allocate memory.");
2792 g_supplicant_free_scan_params(scan_params);
2796 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2797 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2798 scan_ssid->ssid_len = ssid_len;
2799 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2803 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2804 scan_params->freqs[freq_count] = freq;
2805 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2809 scan_params->num_ssids = ap_count;
2810 scan_params->num_freqs = freq_count;
2812 DBG("Invalid scan");
2816 reset_autoscan(device);
2817 connman_device_ref(device);
2819 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2820 specific_scan_callback, device);
2823 connman_device_set_scanning(device,
2824 CONNMAN_SERVICE_TYPE_WIFI, true);
2826 g_supplicant_free_scan_params(scan_params);
2827 connman_device_unref(device);
2834 #if defined TIZEN_EXT_WIFI_MESH
2835 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2838 struct connman_device *device = user_data;
2839 struct wifi_data *wifi = connman_device_get_data(device);
2842 DBG("result %d wifi %p", result, wifi);
2844 scanning = connman_device_get_scanning(device);
2846 connman_device_set_scanning(device,
2847 CONNMAN_SERVICE_TYPE_MESH, false);
2850 connman_device_unref(device);
2853 static int mesh_scan(struct connman_device *device)
2855 struct wifi_data *wifi;
2856 struct wifi_mesh_info *mesh_info;
2861 wifi = connman_device_get_data(device);
2863 if (!wifi->mesh_interface)
2866 mesh_info = wifi->mesh_info;
2867 reset_autoscan(device);
2868 connman_device_ref(device);
2870 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2871 mesh_scan_callback, device);
2873 connman_device_unref(device);
2875 connman_device_set_scanning(device,
2876 CONNMAN_SERVICE_TYPE_MESH, true);
2881 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2884 struct connman_device *device = user_data;
2885 struct wifi_data *wifi = connman_device_get_data(device);
2887 DBG("result %d wifi %p", result, wifi);
2889 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2892 static int mesh_abort_scan(enum connman_service_type type,
2893 struct connman_device *device)
2895 struct wifi_data *wifi = connman_device_get_data(device);
2896 struct wifi_mesh_info *mesh_info;
2900 if (!wifi || !wifi->mesh_interface)
2903 if (type != CONNMAN_SERVICE_TYPE_MESH)
2906 mesh_info = wifi->mesh_info;
2908 scanning = connman_device_get_scanning(device);
2912 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2913 abort_scan_callback, device);
2918 static int mesh_specific_scan(enum connman_service_type type,
2919 struct connman_device *device, const char *ssid,
2920 unsigned int freq, void *user_data)
2922 struct wifi_data *wifi = connman_device_get_data(device);
2923 GSupplicantScanParams *scan_params = NULL;
2924 struct wifi_mesh_info *mesh_info;
2925 struct scan_ssid *scan_ssid;
2929 if (!wifi || !wifi->mesh_interface)
2932 if (type != CONNMAN_SERVICE_TYPE_MESH)
2935 if (wifi->p2p_device)
2938 mesh_info = wifi->mesh_info;
2940 scanning = connman_device_get_scanning(device);
2944 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2948 scan_ssid = g_try_new(struct scan_ssid, 1);
2950 g_free(scan_params);
2954 scan_ssid->ssid_len = strlen(ssid);
2955 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2956 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2957 scan_params->num_ssids = 1;
2959 scan_params->freqs = g_try_new(uint16_t, 1);
2960 if (!scan_params->freqs) {
2961 g_slist_free_full(scan_params->ssids, g_free);
2962 g_free(scan_params);
2966 scan_params->freqs[0] = freq;
2967 scan_params->num_freqs = 1;
2969 reset_autoscan(device);
2970 connman_device_ref(device);
2972 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2973 mesh_scan_callback, device);
2976 connman_device_set_scanning(device,
2977 CONNMAN_SERVICE_TYPE_MESH, true);
2979 g_supplicant_free_scan_params(scan_params);
2980 connman_device_unref(device);
2988 * Note that the hidden scan is only used when connecting to this specific
2989 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2991 static int wifi_scan(enum connman_service_type type,
2992 struct connman_device *device,
2993 const char *ssid, unsigned int ssid_len,
2994 const char *identity, const char* passphrase,
2995 const char *security, void *user_data)
2997 struct wifi_data *wifi = connman_device_get_data(device);
2998 GSupplicantScanParams *scan_params = NULL;
2999 struct scan_ssid *scan_ssid;
3000 struct hidden_params *hidden;
3002 int driver_max_ssids = 0;
3009 if (wifi->p2p_device)
3012 if (wifi->tethering)
3015 if (type == CONNMAN_SERVICE_TYPE_P2P)
3016 return p2p_find(device);
3018 #if defined TIZEN_EXT_WIFI_MESH
3019 if (type == CONNMAN_SERVICE_TYPE_MESH)
3020 return mesh_scan(device);
3023 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
3025 scanning = connman_device_get_scanning(device);
3027 if (!ssid || ssid_len == 0 || ssid_len > 32) {
3031 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
3033 DBG("max ssids %d", driver_max_ssids);
3034 if (driver_max_ssids == 0)
3035 return wifi_scan_simple(device);
3039 if (scanning && wifi->hidden && wifi->postpone_hidden)
3045 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3050 scan_ssid = g_try_new(struct scan_ssid, 1);
3052 g_free(scan_params);
3056 memcpy(scan_ssid->ssid, ssid, ssid_len);
3057 scan_ssid->ssid_len = ssid_len;
3058 scan_params->ssids = g_slist_prepend(scan_params->ssids,
3060 scan_params->num_ssids = 1;
3062 hidden = g_try_new0(struct hidden_params, 1);
3064 g_supplicant_free_scan_params(scan_params);
3069 hidden_free(wifi->hidden);
3070 wifi->hidden = NULL;
3073 memcpy(hidden->ssid, ssid, ssid_len);
3074 hidden->ssid_len = ssid_len;
3075 hidden->identity = g_strdup(identity);
3076 hidden->passphrase = g_strdup(passphrase);
3077 hidden->security = g_strdup(security);
3078 hidden->user_data = user_data;
3079 wifi->hidden = hidden;
3082 /* Let's keep this active scan for later,
3083 * when current scan will be over. */
3084 wifi->postpone_hidden = TRUE;
3085 hidden->scan_params = scan_params;
3089 } else if (wifi->connected) {
3090 g_supplicant_free_scan_params(scan_params);
3091 return wifi_scan_simple(device);
3093 ret = get_latest_connections(driver_max_ssids, scan_params);
3095 g_supplicant_free_scan_params(scan_params);
3096 return wifi_scan_simple(device);
3100 connman_device_ref(device);
3102 reset_autoscan(device);
3104 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3105 scan_callback, device);
3108 connman_device_set_scanning(device,
3109 CONNMAN_SERVICE_TYPE_WIFI, true);
3110 #if defined TIZEN_EXT
3111 /*To allow the Full Scan after ssid based scan, set the flag here
3112 It is required because Tizen does not use the ConnMan specific
3113 backgroung Scan feature.Tizen has added the BG Scan feature in
3114 net-config. To sync with up ConnMan, we need to issue the Full Scan
3115 after SSID specific scan.*/
3116 wifi->allow_full_scan = TRUE;
3119 g_supplicant_free_scan_params(scan_params);
3120 connman_device_unref(device);
3123 hidden_free(wifi->hidden);
3124 wifi->hidden = NULL;
3131 static void wifi_regdom_callback(int result,
3135 struct connman_device *device = user_data;
3137 connman_device_regdom_notify(device, result, alpha2);
3139 connman_device_unref(device);
3142 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3144 struct wifi_data *wifi = connman_device_get_data(device);
3150 connman_device_ref(device);
3152 ret = g_supplicant_interface_set_country(wifi->interface,
3153 wifi_regdom_callback,
3156 connman_device_unref(device);
3161 static struct connman_device_driver wifi_ng_driver = {
3163 .type = CONNMAN_DEVICE_TYPE_WIFI,
3164 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3165 .probe = wifi_probe,
3166 .remove = wifi_remove,
3167 .enable = wifi_enable,
3168 .disable = wifi_disable,
3170 .set_regdom = wifi_set_regdom,
3171 #if defined TIZEN_EXT
3172 .specific_scan = wifi_specific_scan,
3174 #if defined TIZEN_EXT_WIFI_MESH
3175 .abort_scan = mesh_abort_scan,
3176 .mesh_specific_scan = mesh_specific_scan,
3180 static void system_ready(void)
3184 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3185 connman_error("Failed to register WiFi driver");
3188 static void system_killed(void)
3192 connman_device_driver_unregister(&wifi_ng_driver);
3195 static int network_probe(struct connman_network *network)
3197 DBG("network %p", network);
3202 static void network_remove(struct connman_network *network)
3204 struct connman_device *device = connman_network_get_device(network);
3205 struct wifi_data *wifi;
3207 DBG("network %p", network);
3209 wifi = connman_device_get_data(device);
3213 if (wifi->network != network)
3216 wifi->network = NULL;
3218 #if defined TIZEN_EXT
3219 wifi->disconnecting = false;
3221 if (wifi->pending_network == network)
3222 wifi->pending_network = NULL;
3224 if (wifi->scan_pending_network == network)
3225 wifi->scan_pending_network = NULL;
3229 static void connect_callback(int result, GSupplicantInterface *interface,
3232 #if defined TIZEN_EXT
3234 struct wifi_data *wifi;
3236 struct connman_network *network = user_data;
3238 DBG("network %p result %d", network, result);
3240 #if defined TIZEN_EXT
3241 set_connman_bssid(RESET_BSSID, NULL);
3243 for (list = iface_list; list; list = list->next) {
3246 if (wifi && wifi->network == network)
3250 /* wifi_data may be invalid because wifi is already disabled */
3255 if (result == -ENOKEY) {
3256 connman_network_set_error(network,
3257 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3258 } else if (result < 0) {
3259 connman_network_set_error(network,
3260 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3263 connman_network_unref(network);
3266 static GSupplicantSecurity network_security(const char *security)
3268 if (g_str_equal(security, "none"))
3269 return G_SUPPLICANT_SECURITY_NONE;
3270 else if (g_str_equal(security, "wep"))
3271 return G_SUPPLICANT_SECURITY_WEP;
3272 else if (g_str_equal(security, "psk"))
3273 return G_SUPPLICANT_SECURITY_PSK;
3274 else if (g_str_equal(security, "wpa"))
3275 return G_SUPPLICANT_SECURITY_PSK;
3276 else if (g_str_equal(security, "rsn"))
3277 return G_SUPPLICANT_SECURITY_PSK;
3278 else if (g_str_equal(security, "ieee8021x"))
3279 return G_SUPPLICANT_SECURITY_IEEE8021X;
3280 #if defined TIZEN_EXT
3281 else if (g_str_equal(security, "ft_psk") == TRUE)
3282 return G_SUPPLICANT_SECURITY_FT_PSK;
3283 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3284 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3285 else if (g_str_equal(security, "sae"))
3286 return G_SUPPLICANT_SECURITY_SAE;
3287 else if (g_str_equal(security, "owe"))
3288 return G_SUPPLICANT_SECURITY_OWE;
3291 return G_SUPPLICANT_SECURITY_UNKNOWN;
3294 #if defined TIZEN_EXT
3295 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3297 if (security == NULL)
3298 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3300 if (g_str_equal(security, "FT") == TRUE)
3301 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3302 else if (g_str_equal(security, "CCKM") == TRUE)
3303 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3305 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3309 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3311 const char *security;
3312 #if defined TIZEN_EXT
3313 const void *ssid_data;
3316 memset(ssid, 0, sizeof(*ssid));
3317 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3318 #if defined TIZEN_EXT
3319 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3321 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3326 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3328 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3331 ssid->scan_ssid = 1;
3332 security = connman_network_get_string(network, "WiFi.Security");
3333 ssid->security = network_security(security);
3334 #if defined TIZEN_EXT
3335 ssid->ieee80211w = 1;
3337 ssid->passphrase = connman_network_get_string(network,
3339 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3342 * If our private key password is unset,
3343 * we use the supplied passphrase. That is needed
3344 * for PEAP where 2 passphrases (identity and client
3345 * cert may have to be provided.
3347 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3348 connman_network_set_string(network,
3349 "WiFi.PrivateKeyPassphrase",
3351 /* We must have an identity for both PEAP and TLS */
3352 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3354 /* Use agent provided identity as a fallback */
3355 if (!ssid->identity || strlen(ssid->identity) == 0)
3356 ssid->identity = connman_network_get_string(network,
3357 "WiFi.AgentIdentity");
3359 ssid->anonymous_identity = connman_network_get_string(network,
3360 "WiFi.AnonymousIdentity");
3361 ssid->ca_cert_path = connman_network_get_string(network,
3363 ssid->subject_match = connman_network_get_string(network,
3364 "WiFi.SubjectMatch");
3365 ssid->altsubject_match = connman_network_get_string(network,
3366 "WiFi.AltSubjectMatch");
3367 ssid->domain_suffix_match = connman_network_get_string(network,
3368 "WiFi.DomainSuffixMatch");
3369 ssid->domain_match = connman_network_get_string(network,
3370 "WiFi.DomainMatch");
3371 ssid->client_cert_path = connman_network_get_string(network,
3372 "WiFi.ClientCertFile");
3373 ssid->private_key_path = connman_network_get_string(network,
3374 "WiFi.PrivateKeyFile");
3375 ssid->private_key_passphrase = connman_network_get_string(network,
3376 "WiFi.PrivateKeyPassphrase");
3377 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3379 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3380 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3382 #if defined TIZEN_EXT
3383 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3384 ssid->bssid_for_connect_len = 6;
3385 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3386 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3387 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3388 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3389 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3391 ssid->freq = connman_network_get_frequency(network);
3394 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3395 if (bssid_list && g_slist_length(bssid_list) > 1) {
3397 /* If there are more than one bssid,
3398 * the user-specified bssid is tried only once at the beginning.
3399 * After that, the bssids in the list are tried in order.
3401 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3402 set_connman_bssid(RESET_BSSID, NULL);
3407 char buff[MAC_ADDRESS_LENGTH];
3408 for (list = bssid_list; list; list = list->next) {
3409 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3411 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3412 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3413 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3414 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3416 gchar *curr_bssid = g_strdup((const gchar *)buff);
3418 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3419 DBG("bssid match, try next bssid");
3423 g_hash_table_add(failed_bssids, curr_bssid);
3425 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3426 ssid->bssid = buff_bssid;
3427 ssid->freq = (unsigned int)bssids->frequency;
3433 ssid->bssid = connman_network_get_bssid(network);
3434 g_hash_table_remove_all(failed_bssids);
3437 ssid->bssid = connman_network_get_bssid(network);
3440 ssid->eap_keymgmt = network_eap_keymgmt(
3441 connman_network_get_string(network, "WiFi.KeymgmtType"));
3442 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3444 if(g_strcmp0(ssid->eap, "fast") == 0)
3445 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3448 if (connman_setting_get_bool("BackgroundScanning"))
3449 ssid->bgscan = BGSCAN_DEFAULT;
3452 static int network_connect(struct connman_network *network)
3454 struct connman_device *device = connman_network_get_device(network);
3455 struct wifi_data *wifi;
3456 GSupplicantInterface *interface;
3457 GSupplicantSSID *ssid;
3459 DBG("network %p", network);
3464 wifi = connman_device_get_data(device);
3468 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3472 interface = wifi->interface;
3474 ssid_init(ssid, network);
3476 if (wifi->disconnecting) {
3477 wifi->pending_network = network;
3478 #if defined TIZEN_EXT
3483 wifi->network = connman_network_ref(network);
3485 #if defined TIZEN_EXT
3486 wifi->scan_pending_network = NULL;
3489 return g_supplicant_interface_connect(interface, ssid,
3490 connect_callback, network);
3493 return -EINPROGRESS;
3496 static void disconnect_callback(int result, GSupplicantInterface *interface,
3499 #if defined TIZEN_EXT
3501 struct wifi_data *wifi;
3502 struct connman_network *network = user_data;
3504 DBG("network %p result %d", network, result);
3506 for (list = iface_list; list; list = list->next) {
3509 if (wifi->network == NULL && wifi->disconnecting == true)
3510 wifi->disconnecting = false;
3512 if (wifi->network == network)
3516 /* wifi_data may be invalid because wifi is already disabled */
3521 struct wifi_data *wifi = user_data;
3524 DBG("result %d supplicant interface %p wifi %p",
3525 result, interface, wifi);
3527 if (result == -ECONNABORTED) {
3528 DBG("wifi interface no longer available");
3532 if (wifi->network) {
3533 connman_network_set_connected(wifi->network, false);
3534 wifi->network = NULL;
3537 wifi->disconnecting = false;
3538 wifi->connected = false;
3540 if (wifi->pending_network) {
3541 network_connect(wifi->pending_network);
3542 wifi->pending_network = NULL;
3545 start_autoscan(wifi->device);
3548 static int network_disconnect(struct connman_network *network)
3550 struct connman_device *device = connman_network_get_device(network);
3551 struct wifi_data *wifi;
3553 #if defined TIZEN_EXT
3554 struct connman_service *service;
3557 DBG("network %p", network);
3559 wifi = connman_device_get_data(device);
3560 if (!wifi || !wifi->interface)
3563 #if defined TIZEN_EXT
3564 if (connman_network_get_associating(network) == true) {
3565 connman_network_clear_associating(network);
3566 connman_network_set_bool(network, "WiFi.UseWPS", false);
3568 service = connman_service_lookup_from_network(network);
3570 if (service != NULL &&
3571 (__connman_service_is_connected_state(service,
3572 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3573 __connman_service_is_connected_state(service,
3574 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3575 (connman_service_get_favorite(service) == false))
3576 __connman_service_set_passphrase(service, NULL);
3579 if (wifi->pending_network == network)
3580 wifi->pending_network = NULL;
3582 if (wifi->scan_pending_network == network)
3583 wifi->scan_pending_network = NULL;
3586 connman_network_set_associating(network, false);
3588 if (wifi->disconnecting)
3591 wifi->disconnecting = true;
3593 #if defined TIZEN_EXT
3594 err = g_supplicant_interface_disconnect(wifi->interface,
3595 disconnect_callback, network);
3597 err = g_supplicant_interface_disconnect(wifi->interface,
3598 disconnect_callback, wifi);
3602 wifi->disconnecting = false;
3607 #if defined TIZEN_EXT
3608 static void set_connection_mode(struct connman_network *network,
3611 ieee80211_modes_e phy_mode;
3612 connection_mode_e conn_mode;
3614 phy_mode = connman_network_get_phy_mode(network);
3616 case IEEE80211_MODE_B:
3617 if (linkspeed > 0 && linkspeed <= 11)
3618 conn_mode = CONNECTION_MODE_IEEE80211B;
3620 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3623 case IEEE80211_MODE_BG:
3624 if (linkspeed > 0 && linkspeed <= 11)
3625 conn_mode = CONNECTION_MODE_IEEE80211B;
3626 else if (linkspeed > 11 && linkspeed <= 54)
3627 conn_mode = CONNECTION_MODE_IEEE80211G;
3629 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3632 case IEEE80211_MODE_BGN:
3633 if (linkspeed > 0 && linkspeed <= 11)
3634 conn_mode = CONNECTION_MODE_IEEE80211B;
3635 else if (linkspeed > 11 && linkspeed <= 54)
3636 conn_mode = CONNECTION_MODE_IEEE80211G;
3637 else if (linkspeed > 54 && linkspeed <= 450)
3638 conn_mode = CONNECTION_MODE_IEEE80211N;
3640 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3643 case IEEE80211_MODE_A:
3644 if (linkspeed > 0 && linkspeed <= 54)
3645 conn_mode = CONNECTION_MODE_IEEE80211A;
3647 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3650 case IEEE80211_MODE_AN:
3651 if (linkspeed > 0 && linkspeed <= 54)
3652 conn_mode = CONNECTION_MODE_IEEE80211A;
3653 else if (linkspeed > 54 && linkspeed <= 450)
3654 conn_mode = CONNECTION_MODE_IEEE80211N;
3656 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3659 case IEEE80211_MODE_ANAC:
3660 if (linkspeed > 0 && linkspeed <= 54)
3661 conn_mode = CONNECTION_MODE_IEEE80211A;
3662 else if (linkspeed > 54 && linkspeed <= 450)
3663 conn_mode = CONNECTION_MODE_IEEE80211N;
3664 else if (linkspeed > 450 && linkspeed <= 1300)
3665 conn_mode = CONNECTION_MODE_IEEE80211AC;
3667 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3671 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3675 DBG("connection mode(%d)", conn_mode);
3676 connman_network_set_connection_mode(network, conn_mode);
3679 static void signalpoll_callback(int result, int maxspeed, uint8_t strength,
3682 struct connman_network *network = user_data;
3685 DBG("Failed to get maxspeed from signalpoll !");
3693 DBG("maxspeed = %d, strength = %d", maxspeed, strength);
3695 connman_network_set_strength(network, strength);
3696 connman_network_set_maxspeed(network, maxspeed);
3697 set_connection_mode(network, maxspeed);
3701 static int network_signalpoll(struct wifi_data *wifi)
3703 GSupplicantInterface *interface;
3704 struct connman_network *network;
3706 if (!wifi || !wifi->network)
3709 interface = wifi->interface;
3710 network = wifi->network;
3712 DBG("network %p", network);
3714 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3717 static gboolean autosignalpoll_timeout(gpointer data)
3719 struct wifi_data *wifi = data;
3721 if (!wifi || !wifi->automaxspeed_timeout) {
3722 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3726 int ret = network_signalpoll(wifi);
3728 DBG("Fail to get max speed !!");
3729 wifi->automaxspeed_timeout = 0;
3737 static struct connman_network_driver network_driver = {
3739 .type = CONNMAN_NETWORK_TYPE_WIFI,
3740 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3741 .probe = network_probe,
3742 .remove = network_remove,
3743 .connect = network_connect,
3744 .disconnect = network_disconnect,
3747 static void interface_added(GSupplicantInterface *interface)
3749 const char *ifname = g_supplicant_interface_get_ifname(interface);
3750 const char *driver = g_supplicant_interface_get_driver(interface);
3751 #if defined TIZEN_EXT
3752 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3755 struct wifi_data *wifi;
3757 wifi = g_supplicant_interface_get_data(interface);
3759 wifi = get_pending_wifi_data(ifname);
3763 wifi->interface = interface;
3764 g_supplicant_interface_set_data(interface, wifi);
3765 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3766 wifi->p2p_device = true;
3769 DBG("ifname %s driver %s wifi %p tethering %d",
3770 ifname, driver, wifi, wifi->tethering);
3772 if (!wifi->device) {
3773 connman_error("WiFi device not set");
3777 connman_device_set_powered(wifi->device, true);
3778 #if defined TIZEN_EXT
3779 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3780 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3781 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3782 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3786 static bool is_idle(struct wifi_data *wifi)
3788 DBG("state %d", wifi->state);
3790 switch (wifi->state) {
3791 case G_SUPPLICANT_STATE_UNKNOWN:
3792 case G_SUPPLICANT_STATE_DISABLED:
3793 case G_SUPPLICANT_STATE_DISCONNECTED:
3794 case G_SUPPLICANT_STATE_INACTIVE:
3795 case G_SUPPLICANT_STATE_SCANNING:
3798 case G_SUPPLICANT_STATE_AUTHENTICATING:
3799 case G_SUPPLICANT_STATE_ASSOCIATING:
3800 case G_SUPPLICANT_STATE_ASSOCIATED:
3801 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3802 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3803 case G_SUPPLICANT_STATE_COMPLETED:
3810 static bool is_idle_wps(GSupplicantInterface *interface,
3811 struct wifi_data *wifi)
3813 /* First, let's check if WPS processing did not went wrong */
3814 if (g_supplicant_interface_get_wps_state(interface) ==
3815 G_SUPPLICANT_WPS_STATE_FAIL)
3818 /* Unlike normal connection, being associated while processing wps
3819 * actually means that we are idling. */
3820 switch (wifi->state) {
3821 case G_SUPPLICANT_STATE_UNKNOWN:
3822 case G_SUPPLICANT_STATE_DISABLED:
3823 case G_SUPPLICANT_STATE_DISCONNECTED:
3824 case G_SUPPLICANT_STATE_INACTIVE:
3825 case G_SUPPLICANT_STATE_SCANNING:
3826 case G_SUPPLICANT_STATE_ASSOCIATED:
3828 case G_SUPPLICANT_STATE_AUTHENTICATING:
3829 case G_SUPPLICANT_STATE_ASSOCIATING:
3830 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3831 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3832 case G_SUPPLICANT_STATE_COMPLETED:
3839 static bool handle_wps_completion(GSupplicantInterface *interface,
3840 struct connman_network *network,
3841 struct connman_device *device,
3842 struct wifi_data *wifi)
3846 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3848 const unsigned char *ssid, *wps_ssid;
3849 unsigned int ssid_len, wps_ssid_len;
3850 const char *wps_key;
3852 /* Checking if we got associated with requested
3854 ssid = connman_network_get_blob(network, "WiFi.SSID",
3857 wps_ssid = g_supplicant_interface_get_wps_ssid(
3858 interface, &wps_ssid_len);
3860 if (!wps_ssid || wps_ssid_len != ssid_len ||
3861 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3862 connman_network_set_associating(network, false);
3863 #if defined TIZEN_EXT
3864 g_supplicant_interface_disconnect(wifi->interface,
3865 disconnect_callback, wifi->network);
3867 connman_network_set_bool(network, "WiFi.UseWPS", false);
3868 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3870 g_supplicant_interface_disconnect(wifi->interface,
3871 disconnect_callback, wifi);
3876 wps_key = g_supplicant_interface_get_wps_key(interface);
3877 #if defined TIZEN_EXT
3878 /* Check the passphrase and encrypt it
3881 gchar *passphrase = g_strdup(wps_key);
3883 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3885 if (check_passphrase_ext(network, passphrase) < 0) {
3886 DBG("[WPS] Invalid passphrase");
3891 ret = send_encryption_request(passphrase, network);
3896 DBG("[WPS] Encryption request succeeded");
3898 DBG("[WPS] Encryption request failed %d", ret);
3901 connman_network_set_string(network, "WiFi.Passphrase",
3904 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3911 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3912 struct wifi_data *wifi)
3914 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3915 #if defined TIZEN_EXT
3916 wifi->assoc_code > 0 &&
3918 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3920 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3921 wifi->load_shaping_retries ++;
3924 wifi->load_shaping_retries = 0;
3928 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3929 struct connman_network *network,
3930 struct wifi_data *wifi)
3932 #if defined TIZEN_EXT
3933 const char *security;
3934 struct connman_service *service;
3936 if (wifi->connected)
3939 security = connman_network_get_string(network, "WiFi.Security");
3941 if (security && g_str_equal(security, "ieee8021x") == true &&
3942 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3944 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3949 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3952 struct connman_service *service;
3954 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3957 if (wifi->connected)
3961 service = connman_service_lookup_from_network(network);
3967 if (connman_service_get_favorite(service)) {
3968 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3973 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3978 #if defined TIZEN_EXT
3979 static bool handle_wifi_assoc_retry(struct connman_network *network,
3980 struct wifi_data *wifi)
3982 const char *security;
3984 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3985 connman_network_get_connecting(network) != true) {
3986 wifi->assoc_retry_count = 0;
3990 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3991 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3992 wifi->assoc_retry_count = 0;
3996 security = connman_network_get_string(network, "WiFi.Security");
3997 if (security && g_str_equal(security, "ieee8021x") == true &&
3998 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3999 wifi->assoc_retry_count = 0;
4003 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
4004 wifi->assoc_retry_count = 0;
4006 /* Honestly it's not an invalid-key error,
4007 * however QA team recommends that the invalid-key error
4008 * might be better to display for user experience.
4010 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
4019 static void interface_state(GSupplicantInterface *interface)
4021 struct connman_network *network;
4022 struct connman_device *device;
4023 struct wifi_data *wifi;
4024 GSupplicantState state = g_supplicant_interface_get_state(interface);
4028 wifi = g_supplicant_interface_get_data(interface);
4030 DBG("wifi %p interface state %d", wifi, state);
4035 if (state == G_SUPPLICANT_STATE_COMPLETED) {
4036 if (wifi->tethering_param) {
4037 g_free(wifi->tethering_param->ssid);
4038 g_free(wifi->tethering_param);
4039 wifi->tethering_param = NULL;
4043 device = wifi->device;
4047 if (g_supplicant_interface_get_ready(interface) &&
4048 !wifi->interface_ready) {
4049 wifi->interface_ready = true;
4050 finalize_interface_creation(wifi);
4053 network = wifi->network;
4058 case G_SUPPLICANT_STATE_SCANNING:
4059 if (wifi->connected)
4060 connman_network_set_connected(network, false);
4064 case G_SUPPLICANT_STATE_AUTHENTICATING:
4065 case G_SUPPLICANT_STATE_ASSOCIATING:
4066 #if defined TIZEN_EXT
4067 reset_autoscan(device);
4069 stop_autoscan(device);
4072 if (!wifi->connected)
4073 connman_network_set_associating(network, true);
4077 case G_SUPPLICANT_STATE_COMPLETED:
4078 #if defined TIZEN_EXT
4079 /* though it should be already reset: */
4080 reset_autoscan(device);
4082 wifi->assoc_retry_count = 0;
4084 wifi->scan_pending_network = NULL;
4086 /* should be cleared scanning flag */
4087 bool scanning = connman_device_get_scanning(device);
4089 connman_device_set_scanning(device,
4090 CONNMAN_SERVICE_TYPE_WIFI, false);
4091 connman_device_unref(device);
4094 if (!wifi->automaxspeed_timeout) {
4095 DBG("Going to start signalpoll timer!!");
4096 int ret = network_signalpoll(wifi);
4098 DBG("Fail to get max speed !!");
4100 wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
4103 g_hash_table_remove_all(failed_bssids);
4105 /* though it should be already stopped: */
4106 stop_autoscan(device);
4109 if (!handle_wps_completion(interface, network, device, wifi))
4112 connman_network_set_connected(network, true);
4114 wifi->disconnect_code = 0;
4115 wifi->assoc_code = 0;
4116 wifi->load_shaping_retries = 0;
4119 case G_SUPPLICANT_STATE_DISCONNECTED:
4120 #if defined TIZEN_EXT
4121 connman_network_set_strength(network, 0);
4122 connman_network_set_maxspeed(network, 0);
4124 if (wifi->automaxspeed_timeout != 0) {
4125 g_source_remove(wifi->automaxspeed_timeout);
4126 wifi->automaxspeed_timeout = 0;
4127 DBG("Remove signalpoll timer!!");
4131 * If we're in one of the idle modes, we have
4132 * not started association yet and thus setting
4133 * those ones to FALSE could cancel an association
4136 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4138 if (is_idle_wps(interface, wifi))
4144 #if defined TIZEN_EXT
4145 if (handle_assoc_status_code(interface, wifi)) {
4146 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4147 guint bssid_length = 0;
4150 bssid_length = g_slist_length(bssid_list);
4152 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4153 network_connect(network);
4157 wifi->load_shaping_retries = 0;
4160 g_hash_table_remove_all(failed_bssids);
4162 if (handle_assoc_status_code(interface, wifi))
4166 /* If previous state was 4way-handshake, then
4167 * it's either: psk was incorrect and thus we retry
4168 * or if we reach the maximum retries we declare the
4170 if (handle_4way_handshake_failure(interface,
4174 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4175 switch (wifi->disconnect_code) {
4176 case 1: /* Unspecified reason */
4177 /* Let's assume it's because we got blocked */
4179 case 6: /* Class 2 frame received from nonauthenticated STA */
4180 connman_network_set_error(network,
4181 CONNMAN_NETWORK_ERROR_BLOCKED);
4188 #if defined TIZEN_EXT
4189 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4190 * Retry association until its retry count is expired */
4191 if (handle_wifi_assoc_retry(network, wifi) == true) {
4192 throw_wifi_scan(wifi->device, scan_callback);
4193 wifi->scan_pending_network = wifi->network;
4197 if(wifi->disconnect_code > 0){
4198 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4199 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4203 connman_network_set_connected(network, false);
4204 connman_network_set_associating(network, false);
4205 wifi->disconnecting = false;
4207 start_autoscan(device);
4211 case G_SUPPLICANT_STATE_INACTIVE:
4212 #if defined TIZEN_EXT
4213 if (handle_wps_completion(interface, network, device, wifi) == false)
4216 connman_network_set_associating(network, false);
4217 start_autoscan(device);
4221 case G_SUPPLICANT_STATE_UNKNOWN:
4222 case G_SUPPLICANT_STATE_DISABLED:
4223 case G_SUPPLICANT_STATE_ASSOCIATED:
4224 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4225 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4229 old_connected = wifi->connected;
4230 wifi->state = state;
4232 /* Saving wpa_s state policy:
4233 * If connected and if the state changes are roaming related:
4234 * --> We stay connected
4236 * --> We are connected
4238 * --> We are not connected
4241 case G_SUPPLICANT_STATE_AUTHENTICATING:
4242 case G_SUPPLICANT_STATE_ASSOCIATING:
4243 case G_SUPPLICANT_STATE_ASSOCIATED:
4244 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4245 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4246 if (wifi->connected)
4247 connman_warn("Probably roaming right now!"
4248 " Staying connected...");
4250 case G_SUPPLICANT_STATE_SCANNING:
4251 wifi->connected = false;
4254 start_autoscan(device);
4256 case G_SUPPLICANT_STATE_COMPLETED:
4257 wifi->connected = true;
4260 wifi->connected = false;
4267 static void interface_removed(GSupplicantInterface *interface)
4269 const char *ifname = g_supplicant_interface_get_ifname(interface);
4270 struct wifi_data *wifi;
4272 DBG("ifname %s", ifname);
4274 wifi = g_supplicant_interface_get_data(interface);
4276 #if defined TIZEN_EXT_WIFI_MESH
4277 if (wifi && wifi->mesh_interface) {
4278 DBG("Notify mesh interface remove");
4279 connman_mesh_notify_interface_remove(true);
4280 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4281 g_free(mesh_info->parent_ifname);
4282 g_free(mesh_info->ifname);
4283 g_free(mesh_info->identifier);
4285 wifi->mesh_interface = false;
4286 wifi->mesh_info = NULL;
4292 wifi->interface = NULL;
4294 if (wifi && wifi->tethering)
4297 if (!wifi || !wifi->device) {
4298 DBG("wifi interface already removed");
4302 connman_device_set_powered(wifi->device, false);
4304 check_p2p_technology();
4305 #if defined TIZEN_EXT_WIFI_MESH
4306 check_mesh_technology();
4310 static void set_device_type(const char *type, char dev_type[17])
4312 const char *oui = "0050F204";
4313 const char *category = "0001";
4314 const char *sub_category = "0000";
4316 if (!g_strcmp0(type, "handset")) {
4318 sub_category = "0005";
4319 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4320 sub_category = "0001";
4321 else if (!g_strcmp0(type, "server"))
4322 sub_category = "0002";
4323 else if (!g_strcmp0(type, "laptop"))
4324 sub_category = "0005";
4325 else if (!g_strcmp0(type, "desktop"))
4326 sub_category = "0006";
4327 else if (!g_strcmp0(type, "tablet"))
4328 sub_category = "0009";
4329 else if (!g_strcmp0(type, "watch"))
4332 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4335 static void p2p_support(GSupplicantInterface *interface)
4337 char dev_type[17] = {};
4338 const char *hostname;
4345 if (!g_supplicant_interface_has_p2p(interface))
4348 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4349 DBG("Could not register P2P technology driver");
4353 hostname = connman_utsname_get_hostname();
4355 hostname = "ConnMan";
4357 set_device_type(connman_machine_get_type(), dev_type);
4358 g_supplicant_interface_set_p2p_device_config(interface,
4359 hostname, dev_type);
4360 connman_peer_driver_register(&peer_driver);
4363 static void scan_started(GSupplicantInterface *interface)
4368 static void scan_finished(GSupplicantInterface *interface)
4370 #if defined TIZEN_EXT
4371 struct wifi_data *wifi;
4372 bool is_associating = false;
4373 static bool is_scanning = true;
4378 #if defined TIZEN_EXT
4379 wifi = g_supplicant_interface_get_data(interface);
4380 if (wifi && wifi->scan_pending_network) {
4381 network_connect(wifi->scan_pending_network);
4382 wifi->scan_pending_network = NULL;
4385 //service state - associating
4386 if(!wifi || !wifi->network)
4389 is_associating = connman_network_get_associating(wifi->network);
4390 if(is_associating && is_scanning){
4391 is_scanning = false;
4392 DBG("send scan for connecting");
4393 throw_wifi_scan(wifi->device, scan_callback);
4404 static void ap_create_fail(GSupplicantInterface *interface)
4406 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4409 if ((wifi->tethering) && (wifi->tethering_param)) {
4410 DBG("%s create AP fail \n",
4411 g_supplicant_interface_get_ifname(wifi->interface));
4413 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4414 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4415 wifi->tethering = false;
4417 ret = tech_set_tethering(wifi->tethering_param->technology,
4418 wifi->tethering_param->ssid->ssid,
4419 wifi->tethering_param->ssid->passphrase,
4420 wifi->bridge, true);
4422 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4423 connman_technology_tethering_notify(wifi_technology,false);
4426 g_free(wifi->tethering_param->ssid);
4427 g_free(wifi->tethering_param);
4428 wifi->tethering_param = NULL;
4434 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4436 unsigned char strength;
4438 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4440 #if !defined TIZEN_EXT
4447 #if defined TIZEN_EXT_WIFI_MESH
4448 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4450 GSupplicantInterface *interface;
4451 struct wifi_data *wifi;
4452 const char *name, *security;
4453 struct connman_mesh *connman_mesh;
4454 struct wifi_mesh_info *mesh_info;
4455 const unsigned char *bssid;
4456 const char *identifier;
4461 interface = g_supplicant_network_get_interface(supplicant_network);
4462 wifi = g_supplicant_interface_get_data(interface);
4463 if (!wifi || !wifi->mesh_interface) {
4464 DBG("Virtual Mesh interface not created");
4468 bssid = g_supplicant_network_get_bssid(supplicant_network);
4469 address = g_malloc0(19);
4470 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4471 bssid[2], bssid[3], bssid[4], bssid[5]);
4473 identifier = g_supplicant_network_get_identifier(supplicant_network);
4474 name = g_supplicant_network_get_name(supplicant_network);
4475 security = g_supplicant_network_get_security(supplicant_network);
4476 frequency = g_supplicant_network_get_frequency(supplicant_network);
4478 mesh_info = wifi->mesh_info;
4479 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4483 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4485 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4486 connman_mesh_set_name(connman_mesh, name);
4487 connman_mesh_set_security(connman_mesh, security);
4488 connman_mesh_set_frequency(connman_mesh, frequency);
4489 connman_mesh_set_address(connman_mesh, address);
4490 connman_mesh_set_index(connman_mesh, mesh_info->index);
4491 connman_mesh_set_strength(connman_mesh,
4492 calculate_strength(supplicant_network));
4493 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4495 ret = connman_mesh_register(connman_mesh);
4496 if (ret == -EALREADY)
4497 DBG("Mesh Peer is already registered");
4503 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4505 GSupplicantInterface *interface;
4506 struct wifi_data *wifi;
4507 struct connman_mesh *connman_mesh;
4508 struct wifi_mesh_info *mesh_info;
4509 const char *identifier;
4511 interface = g_supplicant_network_get_interface(supplicant_network);
4512 wifi = g_supplicant_interface_get_data(interface);
4513 if (!wifi || !wifi->mesh_interface) {
4514 DBG("Virtual Mesh interface not created");
4518 identifier = g_supplicant_network_get_identifier(supplicant_network);
4520 DBG("Failed to get Mesh Peer identifier");
4524 mesh_info = wifi->mesh_info;
4525 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4527 /* Do not unregister connected mesh peer */
4528 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4529 DBG("Mesh Peer %s is connected", identifier);
4532 DBG("Mesh Peer identifier %s removed", identifier);
4533 connman_mesh_unregister(connman_mesh);
4538 static void network_added(GSupplicantNetwork *supplicant_network)
4540 struct connman_network *network;
4541 GSupplicantInterface *interface;
4542 struct wifi_data *wifi;
4543 const char *name, *identifier, *security, *group, *mode;
4544 const unsigned char *ssid;
4545 unsigned int ssid_len;
4549 bool wps_advertizing;
4551 #if defined TIZEN_EXT
4552 GSList *vsie_list = NULL;
4553 const unsigned char *country_code;
4554 ieee80211_modes_e phy_mode;
4557 mode = g_supplicant_network_get_mode(supplicant_network);
4558 identifier = g_supplicant_network_get_identifier(supplicant_network);
4560 DBG("%s", identifier);
4562 if (!g_strcmp0(mode, "adhoc"))
4565 #if defined TIZEN_EXT_WIFI_MESH
4566 if (!g_strcmp0(mode, "mesh")) {
4567 mesh_peer_added(supplicant_network);
4572 interface = g_supplicant_network_get_interface(supplicant_network);
4573 wifi = g_supplicant_interface_get_data(interface);
4574 name = g_supplicant_network_get_name(supplicant_network);
4575 security = g_supplicant_network_get_security(supplicant_network);
4576 group = g_supplicant_network_get_identifier(supplicant_network);
4577 wps = g_supplicant_network_get_wps(supplicant_network);
4578 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4579 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4580 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4581 supplicant_network);
4586 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4588 network = connman_device_get_network(wifi->device, identifier);
4591 network = connman_network_create(identifier,
4592 CONNMAN_NETWORK_TYPE_WIFI);
4596 connman_network_set_index(network, wifi->index);
4598 if (connman_device_add_network(wifi->device, network) < 0) {
4599 connman_network_unref(network);
4603 wifi->networks = g_slist_prepend(wifi->networks, network);
4606 if (name && name[0] != '\0')
4607 connman_network_set_name(network, name);
4609 connman_network_set_blob(network, "WiFi.SSID",
4611 #if defined TIZEN_EXT
4612 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4614 connman_network_set_vsie_list(network, vsie_list);
4616 DBG("vsie_list is NULL");
4617 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4618 connman_network_set_countrycode(network, country_code);
4619 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4620 connman_network_set_phy_mode(network, phy_mode);
4622 connman_network_set_string(network, "WiFi.Security", security);
4623 connman_network_set_strength(network,
4624 calculate_strength(supplicant_network));
4625 connman_network_set_bool(network, "WiFi.WPS", wps);
4628 /* Is AP advertizing for WPS association?
4629 * If so, we decide to use WPS by default */
4630 if (wps_ready && wps_pbc &&
4632 #if !defined TIZEN_EXT
4633 connman_network_set_bool(network, "WiFi.UseWPS", true);
4635 DBG("wps is activating by ap but ignore it.");
4640 connman_network_set_frequency(network,
4641 g_supplicant_network_get_frequency(supplicant_network));
4642 #if defined TIZEN_EXT
4643 connman_network_set_bssid(network,
4644 g_supplicant_network_get_bssid(supplicant_network));
4645 connman_network_set_maxrate(network,
4646 g_supplicant_network_get_maxrate(supplicant_network));
4647 connman_network_set_enc_mode(network,
4648 g_supplicant_network_get_enc_mode(supplicant_network));
4649 connman_network_set_rsn_mode(network,
4650 g_supplicant_network_get_rsn_mode(supplicant_network));
4651 connman_network_set_keymgmt(network,
4652 g_supplicant_network_get_keymgmt(supplicant_network));
4653 connman_network_set_bool(network, "WiFi.HS20AP",
4654 g_supplicant_network_is_hs20AP(supplicant_network));
4655 connman_network_set_bssid_list(network,
4656 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4658 connman_network_set_available(network, true);
4659 connman_network_set_string(network, "WiFi.Mode", mode);
4661 #if defined TIZEN_EXT
4666 connman_network_set_group(network, group);
4668 #if defined TIZEN_EXT
4669 if (wifi_first_scan == true)
4670 found_with_first_scan = true;
4673 if (wifi->hidden && ssid) {
4674 #if defined TIZEN_EXT
4675 if (network_security(wifi->hidden->security) ==
4676 network_security(security) &&
4678 if (!g_strcmp0(wifi->hidden->security, security) &&
4680 wifi->hidden->ssid_len == ssid_len &&
4681 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4682 connman_network_connect_hidden(network,
4683 wifi->hidden->identity,
4684 wifi->hidden->passphrase,
4685 wifi->hidden->user_data);
4686 wifi->hidden->user_data = NULL;
4687 hidden_free(wifi->hidden);
4688 wifi->hidden = NULL;
4693 static void network_removed(GSupplicantNetwork *network)
4695 GSupplicantInterface *interface;
4696 struct wifi_data *wifi;
4697 const char *name, *identifier;
4698 struct connman_network *connman_network;
4700 #if defined TIZEN_EXT_WIFI_MESH
4702 mode = g_supplicant_network_get_mode(network);
4703 if (!g_strcmp0(mode, "mesh")) {
4704 mesh_peer_removed(network);
4709 interface = g_supplicant_network_get_interface(network);
4710 wifi = g_supplicant_interface_get_data(interface);
4711 identifier = g_supplicant_network_get_identifier(network);
4712 name = g_supplicant_network_get_name(network);
4714 DBG("name %s", name);
4719 connman_network = connman_device_get_network(wifi->device, identifier);
4720 if (!connman_network)
4723 #if defined TIZEN_EXT
4724 if (connman_network == wifi->scan_pending_network)
4725 wifi->scan_pending_network = NULL;
4727 if (connman_network == wifi->pending_network)
4728 wifi->pending_network = NULL;
4730 if(connman_network_get_connecting(connman_network) == true){
4731 connman_network_set_connected(connman_network, false);
4735 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4737 connman_device_remove_network(wifi->device, connman_network);
4738 connman_network_unref(connman_network);
4741 static void network_changed(GSupplicantNetwork *network, const char *property)
4743 GSupplicantInterface *interface;
4744 struct wifi_data *wifi;
4745 const char *name, *identifier;
4746 struct connman_network *connman_network;
4748 #if defined TIZEN_EXT
4749 const unsigned char *bssid;
4750 unsigned int maxrate;
4753 const unsigned char *country_code;
4754 ieee80211_modes_e phy_mode;
4758 interface = g_supplicant_network_get_interface(network);
4759 wifi = g_supplicant_interface_get_data(interface);
4760 identifier = g_supplicant_network_get_identifier(network);
4761 name = g_supplicant_network_get_name(network);
4763 DBG("name %s", name);
4768 connman_network = connman_device_get_network(wifi->device, identifier);
4769 if (!connman_network)
4772 if (g_str_equal(property, "Signal")) {
4773 connman_network_set_strength(connman_network,
4774 calculate_strength(network));
4775 connman_network_update(connman_network);
4778 #if defined TIZEN_EXT
4779 bssid = g_supplicant_network_get_bssid(network);
4780 maxrate = g_supplicant_network_get_maxrate(network);
4781 frequency = g_supplicant_network_get_frequency(network);
4782 wps = g_supplicant_network_get_wps(network);
4783 phy_mode = g_supplicant_network_get_phy_mode(network);
4785 connman_network_set_bssid(connman_network, bssid);
4786 connman_network_set_maxrate(connman_network, maxrate);
4787 connman_network_set_frequency(connman_network, frequency);
4788 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4789 country_code = g_supplicant_network_get_countrycode(network);
4790 connman_network_set_countrycode(connman_network, country_code);
4791 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4792 connman_network_set_bssid_list(connman_network, bssid_list);
4793 connman_network_set_phy_mode(connman_network, phy_mode);
4795 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4796 connman_network_get_associating(connman_network))
4797 network_connect(connman_network);
4801 static void network_associated(GSupplicantNetwork *network)
4803 GSupplicantInterface *interface;
4804 struct wifi_data *wifi;
4805 struct connman_network *connman_network;
4806 const char *identifier;
4810 interface = g_supplicant_network_get_interface(network);
4814 wifi = g_supplicant_interface_get_data(interface);
4818 identifier = g_supplicant_network_get_identifier(network);
4820 connman_network = connman_device_get_network(wifi->device, identifier);
4821 if (!connman_network)
4824 if (wifi->network) {
4825 if (wifi->network == connman_network)
4829 * This should never happen, we got associated with
4830 * a network different than the one we were expecting.
4832 DBG("Associated to %p while expecting %p",
4833 connman_network, wifi->network);
4835 connman_network_set_associating(wifi->network, false);
4838 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4840 wifi->network = connman_network_ref(connman_network);
4844 * Interface state changes callback (interface_state) is always
4845 * called before network_associated callback thus we need to call
4846 * interface_state again in order to process the new state now that
4847 * we have the network properly set.
4849 interface_state(interface);
4852 static void apply_peer_services(GSupplicantPeer *peer,
4853 struct connman_peer *connman_peer)
4855 const unsigned char *data;
4860 connman_peer_reset_services(connman_peer);
4862 data = g_supplicant_peer_get_widi_ies(peer, &length);
4864 connman_peer_add_service(connman_peer,
4865 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4869 static void add_station(const char *mac)
4871 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4875 static void remove_station(const char *mac)
4877 connman_technology_tethering_remove_station(mac);
4880 static void peer_found(GSupplicantPeer *peer)
4882 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4883 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4884 struct connman_peer *connman_peer;
4885 const char *identifier, *name;
4887 #if defined TIZEN_EXT
4891 identifier = g_supplicant_peer_get_identifier(peer);
4892 name = g_supplicant_peer_get_name(peer);
4894 DBG("ident: %s", identifier);
4896 connman_peer = connman_peer_get(wifi->device, identifier);
4900 connman_peer = connman_peer_create(identifier);
4901 connman_peer_set_name(connman_peer, name);
4902 connman_peer_set_device(connman_peer, wifi->device);
4903 apply_peer_services(peer, connman_peer);
4905 ret = connman_peer_register(connman_peer);
4906 if (ret < 0 && ret != -EALREADY)
4907 connman_peer_unref(connman_peer);
4909 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4912 static void peer_lost(GSupplicantPeer *peer)
4914 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4915 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4916 struct connman_peer *connman_peer;
4917 const char *identifier;
4922 identifier = g_supplicant_peer_get_identifier(peer);
4924 DBG("ident: %s", identifier);
4926 connman_peer = connman_peer_get(wifi->device, identifier);
4928 if (wifi->p2p_connecting &&
4929 wifi->pending_peer == connman_peer) {
4930 peer_connect_timeout(wifi);
4932 connman_peer_unregister(connman_peer);
4933 connman_peer_unref(connman_peer);
4936 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4939 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4941 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4942 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4943 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4944 struct connman_peer *connman_peer;
4945 const char *identifier;
4947 identifier = g_supplicant_peer_get_identifier(peer);
4949 DBG("ident: %s", identifier);
4954 connman_peer = connman_peer_get(wifi->device, identifier);
4959 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4960 apply_peer_services(peer, connman_peer);
4961 connman_peer_services_changed(connman_peer);
4963 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4964 if (!g_supplicant_peer_is_in_a_group(peer))
4965 p_state = CONNMAN_PEER_STATE_IDLE;
4967 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4969 case G_SUPPLICANT_PEER_GROUP_STARTED:
4971 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4972 p_state = CONNMAN_PEER_STATE_IDLE;
4974 case G_SUPPLICANT_PEER_GROUP_JOINED:
4975 connman_peer_set_iface_address(connman_peer,
4976 g_supplicant_peer_get_iface_address(peer));
4978 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4979 p_state = CONNMAN_PEER_STATE_IDLE;
4981 case G_SUPPLICANT_PEER_GROUP_FAILED:
4982 if (g_supplicant_peer_has_requested_connection(peer))
4983 p_state = CONNMAN_PEER_STATE_IDLE;
4985 p_state = CONNMAN_PEER_STATE_FAILURE;
4989 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4990 p_state == CONNMAN_PEER_STATE_FAILURE) {
4991 if (wifi->p2p_connecting
4992 && connman_peer == wifi->pending_peer)
4993 peer_cancel_timeout(wifi);
4995 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4998 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
5001 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
5002 GSupplicantInterface *g_iface;
5003 struct wifi_data *g_wifi;
5005 g_iface = g_supplicant_peer_get_group_interface(peer);
5009 g_wifi = g_supplicant_interface_get_data(g_iface);
5013 connman_peer_set_as_master(connman_peer,
5014 !g_supplicant_peer_is_client(peer));
5015 connman_peer_set_sub_device(connman_peer, g_wifi->device);
5018 * If wpa_supplicant didn't create a dedicated p2p-group
5019 * interface then mark this interface as p2p_device to avoid
5020 * scan and auto-scan are launched on it while P2P is connected.
5022 if (!g_list_find(p2p_iface_list, g_wifi))
5023 wifi->p2p_device = true;
5026 connman_peer_set_state(connman_peer, p_state);
5029 static void peer_request(GSupplicantPeer *peer)
5031 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5032 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5033 struct connman_peer *connman_peer;
5034 const char *identifier;
5036 #if defined TIZEN_EXT
5041 identifier = g_supplicant_peer_get_identifier(peer);
5043 DBG("ident: %s", identifier);
5045 connman_peer = connman_peer_get(wifi->device, identifier);
5049 connman_peer_request_connection(connman_peer);
5052 #if defined TIZEN_EXT
5053 static void system_power_off(void)
5056 struct wifi_data *wifi;
5057 struct connman_service *service;
5058 struct connman_ipconfig *ipconfig_ipv4;
5060 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
5061 for (list = iface_list; list; list = list->next) {
5064 if (wifi->network != NULL) {
5065 service = connman_service_lookup_from_network(wifi->network);
5066 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5067 __connman_dhcp_stop(ipconfig_ipv4);
5073 static void network_merged(GSupplicantNetwork *network)
5075 GSupplicantInterface *interface;
5076 GSupplicantState state;
5077 struct wifi_data *wifi;
5078 const char *identifier;
5079 struct connman_network *connman_network;
5083 interface = g_supplicant_network_get_interface(network);
5087 state = g_supplicant_interface_get_state(interface);
5088 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5091 wifi = g_supplicant_interface_get_data(interface);
5095 identifier = g_supplicant_network_get_identifier(network);
5097 connman_network = connman_device_get_network(wifi->device, identifier);
5098 if (!connman_network)
5101 DBG("merged identifier %s", identifier);
5103 if (wifi->connected == FALSE) {
5105 case G_SUPPLICANT_STATE_AUTHENTICATING:
5106 case G_SUPPLICANT_STATE_ASSOCIATING:
5107 case G_SUPPLICANT_STATE_ASSOCIATED:
5108 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5109 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5110 connman_network_set_associating(connman_network, TRUE);
5112 case G_SUPPLICANT_STATE_COMPLETED:
5113 connman_network_set_connected(connman_network, TRUE);
5116 DBG("Not handled the state : %d", state);
5121 ishs20AP = g_supplicant_network_is_hs20AP(network);
5124 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5125 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5126 connman_network_set_string(connman_network, "WiFi.EAP",
5128 connman_network_set_string(connman_network, "WiFi.Identity",
5129 g_supplicant_network_get_identity(network));
5130 connman_network_set_string(connman_network, "WiFi.Phase2",
5131 g_supplicant_network_get_phase2(network));
5136 wifi->network = connman_network;
5139 static void assoc_failed(void *user_data)
5141 struct connman_network *network = user_data;
5142 connman_network_set_associating(network, false);
5146 static void debug(const char *str)
5148 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5149 connman_debug("%s", str);
5152 static void disconnect_reasoncode(GSupplicantInterface *interface,
5155 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5158 wifi->disconnect_code = reasoncode;
5162 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5164 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5167 wifi->assoc_code = status_code;
5171 static const GSupplicantCallbacks callbacks = {
5172 .system_ready = system_ready,
5173 .system_killed = system_killed,
5174 .interface_added = interface_added,
5175 .interface_state = interface_state,
5176 .interface_removed = interface_removed,
5177 .p2p_support = p2p_support,
5178 .scan_started = scan_started,
5179 .scan_finished = scan_finished,
5180 .ap_create_fail = ap_create_fail,
5181 .network_added = network_added,
5182 .network_removed = network_removed,
5183 .network_changed = network_changed,
5184 .network_associated = network_associated,
5185 .add_station = add_station,
5186 .remove_station = remove_station,
5187 .peer_found = peer_found,
5188 .peer_lost = peer_lost,
5189 .peer_changed = peer_changed,
5190 .peer_request = peer_request,
5191 #if defined TIZEN_EXT
5192 .system_power_off = system_power_off,
5193 .network_merged = network_merged,
5194 .assoc_failed = assoc_failed,
5197 .disconnect_reasoncode = disconnect_reasoncode,
5198 .assoc_status_code = assoc_status_code,
5199 #if defined TIZEN_EXT_WIFI_MESH
5200 .mesh_support = mesh_support,
5201 .mesh_group_started = mesh_group_started,
5202 .mesh_group_removed = mesh_group_removed,
5203 .mesh_peer_connected = mesh_peer_connected,
5204 .mesh_peer_disconnected = mesh_peer_disconnected,
5209 static int tech_probe(struct connman_technology *technology)
5211 wifi_technology = technology;
5216 static void tech_remove(struct connman_technology *technology)
5218 wifi_technology = NULL;
5221 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5222 const char *passphrase)
5224 GSupplicantSSID *ap;
5226 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5230 ap->mode = G_SUPPLICANT_MODE_MASTER;
5231 #if defined TIZEN_EXT
5232 ap->ssid = (void *) ssid;
5236 ap->ssid_len = strlen(ssid);
5240 if (!passphrase || strlen(passphrase) == 0) {
5241 ap->security = G_SUPPLICANT_SECURITY_NONE;
5242 ap->passphrase = NULL;
5244 ap->security = G_SUPPLICANT_SECURITY_PSK;
5245 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5246 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5247 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5248 ap->passphrase = passphrase;
5254 static void ap_start_callback(int result, GSupplicantInterface *interface,
5257 struct wifi_tethering_info *info = user_data;
5259 DBG("result %d index %d bridge %s",
5260 result, info->wifi->index, info->wifi->bridge);
5262 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5263 connman_inet_remove_from_bridge(info->wifi->index,
5264 info->wifi->bridge);
5266 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5267 connman_technology_tethering_notify(info->technology, false);
5268 g_free(info->wifi->tethering_param->ssid);
5269 g_free(info->wifi->tethering_param);
5270 info->wifi->tethering_param = NULL;
5274 g_free(info->ifname);
5278 static void ap_create_callback(int result,
5279 GSupplicantInterface *interface,
5282 struct wifi_tethering_info *info = user_data;
5284 DBG("result %d ifname %s", result,
5285 g_supplicant_interface_get_ifname(interface));
5287 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5288 connman_inet_remove_from_bridge(info->wifi->index,
5289 info->wifi->bridge);
5291 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5292 connman_technology_tethering_notify(info->technology, false);
5293 g_free(info->wifi->tethering_param->ssid);
5294 g_free(info->wifi->tethering_param);
5295 info->wifi->tethering_param = NULL;
5299 g_free(info->ifname);
5305 info->wifi->interface = interface;
5306 g_supplicant_interface_set_data(interface, info->wifi);
5308 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5309 connman_error("Failed to set interface ap_scan property");
5311 g_supplicant_interface_connect(interface, info->ssid,
5312 ap_start_callback, info);
5315 static void sta_remove_callback(int result,
5316 GSupplicantInterface *interface,
5319 struct wifi_tethering_info *info = user_data;
5320 const char *driver = connman_option_get_string("wifi");
5322 DBG("ifname %s result %d ", info->ifname, result);
5324 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5325 info->wifi->tethering = false;
5326 connman_technology_tethering_notify(info->technology, false);
5328 g_free(info->ifname);
5332 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5333 g_free(info->wifi->tethering_param->ssid);
5334 g_free(info->wifi->tethering_param);
5335 info->wifi->tethering_param = NULL;
5340 info->wifi->interface = NULL;
5342 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5347 static int enable_wifi_tethering(struct connman_technology *technology,
5348 const char *bridge, const char *identifier,
5349 const char *passphrase, bool available)
5352 GSupplicantInterface *interface;
5353 struct wifi_data *wifi;
5354 struct wifi_tethering_info *info;
5359 for (list = iface_list; list; list = list->next) {
5362 DBG("wifi %p network %p pending_network %p", wifi,
5363 wifi->network, wifi->pending_network);
5365 interface = wifi->interface;
5370 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5373 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5375 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5376 DBG("%s does not support AP mode (detected)", ifname);
5380 mode = g_supplicant_interface_get_mode(interface);
5381 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5382 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5383 DBG("%s does not support AP mode (capability)", ifname);
5387 if (wifi->network && available)
5390 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5394 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5395 if (!wifi->tethering_param) {
5401 info->technology = technology;
5402 info->wifi->bridge = bridge;
5403 info->ssid = ssid_ap_init(identifier, passphrase);
5407 info->ifname = g_strdup(ifname);
5411 wifi->tethering_param->technology = technology;
5412 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5413 if (!wifi->tethering_param->ssid)
5416 info->wifi->tethering = true;
5417 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5419 berr = connman_technology_tethering_notify(technology, true);
5423 err = g_supplicant_interface_remove(interface,
5424 sta_remove_callback,
5427 DBG("tethering wifi %p ifname %s", wifi, ifname);
5432 g_free(info->ifname);
5435 g_free(wifi->tethering_param);
5436 wifi->tethering_param = NULL;
5439 * Remove bridge if it was correctly created but remove
5440 * operation failed. Instead, if bridge creation failed then
5441 * break out and do not try again on another interface,
5442 * bridge set-up does not depend on it.
5445 connman_technology_tethering_notify(technology, false);
5453 static int tech_set_tethering(struct connman_technology *technology,
5454 const char *identifier, const char *passphrase,
5455 const char *bridge, bool enabled)
5458 struct wifi_data *wifi;
5464 for (list = iface_list; list; list = list->next) {
5467 if (wifi->tethering) {
5468 wifi->tethering = false;
5470 connman_inet_remove_from_bridge(wifi->index,
5472 wifi->bridged = false;
5476 connman_technology_tethering_notify(technology, false);
5481 DBG("trying tethering for available devices");
5482 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5486 DBG("trying tethering for any device");
5487 err = enable_wifi_tethering(technology, bridge, identifier,
5494 static void regdom_callback(int result, const char *alpha2, void *user_data)
5498 if (!wifi_technology)
5504 connman_technology_regdom_notify(wifi_technology, alpha2);
5507 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5509 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5512 static struct connman_technology_driver tech_driver = {
5514 .type = CONNMAN_SERVICE_TYPE_WIFI,
5515 .probe = tech_probe,
5516 .remove = tech_remove,
5517 .set_tethering = tech_set_tethering,
5518 .set_regdom = tech_set_regdom,
5521 static int wifi_init(void)
5525 err = connman_network_driver_register(&network_driver);
5529 err = g_supplicant_register(&callbacks);
5531 connman_network_driver_unregister(&network_driver);
5535 err = connman_technology_driver_register(&tech_driver);
5537 g_supplicant_unregister(&callbacks);
5538 connman_network_driver_unregister(&network_driver);
5542 #if defined TIZEN_EXT
5543 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5548 static void wifi_exit(void)
5552 connman_technology_driver_unregister(&tech_driver);
5554 g_supplicant_unregister(&callbacks);
5556 connman_network_driver_unregister(&network_driver);
5558 #if defined TIZEN_EXT
5559 g_hash_table_unref(failed_bssids);
5563 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5564 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)