5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <linux/if_arp.h>
34 #include <linux/wireless.h>
35 #include <net/ethernet.h>
38 #define IFF_LOWER_UP 0x10000
41 #include <dbus/dbus.h>
44 #define CONNMAN_API_SUBJECT_TO_CHANGE
45 #include <connman/plugin.h>
46 #include <connman/inet.h>
47 #include <connman/device.h>
48 #include <connman/rtnl.h>
49 #include <connman/technology.h>
50 #include <connman/service.h>
51 #include <connman/peer.h>
52 #include <connman/log.h>
53 #include <connman/option.h>
54 #include <connman/storage.h>
55 #include <include/setting.h>
56 #include <connman/provision.h>
57 #include <connman/utsname.h>
58 #include <connman/machine.h>
60 #include <gsupplicant/gsupplicant.h>
62 #define CLEANUP_TIMEOUT 8 /* in seconds */
63 #define INACTIVE_TIMEOUT 12 /* in seconds */
64 #define FAVORITE_MAXIMUM_RETRIES 2
66 #define BGSCAN_DEFAULT "simple:30:-45:300"
67 #define AUTOSCAN_DEFAULT "exponential:3:300"
69 #define P2P_FIND_TIMEOUT 30
70 #define P2P_CONNECTION_TIMEOUT 100
71 #define P2P_LISTEN_PERIOD 500
72 #define P2P_LISTEN_INTERVAL 2000
74 #define ASSOC_STATUS_NO_CLIENT 17
76 #define LOAD_SHAPING_MAX_RETRIES 7
78 #define LOAD_SHAPING_MAX_RETRIES 3
82 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
85 static struct connman_technology *wifi_technology = NULL;
86 static struct connman_technology *p2p_technology = NULL;
88 enum wifi_ap_capability{
90 WIFI_AP_SUPPORTED = 1,
91 WIFI_AP_NOT_SUPPORTED = 2,
94 struct hidden_params {
96 unsigned int ssid_len;
98 char *anonymous_identity;
100 char *altsubject_match;
101 char *domain_suffix_match;
105 GSupplicantScanParams *scan_params;
110 * Used for autoscan "emulation".
111 * Should be removed when wpa_s autoscan support will be by default.
113 struct autoscan_params {
117 unsigned int timeout;
120 struct wifi_tethering_info {
121 struct wifi_data *wifi;
122 struct connman_technology *technology;
124 GSupplicantSSID *ssid;
129 struct connman_device *device;
130 struct connman_network *network;
131 struct connman_network *pending_network;
133 GSupplicantInterface *interface;
134 GSupplicantState state;
138 enum wifi_ap_capability ap_supported;
140 bool interface_ready;
146 int load_shaping_retries;
147 struct hidden_params *hidden;
148 bool postpone_hidden;
149 struct wifi_tethering_info *tethering_param;
151 * autoscan "emulation".
153 struct autoscan_params *autoscan;
155 GSupplicantScanParams *scan_params;
156 unsigned int p2p_find_timeout;
157 unsigned int p2p_connection_timeout;
158 struct connman_peer *pending_peer;
163 #if defined TIZEN_EXT
164 int assoc_retry_count;
165 struct connman_network *scan_pending_network;
166 bool allow_full_scan;
167 unsigned int automaxspeed_timeout;
168 GSupplicantScanParams *hidden_scan_params;
172 #if defined TIZEN_EXT_WIFI_MESH
174 struct wifi_mesh_info *mesh_info;
178 #if defined TIZEN_EXT
182 #define TIZEN_ASSOC_RETRY_COUNT 4
184 static gboolean wifi_first_scan = false;
185 static gboolean found_with_first_scan = false;
186 static gboolean is_wifi_notifier_registered = false;
187 static GHashTable *failed_bssids = NULL;
188 static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
192 static GList *iface_list = NULL;
194 static GList *pending_wifi_device = NULL;
195 static GList *p2p_iface_list = NULL;
196 bool wfd_service_registered = false;
198 static void start_autoscan(struct connman_device *device);
200 static int tech_set_tethering(struct connman_technology *technology,
201 const char *identifier, const char *passphrase,
202 const char *bridge, bool enabled);
204 #if defined TIZEN_EXT
205 #define NETCONFIG_SERVICE "net.netconfig"
206 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
207 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
209 struct enc_method_call_data {
210 DBusConnection *connection;
211 struct connman_network *network;
214 static struct enc_method_call_data encrypt_request_data;
216 static void encryption_request_reply(DBusPendingCall *call,
221 DBusMessageIter args;
223 struct connman_service *service;
224 gchar* encrypted_value = NULL;
225 struct connman_network *network = encrypt_request_data.network;
229 reply = dbus_pending_call_steal_reply(call);
231 dbus_error_init(&error);
232 if (dbus_set_error_from_message(&error, reply)) {
233 DBG("send_encryption_request() %s %s", error.name, error.message);
234 dbus_error_free(&error);
238 if (dbus_message_iter_init(reply, &args) == FALSE)
241 dbus_message_iter_get_basic(&args, &out_data);
243 encrypted_value = g_strdup((const gchar *)out_data);
244 service = connman_service_lookup_from_network(network);
247 DBG("encryption result: no service");
251 if (connman_service_get_favorite(service)) {
252 __connman_service_set_passphrase(service, encrypted_value);
253 __connman_service_save(service);
255 connman_network_set_string(network, "WiFi.Passphrase",
258 DBG("encryption result: succeeded");
261 dbus_message_unref(reply);
262 dbus_pending_call_unref(call);
263 dbus_connection_unref(encrypt_request_data.connection);
264 g_free(encrypted_value);
266 encrypt_request_data.connection = NULL;
267 encrypt_request_data.network = NULL;
270 static int send_encryption_request(const char *passphrase,
271 struct connman_network *network)
273 DBusConnection *connection = NULL;
274 DBusMessage *msg = NULL;
275 DBusPendingCall *call;
278 DBG("Invalid parameter");
282 connection = connman_dbus_get_connection();
284 DBG("dbus connection does not exist");
288 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
289 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
291 dbus_connection_unref(connection);
295 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
298 if (!dbus_connection_send_with_reply(connection, msg,
299 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
300 dbus_message_unref(msg);
301 dbus_connection_unref(connection);
306 dbus_message_unref(msg);
307 dbus_connection_unref(connection);
311 encrypt_request_data.connection = connection;
312 encrypt_request_data.network = network;
314 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
315 dbus_message_unref(msg);
321 static int p2p_tech_probe(struct connman_technology *technology)
323 p2p_technology = technology;
328 static void p2p_tech_remove(struct connman_technology *technology)
330 p2p_technology = NULL;
333 static struct connman_technology_driver p2p_tech_driver = {
335 .type = CONNMAN_SERVICE_TYPE_P2P,
336 .probe = p2p_tech_probe,
337 .remove = p2p_tech_remove,
340 static bool is_p2p_connecting(void)
344 for (list = iface_list; list; list = list->next) {
345 struct wifi_data *wifi = list->data;
347 if (wifi->p2p_connecting)
354 static void add_pending_wifi_device(struct wifi_data *wifi)
356 if (g_list_find(pending_wifi_device, wifi))
359 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
362 #if defined TIZEN_EXT_WIFI_MESH
363 struct wifi_mesh_info {
364 struct wifi_data *wifi;
365 GSupplicantInterface *interface;
366 struct connman_mesh *mesh;
373 struct mesh_change_peer_status_info {
375 enum connman_mesh_peer_status peer_status;
376 mesh_change_peer_status_cb_t callback;
380 static struct connman_technology_driver mesh_tech_driver = {
382 .type = CONNMAN_SERVICE_TYPE_MESH,
385 static void mesh_interface_create_callback(int result,
386 GSupplicantInterface *interface,
389 struct wifi_mesh_info *mesh_info = user_data;
390 struct wifi_data *wifi;
391 bool success = false;
393 DBG("result %d ifname %s, mesh_info %p", result,
394 g_supplicant_interface_get_ifname(interface),
397 if (result < 0 || !mesh_info)
400 wifi = mesh_info->wifi;
402 mesh_info->interface = interface;
403 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
404 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
405 DBG("Mesh Interface identifier %s", mesh_info->identifier);
406 wifi->mesh_interface = true;
407 wifi->mesh_info = mesh_info;
408 g_supplicant_interface_set_data(interface, wifi);
412 connman_mesh_notify_interface_create(success);
415 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
418 struct wifi_data *wifi;
419 struct wifi_mesh_info *mesh_info;
420 const char *wifi_ifname;
421 bool parent_found = false;
422 const char *driver = "nl80211";
424 for (list = iface_list; list; list = list->next) {
427 if (!g_supplicant_interface_has_mesh(wifi->interface))
430 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
434 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
441 DBG("Parent interface %s doesn't exist", parent_ifname);
445 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
449 mesh_info->wifi = wifi;
450 mesh_info->ifname = g_strdup(ifname);
451 mesh_info->parent_ifname = g_strdup(parent_ifname);
453 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
454 mesh_interface_create_callback, mesh_info);
458 static void mesh_interface_remove_callback(int result,
459 GSupplicantInterface *interface,
462 struct wifi_data *wifi = user_data;
463 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
464 bool success = false;
466 DBG("result %d mesh_info %p", result, mesh_info);
468 if (result < 0 || !mesh_info)
471 mesh_info->interface = NULL;
472 g_free(mesh_info->parent_ifname);
473 g_free(mesh_info->ifname);
474 g_free(mesh_info->identifier);
476 wifi->mesh_interface = false;
477 wifi->mesh_info = NULL;
481 connman_mesh_notify_interface_remove(success);
484 static int remove_mesh_interface(const char *ifname)
487 struct wifi_data *wifi;
488 struct wifi_mesh_info *mesh_info;
489 bool mesh_if_found = false;
492 for (list = iface_list; list; list = list->next) {
495 if (wifi->mesh_interface) {
496 mesh_if_found = true;
501 if (!mesh_if_found) {
502 DBG("Mesh interface %s doesn't exist", ifname);
506 mesh_info = wifi->mesh_info;
507 ret = g_supplicant_interface_remove(mesh_info->interface,
508 mesh_interface_remove_callback, wifi);
515 static void mesh_disconnect_callback(int result,
516 GSupplicantInterface *interface, void *user_data)
518 struct connman_mesh *mesh = user_data;
520 DBG("result %d interface %p mesh %p", result, interface, mesh);
523 static int mesh_peer_disconnect(struct connman_mesh *mesh)
526 struct wifi_data *wifi;
527 struct wifi_mesh_info *mesh_info;
528 bool mesh_if_found = false;
529 GSupplicantInterface *interface;
531 for (list = iface_list; list; list = list->next) {
534 if (wifi->mesh_interface) {
535 mesh_if_found = true;
540 if (!mesh_if_found) {
541 DBG("Mesh interface is not created");
545 mesh_info = wifi->mesh_info;
547 interface = mesh_info->interface;
548 return g_supplicant_interface_disconnect(interface,
549 mesh_disconnect_callback, mesh);
552 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
555 struct connman_mesh *mesh = user_data;
556 DBG("mesh %p result %d", mesh, result);
559 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
561 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
564 static GSupplicantSecurity mesh_network_security(const char *security)
566 if (g_str_equal(security, "none"))
567 return G_SUPPLICANT_SECURITY_NONE;
568 else if (g_str_equal(security, "sae"))
569 return G_SUPPLICANT_SECURITY_SAE;
571 return G_SUPPLICANT_SECURITY_UNKNOWN;
574 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
577 const char *security;
582 memset(ssid, 0, sizeof(*ssid));
583 ssid->mode = G_SUPPLICANT_MODE_MESH;
585 security = connman_mesh_get_security(mesh);
586 ssid->security = mesh_network_security(security);
588 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
589 ssid->passphrase = connman_mesh_get_passphrase(mesh);
591 ssid->freq = connman_mesh_get_frequency(mesh);
592 name = connman_mesh_get_name(mesh);
594 ssid->ssid_len = strlen(name);
595 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
596 memcpy(ssid->ssid, name, ssid->ssid_len);
601 static int mesh_peer_connect(struct connman_mesh *mesh)
604 struct wifi_data *wifi;
605 struct wifi_mesh_info *mesh_info;
606 bool mesh_if_found = false;
607 GSupplicantInterface *interface;
608 GSupplicantSSID *ssid;
610 for (list = iface_list; list; list = list->next) {
613 if (wifi->mesh_interface) {
614 mesh_if_found = true;
619 if (!mesh_if_found) {
620 DBG("Mesh interface is not created");
624 mesh_info = wifi->mesh_info;
626 interface = mesh_info->interface;
628 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
632 mesh_info->mesh = mesh;
634 mesh_ssid_init(ssid, mesh);
635 return g_supplicant_interface_connect(interface, ssid,
636 mesh_connect_callback, mesh);
639 static void mesh_peer_change_status_callback(int result,
640 GSupplicantInterface *interface,
643 struct mesh_change_peer_status_info *data = user_data;
645 DBG("result %d Peer Status %d", result, data->peer_status);
647 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
648 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
649 connman_mesh_remove_connected_peer(data->peer_address, 52);
653 data->callback(result, data->user_data);
655 g_free(data->peer_address);
660 static int mesh_change_peer_status(const char *peer_address,
661 enum connman_mesh_peer_status status,
662 mesh_change_peer_status_cb_t callback, void *user_data)
665 struct wifi_data *wifi;
666 struct wifi_mesh_info *mesh_info;
667 bool mesh_if_found = false;
668 GSupplicantInterface *interface;
669 struct mesh_change_peer_status_info *data;
672 for (list = iface_list; list; list = list->next) {
675 if (wifi->mesh_interface) {
676 mesh_if_found = true;
681 if (!mesh_if_found) {
682 DBG("Mesh interface is not created");
686 mesh_info = wifi->mesh_info;
688 interface = mesh_info->interface;
691 case CONNMAN_MESH_PEER_ADD:
692 method = "MeshPeerAdd";
694 case CONNMAN_MESH_PEER_REMOVE:
695 method = "MeshPeerRemove";
698 DBG("Invalid method");
702 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
704 DBG("Memory allocation failed");
708 data->peer_address = g_strdup(peer_address);
709 data->peer_status = status;
710 data->callback = callback;
711 data->user_data = user_data;
713 return g_supplicant_interface_mesh_peer_change_status(interface,
714 mesh_peer_change_status_callback, peer_address, method,
718 static struct connman_mesh_driver mesh_driver = {
719 .add_interface = add_mesh_interface,
720 .remove_interface = remove_mesh_interface,
721 .connect = mesh_peer_connect,
722 .disconnect = mesh_peer_disconnect,
723 .change_peer_status = mesh_change_peer_status,
726 static void mesh_support(GSupplicantInterface *interface)
730 if (!g_supplicant_interface_has_mesh(interface))
733 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
734 DBG("Could not register Mesh technology driver");
738 connman_mesh_driver_register(&mesh_driver);
741 static void check_mesh_technology(void)
743 bool mesh_exists = false;
746 for (list = iface_list; list; list = list->next) {
747 struct wifi_data *w = list->data;
750 g_supplicant_interface_has_mesh(w->interface))
755 connman_technology_driver_unregister(&mesh_tech_driver);
756 connman_mesh_driver_unregister(&mesh_driver);
760 static void mesh_group_started(GSupplicantInterface *interface)
762 struct wifi_data *wifi;
763 struct wifi_mesh_info *mesh_info;
764 struct connman_mesh *mesh;
765 const unsigned char *ssid;
766 unsigned int ssid_len;
769 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
770 memcpy(name, ssid, ssid_len);
771 name[ssid_len] = '\0';
772 DBG("name %s", name);
773 wifi = g_supplicant_interface_get_data(interface);
774 DBG("wifi %p", wifi);
779 mesh_info = wifi->mesh_info;
783 mesh = mesh_info->mesh;
787 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
790 static void mesh_group_removed(GSupplicantInterface *interface)
792 struct wifi_data *wifi;
793 struct wifi_mesh_info *mesh_info;
794 struct connman_mesh *mesh;
795 const unsigned char *ssid;
796 unsigned int ssid_len;
797 int disconnect_reason;
800 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
801 memcpy(name, ssid, ssid_len);
802 name[ssid_len] = '\0';
803 DBG("name %s", name);
805 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
806 DBG("Disconnect Reason %d", disconnect_reason);
808 wifi = g_supplicant_interface_get_data(interface);
809 DBG("wifi %p", wifi);
814 mesh_info = wifi->mesh_info;
818 mesh = connman_get_connected_mesh_from_name(name);
820 DBG("%s is not connected", name);
821 mesh = connman_get_connecting_mesh_from_name(name);
823 DBG("%s is not connecting", name);
828 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
829 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
832 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
834 const char *peer_address;
836 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
841 DBG("Peer %s connected", peer_address);
842 connman_mesh_add_connected_peer(peer_address);
845 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
847 const char *peer_address;
850 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
855 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
857 DBG("Peer %s disconnected with reason %d", peer_address, reason);
858 connman_mesh_remove_connected_peer(peer_address, reason);
862 static struct wifi_data *get_pending_wifi_data(const char *ifname)
866 for (list = pending_wifi_device; list; list = list->next) {
867 struct wifi_data *wifi;
868 const char *dev_name;
871 if (!wifi || !wifi->device)
874 dev_name = connman_device_get_string(wifi->device, "Interface");
875 if (!g_strcmp0(ifname, dev_name)) {
876 pending_wifi_device = g_list_delete_link(
877 pending_wifi_device, list);
885 static void remove_pending_wifi_device(struct wifi_data *wifi)
889 link = g_list_find(pending_wifi_device, wifi);
894 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
897 static void peer_cancel_timeout(struct wifi_data *wifi)
899 if (wifi->p2p_connection_timeout > 0)
900 g_source_remove(wifi->p2p_connection_timeout);
902 wifi->p2p_connection_timeout = 0;
903 wifi->p2p_connecting = false;
905 if (wifi->pending_peer) {
906 connman_peer_unref(wifi->pending_peer);
907 wifi->pending_peer = NULL;
911 static gboolean peer_connect_timeout(gpointer data)
913 struct wifi_data *wifi = data;
917 if (wifi->p2p_connecting) {
918 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
919 GSupplicantPeer *gs_peer =
920 g_supplicant_interface_peer_lookup(wifi->interface,
921 connman_peer_get_identifier(wifi->pending_peer));
923 if (g_supplicant_peer_has_requested_connection(gs_peer))
924 state = CONNMAN_PEER_STATE_IDLE;
926 connman_peer_set_state(wifi->pending_peer, state);
929 peer_cancel_timeout(wifi);
934 static void peer_connect_callback(int result, GSupplicantInterface *interface,
937 struct wifi_data *wifi = user_data;
938 struct connman_peer *peer = wifi->pending_peer;
940 DBG("peer %p - %d", peer, result);
946 peer_connect_timeout(wifi);
950 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
952 wifi->p2p_connection_timeout = g_timeout_add_seconds(
953 P2P_CONNECTION_TIMEOUT,
954 peer_connect_timeout, wifi);
957 static int peer_connect(struct connman_peer *peer,
958 enum connman_peer_wps_method wps_method,
961 struct connman_device *device = connman_peer_get_device(peer);
962 GSupplicantPeerParams *peer_params;
963 GSupplicantPeer *gs_peer;
964 struct wifi_data *wifi;
968 DBG("peer %p", peer);
973 wifi = connman_device_get_data(device);
974 if (!wifi || !wifi->interface)
977 if (wifi->p2p_connecting)
980 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
981 connman_peer_get_identifier(peer));
985 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
986 pin = g_supplicant_peer_is_wps_pin(gs_peer);
988 switch (wps_method) {
989 case CONNMAN_PEER_WPS_UNKNOWN:
990 if ((pbc && pin) || pin)
993 case CONNMAN_PEER_WPS_PBC:
998 case CONNMAN_PEER_WPS_PIN:
999 if (!pin || !wps_pin)
1004 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1008 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1010 peer_params->wps_pin = g_strdup(wps_pin);
1012 peer_params->master = connman_peer_service_is_master();
1014 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1015 peer_connect_callback, wifi);
1016 if (ret == -EINPROGRESS) {
1017 wifi->pending_peer = connman_peer_ref(peer);
1018 wifi->p2p_connecting = true;
1019 } else if (ret < 0) {
1020 g_free(peer_params->path);
1021 g_free(peer_params->wps_pin);
1022 g_free(peer_params);
1028 static int peer_disconnect(struct connman_peer *peer)
1030 struct connman_device *device = connman_peer_get_device(peer);
1031 GSupplicantPeerParams peer_params = {};
1032 GSupplicantPeer *gs_peer;
1033 struct wifi_data *wifi;
1036 DBG("peer %p", peer);
1041 wifi = connman_device_get_data(device);
1045 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1046 connman_peer_get_identifier(peer));
1050 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1052 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1054 g_free(peer_params.path);
1056 if (ret == -EINPROGRESS) {
1057 peer_cancel_timeout(wifi);
1058 wifi->p2p_device = false;
1064 struct peer_service_registration {
1065 peer_service_registration_cb_t callback;
1069 static bool is_service_wfd(const unsigned char *specs, int length)
1071 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1077 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1079 struct wifi_data *wifi = data;
1081 if (!wifi->interface ||
1082 !g_supplicant_interface_has_p2p(wifi->interface))
1085 if (!wifi->servicing) {
1086 g_supplicant_interface_p2p_listen(wifi->interface,
1087 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1093 static void register_wfd_service_cb(int result,
1094 GSupplicantInterface *iface, void *user_data)
1096 struct peer_service_registration *reg_data = user_data;
1101 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1103 if (reg_data && reg_data->callback) {
1104 reg_data->callback(result, reg_data->user_data);
1109 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1110 const unsigned char *spec,
1111 int spec_length, const unsigned char *query,
1112 int query_length, int version)
1114 GSupplicantP2PServiceParams *params;
1116 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1121 params->version = version;
1122 params->service = g_memdup(spec, spec_length);
1123 } else if (query_length > 0 && spec_length > 0) {
1124 params->query = g_memdup(query, query_length);
1125 params->query_length = query_length;
1127 params->response = g_memdup(spec, spec_length);
1128 params->response_length = spec_length;
1130 params->wfd_ies = g_memdup(spec, spec_length);
1131 params->wfd_ies_length = spec_length;
1137 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1142 g_free(params->service);
1143 g_free(params->query);
1144 g_free(params->response);
1145 g_free(params->wfd_ies);
1150 static int peer_register_wfd_service(const unsigned char *specification,
1151 int specification_length,
1152 peer_service_registration_cb_t callback,
1155 struct peer_service_registration *reg_data = NULL;
1156 static GSupplicantP2PServiceParams *params;
1161 if (wfd_service_registered)
1164 params = fill_in_peer_service_params(specification,
1165 specification_length, NULL, 0, 0);
1169 reg_data = g_try_malloc0(sizeof(*reg_data));
1175 reg_data->callback = callback;
1176 reg_data->user_data = user_data;
1178 ret = g_supplicant_set_widi_ies(params,
1179 register_wfd_service_cb, reg_data);
1180 if (ret < 0 && ret != -EINPROGRESS)
1183 wfd_service_registered = true;
1187 free_peer_service_params(params);
1193 static void register_peer_service_cb(int result,
1194 GSupplicantInterface *iface, void *user_data)
1196 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1197 struct peer_service_registration *reg_data = user_data;
1199 #if defined TIZEN_EXT
1207 apply_p2p_listen_on_iface(wifi, NULL);
1209 if (reg_data->callback)
1210 reg_data->callback(result, reg_data->user_data);
1215 static int peer_register_service(const unsigned char *specification,
1216 int specification_length,
1217 const unsigned char *query,
1218 int query_length, int version,
1219 peer_service_registration_cb_t callback,
1222 struct peer_service_registration *reg_data;
1223 GSupplicantP2PServiceParams *params;
1230 if (specification && !version && !query &&
1231 is_service_wfd(specification, specification_length)) {
1232 return peer_register_wfd_service(specification,
1233 specification_length, callback, user_data);
1236 reg_data = g_try_malloc0(sizeof(*reg_data));
1240 reg_data->callback = callback;
1241 reg_data->user_data = user_data;
1243 ret_f = -EOPNOTSUPP;
1245 for (list = iface_list; list; list = list->next) {
1246 struct wifi_data *wifi = list->data;
1247 GSupplicantInterface *iface = wifi->interface;
1249 if (!g_supplicant_interface_has_p2p(iface))
1252 params = fill_in_peer_service_params(specification,
1253 specification_length, query,
1254 query_length, version);
1261 ret_f = g_supplicant_interface_p2p_add_service(iface,
1262 register_peer_service_cb, params, reg_data);
1263 if (ret_f == 0 || ret_f == -EINPROGRESS)
1267 ret = g_supplicant_interface_p2p_add_service(iface,
1268 register_peer_service_cb, params, NULL);
1269 if (ret != 0 && ret != -EINPROGRESS)
1270 free_peer_service_params(params);
1273 if (ret_f != 0 && ret_f != -EINPROGRESS)
1279 static int peer_unregister_wfd_service(void)
1281 GSupplicantP2PServiceParams *params;
1284 if (!wfd_service_registered)
1287 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1291 wfd_service_registered = false;
1293 g_supplicant_set_widi_ies(params, NULL, NULL);
1295 for (list = iface_list; list; list = list->next) {
1296 struct wifi_data *wifi = list->data;
1298 if (!g_supplicant_interface_has_p2p(wifi->interface))
1302 if (!wifi->servicing || wifi->servicing < 0) {
1303 g_supplicant_interface_p2p_listen(wifi->interface,
1305 wifi->servicing = 0;
1312 static int peer_unregister_service(const unsigned char *specification,
1313 int specification_length,
1314 const unsigned char *query,
1315 int query_length, int version)
1317 GSupplicantP2PServiceParams *params;
1322 if (specification && !version && !query &&
1323 is_service_wfd(specification, specification_length)) {
1324 ret = peer_unregister_wfd_service();
1325 if (ret != 0 && ret != -EINPROGRESS)
1330 for (list = iface_list; list; list = list->next) {
1331 struct wifi_data *wifi = list->data;
1332 GSupplicantInterface *iface = wifi->interface;
1335 goto stop_listening;
1337 if (!g_supplicant_interface_has_p2p(iface))
1340 params = fill_in_peer_service_params(specification,
1341 specification_length, query,
1342 query_length, version);
1348 ret = g_supplicant_interface_p2p_del_service(iface, params);
1349 if (ret != 0 && ret != -EINPROGRESS)
1350 free_peer_service_params(params);
1353 if (!wifi->servicing || wifi->servicing < 0) {
1354 g_supplicant_interface_p2p_listen(iface, 0, 0);
1355 wifi->servicing = 0;
1362 static struct connman_peer_driver peer_driver = {
1363 .connect = peer_connect,
1364 .disconnect = peer_disconnect,
1365 .register_service = peer_register_service,
1366 .unregister_service = peer_unregister_service,
1369 static void handle_tethering(struct wifi_data *wifi)
1371 if (!wifi->tethering)
1380 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1382 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1385 wifi->bridged = true;
1388 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1390 struct connman_device *device = user_data;
1391 struct wifi_data *wifi = connman_device_get_data(device);
1396 DBG("index %d flags %d change %d", wifi->index, flags, change);
1398 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1400 DBG("interface up");
1402 DBG("interface down");
1405 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1406 if (flags & IFF_LOWER_UP) {
1409 handle_tethering(wifi);
1414 wifi->flags = flags;
1417 static int wifi_probe(struct connman_device *device)
1419 struct wifi_data *wifi;
1421 DBG("device %p", device);
1423 wifi = g_try_new0(struct wifi_data, 1);
1427 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1428 wifi->ap_supported = WIFI_AP_UNKNOWN;
1429 wifi->tethering_param = NULL;
1431 connman_device_set_data(device, wifi);
1432 wifi->device = connman_device_ref(device);
1434 wifi->index = connman_device_get_index(device);
1437 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1438 wifi_newlink, device);
1439 if (is_p2p_connecting())
1440 add_pending_wifi_device(wifi);
1442 iface_list = g_list_append(iface_list, wifi);
1447 static void remove_networks(struct connman_device *device,
1448 struct wifi_data *wifi)
1452 for (list = wifi->networks; list; list = list->next) {
1453 struct connman_network *network = list->data;
1455 connman_device_remove_network(device, network);
1456 connman_network_unref(network);
1459 g_slist_free(wifi->networks);
1460 wifi->networks = NULL;
1463 static void remove_peers(struct wifi_data *wifi)
1467 for (list = wifi->peers; list; list = list->next) {
1468 struct connman_peer *peer = list->data;
1470 connman_peer_unregister(peer);
1471 connman_peer_unref(peer);
1474 g_slist_free(wifi->peers);
1478 static void reset_autoscan(struct connman_device *device)
1480 struct wifi_data *wifi = connman_device_get_data(device);
1481 struct autoscan_params *autoscan;
1485 if (!wifi || !wifi->autoscan)
1488 autoscan = wifi->autoscan;
1490 if (autoscan->timeout == 0 && autoscan->interval == 0)
1493 g_source_remove(autoscan->timeout);
1495 autoscan->timeout = 0;
1496 autoscan->interval = 0;
1498 connman_device_unref(device);
1501 static void stop_autoscan(struct connman_device *device)
1503 const struct wifi_data *wifi = connman_device_get_data(device);
1505 if (!wifi || !wifi->autoscan)
1508 reset_autoscan(device);
1510 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1513 static void check_p2p_technology(void)
1515 bool p2p_exists = false;
1518 for (list = iface_list; list; list = list->next) {
1519 struct wifi_data *w = list->data;
1522 g_supplicant_interface_has_p2p(w->interface))
1527 connman_technology_driver_unregister(&p2p_tech_driver);
1528 connman_peer_driver_unregister(&peer_driver);
1532 static void wifi_remove(struct connman_device *device)
1534 struct wifi_data *wifi = connman_device_get_data(device);
1536 DBG("device %p wifi %p", device, wifi);
1541 stop_autoscan(device);
1543 if (wifi->p2p_device)
1544 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1546 iface_list = g_list_remove(iface_list, wifi);
1548 check_p2p_technology();
1549 #if defined TIZEN_EXT_WIFI_MESH
1550 check_mesh_technology();
1553 remove_pending_wifi_device(wifi);
1555 if (wifi->p2p_find_timeout) {
1556 g_source_remove(wifi->p2p_find_timeout);
1557 connman_device_unref(wifi->device);
1560 if (wifi->p2p_connection_timeout)
1561 g_source_remove(wifi->p2p_connection_timeout);
1563 #if defined TIZEN_EXT
1564 if (wifi->automaxspeed_timeout != 0) {
1565 g_source_remove(wifi->automaxspeed_timeout);
1566 wifi->automaxspeed_timeout = 0;
1570 remove_networks(device, wifi);
1573 connman_device_set_powered(device, false);
1574 connman_device_set_data(device, NULL);
1575 connman_device_unref(wifi->device);
1576 connman_rtnl_remove_watch(wifi->watch);
1578 g_supplicant_interface_set_data(wifi->interface, NULL);
1580 g_supplicant_interface_cancel(wifi->interface);
1582 if (wifi->scan_params)
1583 g_supplicant_free_scan_params(wifi->scan_params);
1584 #if defined TIZEN_EXT
1585 if (wifi->hidden_scan_params) {
1586 while (wifi->hidden_scan_params->ssids) {
1587 struct scan_ssid *ssid;
1588 ssid = wifi->hidden_scan_params->ssids->data;
1589 wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
1591 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1595 g_free(wifi->autoscan);
1596 g_free(wifi->identifier);
1600 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1604 for (iter = list; iter; iter = g_slist_next(iter)) {
1605 struct scan_ssid *scan_ssid = iter->data;
1607 if (ssid_len == scan_ssid->ssid_len &&
1608 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1615 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1616 int freq, GSupplicantScanParams *scan_data,
1617 int driver_max_scan_ssids, char *ssid_name)
1620 struct scan_ssid *scan_ssid;
1622 if ((driver_max_scan_ssids == 0 ||
1623 driver_max_scan_ssids > scan_data->num_ssids) &&
1624 (hex_ssid || raw_ssid)) {
1626 unsigned int j = 0, hex;
1629 size_t hex_ssid_len = strlen(hex_ssid);
1631 ssid = g_try_malloc0(hex_ssid_len / 2);
1635 for (i = 0; i < hex_ssid_len; i += 2) {
1636 sscanf(hex_ssid + i, "%02x", &hex);
1645 * If we have already added hidden AP to the list,
1646 * then do not do it again. This might happen if you have
1647 * used or are using multiple wifi cards, so in that case
1648 * you might have multiple service files for same AP.
1650 if (is_duplicate(scan_data->ssids, ssid, j)) {
1656 scan_ssid = g_try_new(struct scan_ssid, 1);
1663 memcpy(scan_ssid->ssid, ssid, j);
1664 scan_ssid->ssid_len = j;
1665 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1668 scan_data->num_ssids++;
1670 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1671 scan_data->num_ssids);
1678 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1680 if (!scan_data->freqs) {
1681 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1682 if (!scan_data->freqs) {
1683 g_slist_free_full(scan_data->ssids, g_free);
1687 scan_data->num_freqs = 1;
1688 scan_data->freqs[0] = freq;
1690 bool duplicate = false;
1692 /* Don't add duplicate entries */
1693 for (i = 0; i < scan_data->num_freqs; i++) {
1694 if (scan_data->freqs[i] == freq) {
1701 scan_data->num_freqs++;
1702 scan_data->freqs = g_try_realloc(scan_data->freqs,
1703 sizeof(uint16_t) * scan_data->num_freqs);
1704 if (!scan_data->freqs) {
1705 g_slist_free_full(scan_data->ssids, g_free);
1708 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1715 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1717 struct connman_config_entry **entries;
1723 int num_ssids = 0, add_param_failed = 0;
1725 services = connman_storage_get_services();
1726 for (i = 0; services && services[i]; i++) {
1727 if (strncmp(services[i], "wifi_", 5) != 0)
1730 keyfile = connman_storage_load_service(services[i]);
1734 value = g_key_file_get_boolean(keyfile,
1735 services[i], "Hidden", NULL);
1737 g_key_file_free(keyfile);
1741 value = g_key_file_get_boolean(keyfile,
1742 services[i], "Favorite", NULL);
1744 g_key_file_free(keyfile);
1748 #if defined TIZEN_EXT
1749 value = g_key_file_get_boolean(keyfile,
1750 services[i], "AutoConnect", NULL);
1752 g_key_file_free(keyfile);
1757 ssid = g_key_file_get_string(keyfile,
1758 services[i], "SSID", NULL);
1760 name = g_key_file_get_string(keyfile, services[i], "Name",
1763 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1771 g_key_file_free(keyfile);
1775 * Check if there are any hidden AP that needs to be provisioned.
1777 entries = connman_config_get_entries("wifi");
1778 for (i = 0; entries && entries[i]; i++) {
1781 if (!entries[i]->hidden)
1784 if (!entries[i]->ssid) {
1785 ssid = entries[i]->name;
1788 ssid = entries[i]->ssid;
1789 len = entries[i]->ssid_len;
1795 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1802 connman_config_free_entries(entries);
1804 if (add_param_failed > 0)
1805 DBG("Unable to scan %d out of %d SSIDs",
1806 add_param_failed, num_ssids);
1808 g_strfreev(services);
1813 static int get_hidden_connections_params(struct wifi_data *wifi,
1814 GSupplicantScanParams *scan_params)
1816 int driver_max_ssids, i;
1817 GSupplicantScanParams *orig_params;
1820 * Scan hidden networks so that we can autoconnect to them.
1821 * We will assume 1 as a default number of ssid to scan.
1823 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1825 if (driver_max_ssids == 0)
1826 driver_max_ssids = 1;
1828 DBG("max ssids %d", driver_max_ssids);
1830 #if defined TIZEN_EXT
1831 if (!wifi->hidden_scan_params) {
1832 wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1833 if (!wifi->hidden_scan_params)
1836 if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
1837 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1838 wifi->hidden_scan_params = NULL;
1844 orig_params = wifi->hidden_scan_params;
1846 if (!wifi->scan_params) {
1847 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1848 if (!wifi->scan_params)
1851 if (get_hidden_connections(wifi->scan_params) == 0) {
1852 g_supplicant_free_scan_params(wifi->scan_params);
1853 wifi->scan_params = NULL;
1859 orig_params = wifi->scan_params;
1862 /* Let's transfer driver_max_ssids params */
1863 for (i = 0; i < driver_max_ssids; i++) {
1864 struct scan_ssid *ssid;
1866 #if defined TIZEN_EXT
1867 if (!wifi->hidden_scan_params->ssids)
1869 if (!wifi->scan_params->ssids)
1873 ssid = orig_params->ssids->data;
1874 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1875 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1879 scan_params->num_ssids = i;
1880 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1882 scan_params->freqs = g_memdup(orig_params->freqs,
1883 sizeof(uint16_t) * orig_params->num_freqs);
1884 if (!scan_params->freqs)
1887 scan_params->num_freqs = orig_params->num_freqs;
1892 orig_params->num_ssids -= scan_params->num_ssids;
1894 return scan_params->num_ssids;
1897 g_slist_free_full(scan_params->ssids, g_free);
1898 #if defined TIZEN_EXT
1899 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1900 wifi->hidden_scan_params = NULL;
1902 g_supplicant_free_scan_params(wifi->scan_params);
1903 wifi->scan_params = NULL;
1909 static int throw_wifi_scan(struct connman_device *device,
1910 GSupplicantInterfaceCallback callback)
1912 struct wifi_data *wifi = connman_device_get_data(device);
1918 DBG("device %p %p", device, wifi->interface);
1920 if (wifi->tethering)
1922 #if defined TIZEN_EXT
1923 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1925 if (connman_device_get_scanning(device))
1929 connman_device_ref(device);
1931 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1934 connman_device_set_scanning(device,
1935 CONNMAN_SERVICE_TYPE_WIFI, true);
1937 connman_device_unref(device);
1942 static void hidden_free(struct hidden_params *hidden)
1947 if (hidden->scan_params)
1948 g_supplicant_free_scan_params(hidden->scan_params);
1949 g_free(hidden->identity);
1950 g_free(hidden->passphrase);
1951 g_free(hidden->security);
1955 #if defined TIZEN_EXT
1956 static void service_state_changed(struct connman_service *service,
1957 enum connman_service_state state);
1959 static int network_connect(struct connman_network *network);
1961 static struct connman_notifier notifier = {
1963 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1964 .service_state_changed = service_state_changed,
1967 static void service_state_changed(struct connman_service *service,
1968 enum connman_service_state state)
1970 enum connman_service_type type;
1972 type = connman_service_get_type(service);
1973 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1976 DBG("service %p state %d", service, state);
1979 case CONNMAN_SERVICE_STATE_READY:
1980 case CONNMAN_SERVICE_STATE_ONLINE:
1981 case CONNMAN_SERVICE_STATE_FAILURE:
1982 connman_notifier_unregister(¬ifier);
1983 is_wifi_notifier_registered = FALSE;
1985 __connman_device_request_scan(type);
1993 static void scan_callback_hidden(int result,
1994 GSupplicantInterface *interface, void *user_data);
1997 static void scan_callback(int result, GSupplicantInterface *interface,
2000 struct connman_device *device = user_data;
2001 struct wifi_data *wifi = connman_device_get_data(device);
2004 DBG("result %d wifi %p", result, wifi);
2007 if (wifi->hidden && !wifi->postpone_hidden) {
2008 connman_network_clear_hidden(wifi->hidden->user_data);
2009 hidden_free(wifi->hidden);
2010 wifi->hidden = NULL;
2013 if (wifi->scan_params) {
2014 g_supplicant_free_scan_params(wifi->scan_params);
2015 wifi->scan_params = NULL;
2018 #if defined TIZEN_EXT
2019 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2020 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2021 wifi->hidden_scan_params = NULL;
2027 connman_device_reset_scanning(device);
2029 /* User is connecting to a hidden AP, let's wait for finished event */
2030 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2031 GSupplicantScanParams *scan_params;
2034 wifi->postpone_hidden = false;
2035 scan_params = wifi->hidden->scan_params;
2036 wifi->hidden->scan_params = NULL;
2038 reset_autoscan(device);
2040 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2041 scan_callback, device);
2045 /* On error, let's recall scan_callback, which will cleanup */
2046 return scan_callback(ret, interface, user_data);
2049 #if defined TIZEN_EXT
2050 if (wifi && wifi->allow_full_scan) {
2052 DBG("Trigger Full Channel Scan");
2053 wifi->allow_full_scan = FALSE;
2055 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2056 scan_callback_hidden, device);
2060 /* On error, let's recall scan_callback, which will cleanup */
2061 return scan_callback(ret, interface, user_data);
2065 scanning = connman_device_get_scanning(device);
2067 connman_device_set_scanning(device,
2068 CONNMAN_SERVICE_TYPE_WIFI, false);
2070 if (result != -ENOLINK)
2071 #if defined TIZEN_EXT
2074 start_autoscan(device);
2077 * If we are here then we were scanning; however, if we are
2078 * also mid-flight disabling the interface, then wifi_disable
2079 * has already cleared the device scanning state and
2080 * unreferenced the device, obviating the need to do it here.
2084 connman_device_unref(device);
2086 #if defined TIZEN_EXT
2087 if (wifi && wifi->scan_pending_network && result != -EIO) {
2088 network_connect(wifi->scan_pending_network);
2089 wifi->scan_pending_network = NULL;
2090 connman_network_set_connecting(wifi->network);
2093 if (is_wifi_notifier_registered != true &&
2094 wifi_first_scan == true && found_with_first_scan == true) {
2095 wifi_first_scan = false;
2096 found_with_first_scan = false;
2098 connman_notifier_register(¬ifier);
2099 is_wifi_notifier_registered = true;
2104 static void scan_callback_hidden(int result,
2105 GSupplicantInterface *interface, void *user_data)
2107 struct connman_device *device = user_data;
2108 struct wifi_data *wifi = connman_device_get_data(device);
2109 GSupplicantScanParams *scan_params;
2112 DBG("result %d wifi %p", result, wifi);
2117 /* User is trying to connect to a hidden AP */
2118 if (wifi->hidden && wifi->postpone_hidden)
2121 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2125 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2126 ret = g_supplicant_interface_scan(wifi->interface,
2128 #if defined TIZEN_EXT
2131 scan_callback_hidden,
2139 g_supplicant_free_scan_params(scan_params);
2142 scan_callback(result, interface, user_data);
2145 static gboolean autoscan_timeout(gpointer data)
2147 struct connman_device *device = data;
2148 struct wifi_data *wifi = connman_device_get_data(device);
2149 struct autoscan_params *autoscan;
2155 autoscan = wifi->autoscan;
2157 if (autoscan->interval <= 0) {
2158 interval = autoscan->base;
2161 interval = autoscan->interval * autoscan->base;
2163 #if defined TIZEN_EXT
2164 if (autoscan->interval >= autoscan->limit)
2166 if (interval > autoscan->limit)
2168 interval = autoscan->limit;
2170 throw_wifi_scan(wifi->device, scan_callback_hidden);
2173 DBG("interval %d", interval);
2175 autoscan->interval = interval;
2177 autoscan->timeout = g_timeout_add_seconds(interval,
2178 autoscan_timeout, device);
2183 static void start_autoscan(struct connman_device *device)
2185 struct wifi_data *wifi = connman_device_get_data(device);
2186 struct autoscan_params *autoscan;
2193 if (wifi->p2p_device)
2196 if (wifi->connected)
2199 autoscan = wifi->autoscan;
2203 if (autoscan->timeout > 0 || autoscan->interval > 0)
2206 connman_device_ref(device);
2208 autoscan_timeout(device);
2211 static struct autoscan_params *parse_autoscan_params(const char *params)
2213 struct autoscan_params *autoscan;
2218 DBG("Emulating autoscan");
2220 list_params = g_strsplit(params, ":", 0);
2221 if (list_params == 0)
2224 if (g_strv_length(list_params) < 3) {
2225 g_strfreev(list_params);
2229 base = atoi(list_params[1]);
2230 limit = atoi(list_params[2]);
2232 g_strfreev(list_params);
2234 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2236 DBG("Could not allocate memory for autoscan");
2240 DBG("base %d - limit %d", base, limit);
2241 autoscan->base = base;
2242 autoscan->limit = limit;
2247 static void setup_autoscan(struct wifi_data *wifi)
2249 if (!wifi->autoscan)
2250 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2252 start_autoscan(wifi->device);
2255 static void finalize_interface_creation(struct wifi_data *wifi)
2257 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2259 if (!wifi->device) {
2260 connman_error("WiFi device not set");
2264 connman_device_set_powered(wifi->device, true);
2266 if (!connman_setting_get_bool("BackgroundScanning"))
2269 if (wifi->p2p_device)
2272 setup_autoscan(wifi);
2275 static void interface_create_callback(int result,
2276 GSupplicantInterface *interface,
2279 struct wifi_data *wifi = user_data;
2281 DBG("result %d ifname %s, wifi %p", result,
2282 g_supplicant_interface_get_ifname(interface),
2285 if (result < 0 || !wifi)
2288 wifi->interface = interface;
2289 g_supplicant_interface_set_data(interface, wifi);
2291 if (g_supplicant_interface_get_ready(interface)) {
2292 wifi->interface_ready = true;
2293 finalize_interface_creation(wifi);
2297 static int wifi_enable(struct connman_device *device)
2299 struct wifi_data *wifi = connman_device_get_data(device);
2302 const char *driver = connman_option_get_string("wifi");
2305 DBG("device %p %p", device, wifi);
2307 index = connman_device_get_index(device);
2308 if (!wifi || index < 0)
2311 if (is_p2p_connecting())
2312 return -EINPROGRESS;
2314 interface = connman_inet_ifname(index);
2315 ret = g_supplicant_interface_create(interface, driver, NULL,
2316 interface_create_callback,
2323 return -EINPROGRESS;
2326 static int wifi_disable(struct connman_device *device)
2328 struct wifi_data *wifi = connman_device_get_data(device);
2331 DBG("device %p wifi %p", device, wifi);
2336 wifi->connected = false;
2337 wifi->disconnecting = false;
2339 if (wifi->pending_network)
2340 wifi->pending_network = NULL;
2342 stop_autoscan(device);
2344 if (wifi->p2p_find_timeout) {
2345 g_source_remove(wifi->p2p_find_timeout);
2346 wifi->p2p_find_timeout = 0;
2347 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2348 connman_device_unref(wifi->device);
2351 #if defined TIZEN_EXT
2352 if (wifi->automaxspeed_timeout != 0) {
2353 g_source_remove(wifi->automaxspeed_timeout);
2354 wifi->automaxspeed_timeout = 0;
2358 /* In case of a user scan, device is still referenced */
2359 if (connman_device_get_scanning(device)) {
2360 connman_device_set_scanning(device,
2361 CONNMAN_SERVICE_TYPE_WIFI, false);
2362 connman_device_unref(wifi->device);
2365 remove_networks(device, wifi);
2368 #if defined TIZEN_EXT
2369 wifi->scan_pending_network = NULL;
2371 if (is_wifi_notifier_registered == true) {
2372 connman_notifier_unregister(¬ifier);
2373 is_wifi_notifier_registered = false;
2377 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2381 return -EINPROGRESS;
2384 struct last_connected {
2390 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
2392 GTimeVal *aval = (GTimeVal *)a;
2393 GTimeVal *bval = (GTimeVal *)b;
2395 /* Note that the sort order is descending */
2396 if (aval->tv_sec < bval->tv_sec)
2399 if (aval->tv_sec > bval->tv_sec)
2405 static void free_entry(gpointer data)
2407 struct last_connected *entry = data;
2409 g_free(entry->ssid);
2413 static int get_latest_connections(int max_ssids,
2414 GSupplicantScanParams *scan_data)
2416 GSequenceIter *iter;
2417 GSequence *latest_list;
2418 struct last_connected *entry;
2427 latest_list = g_sequence_new(free_entry);
2431 services = connman_storage_get_services();
2432 for (i = 0; services && services[i]; i++) {
2433 if (strncmp(services[i], "wifi_", 5) != 0)
2436 keyfile = connman_storage_load_service(services[i]);
2440 str = g_key_file_get_string(keyfile,
2441 services[i], "Favorite", NULL);
2442 if (!str || g_strcmp0(str, "true")) {
2444 g_key_file_free(keyfile);
2449 str = g_key_file_get_string(keyfile,
2450 services[i], "AutoConnect", NULL);
2451 if (!str || g_strcmp0(str, "true")) {
2453 g_key_file_free(keyfile);
2458 str = g_key_file_get_string(keyfile,
2459 services[i], "Modified", NULL);
2461 g_key_file_free(keyfile);
2464 g_time_val_from_iso8601(str, &modified);
2467 ssid = g_key_file_get_string(keyfile,
2468 services[i], "SSID", NULL);
2470 freq = g_key_file_get_integer(keyfile, services[i],
2473 entry = g_try_new(struct last_connected, 1);
2475 g_sequence_free(latest_list);
2476 g_key_file_free(keyfile);
2482 entry->modified = modified;
2485 g_sequence_insert_sorted(latest_list, entry,
2491 g_key_file_free(keyfile);
2494 g_strfreev(services);
2496 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2498 iter = g_sequence_get_begin_iter(latest_list);
2500 for (i = 0; i < num_ssids; i++) {
2501 entry = g_sequence_get(iter);
2503 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2504 entry->modified.tv_sec);
2506 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2507 max_ssids, entry->ssid);
2509 iter = g_sequence_iter_next(iter);
2512 g_sequence_free(latest_list);
2516 static int wifi_scan_simple(struct connman_device *device)
2518 reset_autoscan(device);
2520 return throw_wifi_scan(device, scan_callback_hidden);
2523 static gboolean p2p_find_stop(gpointer data)
2525 struct connman_device *device = data;
2526 struct wifi_data *wifi = connman_device_get_data(device);
2531 wifi->p2p_find_timeout = 0;
2533 g_supplicant_interface_p2p_stop_find(wifi->interface);
2536 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2538 connman_device_unref(device);
2539 reset_autoscan(device);
2544 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2547 struct connman_device *device = user_data;
2548 struct wifi_data *wifi = connman_device_get_data(device);
2550 DBG("result %d wifi %p", result, wifi);
2555 if (wifi->p2p_find_timeout) {
2556 g_source_remove(wifi->p2p_find_timeout);
2557 wifi->p2p_find_timeout = 0;
2563 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2564 p2p_find_stop, device);
2565 if (!wifi->p2p_find_timeout)
2570 p2p_find_stop(device);
2573 static int p2p_find(struct connman_device *device)
2575 struct wifi_data *wifi;
2580 if (!p2p_technology)
2583 wifi = connman_device_get_data(device);
2585 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2588 reset_autoscan(device);
2589 connman_device_ref(device);
2591 ret = g_supplicant_interface_p2p_find(wifi->interface,
2592 p2p_find_callback, device);
2594 connman_device_unref(device);
2595 start_autoscan(device);
2597 connman_device_set_scanning(device,
2598 CONNMAN_SERVICE_TYPE_P2P, true);
2604 #if defined TIZEN_EXT
2605 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2608 struct connman_device *device = user_data;
2609 struct wifi_data *wifi = connman_device_get_data(device);
2612 DBG("result %d wifi %p", result, wifi);
2614 if (wifi && wifi->scan_params) {
2615 g_supplicant_free_scan_params(wifi->scan_params);
2616 wifi->scan_params = NULL;
2619 scanning = connman_device_get_scanning(device);
2621 connman_device_set_scanning(device,
2622 CONNMAN_SERVICE_TYPE_WIFI, false);
2623 connman_device_unref(device);
2627 static int wifi_specific_scan(enum connman_service_type type,
2628 struct connman_device *device, int scan_type,
2629 GSList *specific_scan_list, void *user_data)
2631 GSList *list = NULL;
2633 struct wifi_data *wifi = connman_device_get_data(device);
2634 GSupplicantScanParams *scan_params = NULL;
2635 struct scan_ssid *scan_ssid = NULL;
2644 if (wifi->p2p_device)
2647 if (type == CONNMAN_SERVICE_TYPE_P2P)
2648 return p2p_find(device);
2650 if (wifi->tethering)
2653 scanning = connman_device_get_scanning(device);
2657 DBG("scan_type: %d", scan_type);
2658 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2659 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2661 DBG("Failed to allocate memory.");
2665 for (list = specific_scan_list; list; list = list->next) {
2666 ssid = (char *)list->data;
2667 int ssid_len = strlen(ssid);
2669 scan_ssid = g_try_new0(struct scan_ssid, 1);
2671 DBG("Failed to allocate memory.");
2672 g_supplicant_free_scan_params(scan_params);
2676 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2677 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2678 scan_ssid->ssid_len = ssid_len;
2679 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2682 scan_params->num_ssids = count;
2684 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2686 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2688 DBG("Failed to allocate memory.");
2692 guint num_freqs = g_slist_length(specific_scan_list);
2693 DBG("num_freqs: %d", num_freqs);
2695 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2696 if (!scan_params->freqs) {
2697 DBG("Failed to allocate memory.");
2698 g_free(scan_params);
2703 for (list = specific_scan_list; list; list = list->next) {
2704 freq = (int)list->data;
2706 scan_params->freqs[count] = freq;
2707 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2710 scan_params->num_freqs = count;
2712 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2713 int freq_count, ap_count;
2714 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2716 DBG("Failed to allocate memory.");
2720 guint size = g_slist_length(specific_scan_list);
2722 scan_params->freqs = g_try_new0(uint16_t, size/2);
2723 if (!scan_params->freqs) {
2724 DBG("Failed to allocate memory.");
2725 g_free(scan_params);
2729 ap_count = freq_count = 0;
2730 for (list = specific_scan_list; list; list = list->next) {
2731 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2732 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2733 int ssid_len = strlen(ssid);
2735 scan_ssid = g_try_new0(struct scan_ssid, 1);
2737 DBG("Failed to allocate memory.");
2738 g_supplicant_free_scan_params(scan_params);
2742 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2743 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2744 scan_ssid->ssid_len = ssid_len;
2745 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2749 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2750 scan_params->freqs[freq_count] = freq;
2751 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2755 scan_params->num_ssids = ap_count;
2756 scan_params->num_freqs = freq_count;
2758 DBG("Invalid scan");
2762 reset_autoscan(device);
2763 connman_device_ref(device);
2765 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2766 specific_scan_callback, device);
2769 connman_device_set_scanning(device,
2770 CONNMAN_SERVICE_TYPE_WIFI, true);
2772 g_supplicant_free_scan_params(scan_params);
2773 connman_device_unref(device);
2780 #if defined TIZEN_EXT_WIFI_MESH
2781 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2784 struct connman_device *device = user_data;
2785 struct wifi_data *wifi = connman_device_get_data(device);
2788 DBG("result %d wifi %p", result, wifi);
2790 scanning = connman_device_get_scanning(device);
2792 connman_device_set_scanning(device,
2793 CONNMAN_SERVICE_TYPE_MESH, false);
2796 connman_device_unref(device);
2799 static int mesh_scan(struct connman_device *device)
2801 struct wifi_data *wifi;
2802 struct wifi_mesh_info *mesh_info;
2807 wifi = connman_device_get_data(device);
2809 if (!wifi->mesh_interface)
2812 mesh_info = wifi->mesh_info;
2813 reset_autoscan(device);
2814 connman_device_ref(device);
2816 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2817 mesh_scan_callback, device);
2819 connman_device_unref(device);
2821 connman_device_set_scanning(device,
2822 CONNMAN_SERVICE_TYPE_MESH, true);
2827 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2830 struct connman_device *device = user_data;
2831 struct wifi_data *wifi = connman_device_get_data(device);
2833 DBG("result %d wifi %p", result, wifi);
2835 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2838 static int mesh_abort_scan(enum connman_service_type type,
2839 struct connman_device *device)
2841 struct wifi_data *wifi = connman_device_get_data(device);
2842 struct wifi_mesh_info *mesh_info;
2846 if (!wifi || !wifi->mesh_interface)
2849 if (type != CONNMAN_SERVICE_TYPE_MESH)
2852 mesh_info = wifi->mesh_info;
2854 scanning = connman_device_get_scanning(device);
2858 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2859 abort_scan_callback, device);
2864 static int mesh_specific_scan(enum connman_service_type type,
2865 struct connman_device *device, const char *ssid,
2866 unsigned int freq, void *user_data)
2868 struct wifi_data *wifi = connman_device_get_data(device);
2869 GSupplicantScanParams *scan_params = NULL;
2870 struct wifi_mesh_info *mesh_info;
2871 struct scan_ssid *scan_ssid;
2875 if (!wifi || !wifi->mesh_interface)
2878 if (type != CONNMAN_SERVICE_TYPE_MESH)
2881 if (wifi->p2p_device)
2884 mesh_info = wifi->mesh_info;
2886 scanning = connman_device_get_scanning(device);
2890 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2894 scan_ssid = g_try_new(struct scan_ssid, 1);
2896 g_free(scan_params);
2900 scan_ssid->ssid_len = strlen(ssid);
2901 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2902 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2903 scan_params->num_ssids = 1;
2905 scan_params->freqs = g_try_new(uint16_t, 1);
2906 if (!scan_params->freqs) {
2907 g_slist_free_full(scan_params->ssids, g_free);
2908 g_free(scan_params);
2912 scan_params->freqs[0] = freq;
2913 scan_params->num_freqs = 1;
2915 reset_autoscan(device);
2916 connman_device_ref(device);
2918 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2919 mesh_scan_callback, device);
2922 connman_device_set_scanning(device,
2923 CONNMAN_SERVICE_TYPE_MESH, true);
2925 g_supplicant_free_scan_params(scan_params);
2926 connman_device_unref(device);
2934 * Note that the hidden scan is only used when connecting to this specific
2935 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2937 static int wifi_scan(enum connman_service_type type,
2938 struct connman_device *device,
2939 const char *ssid, unsigned int ssid_len,
2940 const char *identity, const char* passphrase,
2941 const char *security, void *user_data)
2943 struct wifi_data *wifi = connman_device_get_data(device);
2944 GSupplicantScanParams *scan_params = NULL;
2945 struct scan_ssid *scan_ssid;
2946 struct hidden_params *hidden;
2948 int driver_max_ssids = 0;
2955 if (wifi->p2p_device)
2958 if (wifi->tethering)
2961 if (type == CONNMAN_SERVICE_TYPE_P2P)
2962 return p2p_find(device);
2964 #if defined TIZEN_EXT_WIFI_MESH
2965 if (type == CONNMAN_SERVICE_TYPE_MESH)
2966 return mesh_scan(device);
2969 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2971 scanning = connman_device_get_scanning(device);
2973 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2977 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2979 DBG("max ssids %d", driver_max_ssids);
2980 if (driver_max_ssids == 0)
2981 return wifi_scan_simple(device);
2985 if (scanning && wifi->hidden && wifi->postpone_hidden)
2991 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2996 scan_ssid = g_try_new(struct scan_ssid, 1);
2998 g_free(scan_params);
3002 memcpy(scan_ssid->ssid, ssid, ssid_len);
3003 scan_ssid->ssid_len = ssid_len;
3004 scan_params->ssids = g_slist_prepend(scan_params->ssids,
3006 scan_params->num_ssids = 1;
3008 hidden = g_try_new0(struct hidden_params, 1);
3010 g_supplicant_free_scan_params(scan_params);
3015 hidden_free(wifi->hidden);
3016 wifi->hidden = NULL;
3019 memcpy(hidden->ssid, ssid, ssid_len);
3020 hidden->ssid_len = ssid_len;
3021 hidden->identity = g_strdup(identity);
3022 hidden->passphrase = g_strdup(passphrase);
3023 hidden->security = g_strdup(security);
3024 hidden->user_data = user_data;
3025 wifi->hidden = hidden;
3028 /* Let's keep this active scan for later,
3029 * when current scan will be over. */
3030 wifi->postpone_hidden = TRUE;
3031 hidden->scan_params = scan_params;
3035 } else if (wifi->connected) {
3036 g_supplicant_free_scan_params(scan_params);
3037 return wifi_scan_simple(device);
3039 ret = get_latest_connections(driver_max_ssids, scan_params);
3041 g_supplicant_free_scan_params(scan_params);
3042 return wifi_scan_simple(device);
3046 connman_device_ref(device);
3048 reset_autoscan(device);
3050 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3051 scan_callback, device);
3054 connman_device_set_scanning(device,
3055 CONNMAN_SERVICE_TYPE_WIFI, true);
3056 #if defined TIZEN_EXT
3057 /*To allow the Full Scan after ssid based scan, set the flag here
3058 It is required because Tizen does not use the ConnMan specific
3059 backgroung Scan feature.Tizen has added the BG Scan feature in
3060 net-config. To sync with up ConnMan, we need to issue the Full Scan
3061 after SSID specific scan.*/
3062 wifi->allow_full_scan = TRUE;
3065 g_supplicant_free_scan_params(scan_params);
3066 connman_device_unref(device);
3069 hidden_free(wifi->hidden);
3070 wifi->hidden = NULL;
3077 static void wifi_regdom_callback(int result,
3081 struct connman_device *device = user_data;
3083 connman_device_regdom_notify(device, result, alpha2);
3085 connman_device_unref(device);
3088 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3090 struct wifi_data *wifi = connman_device_get_data(device);
3096 connman_device_ref(device);
3098 ret = g_supplicant_interface_set_country(wifi->interface,
3099 wifi_regdom_callback,
3102 connman_device_unref(device);
3107 static struct connman_device_driver wifi_ng_driver = {
3109 .type = CONNMAN_DEVICE_TYPE_WIFI,
3110 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3111 .probe = wifi_probe,
3112 .remove = wifi_remove,
3113 .enable = wifi_enable,
3114 .disable = wifi_disable,
3116 .set_regdom = wifi_set_regdom,
3117 #if defined TIZEN_EXT
3118 .specific_scan = wifi_specific_scan,
3120 #if defined TIZEN_EXT_WIFI_MESH
3121 .abort_scan = mesh_abort_scan,
3122 .mesh_specific_scan = mesh_specific_scan,
3126 static void system_ready(void)
3130 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3131 connman_error("Failed to register WiFi driver");
3134 static void system_killed(void)
3138 connman_device_driver_unregister(&wifi_ng_driver);
3141 static int network_probe(struct connman_network *network)
3143 DBG("network %p", network);
3148 static void network_remove(struct connman_network *network)
3150 struct connman_device *device = connman_network_get_device(network);
3151 struct wifi_data *wifi;
3153 DBG("network %p", network);
3155 wifi = connman_device_get_data(device);
3159 if (wifi->network != network)
3162 wifi->network = NULL;
3164 #if defined TIZEN_EXT
3165 wifi->disconnecting = false;
3167 if (wifi->pending_network == network)
3168 wifi->pending_network = NULL;
3170 if (wifi->scan_pending_network == network)
3171 wifi->scan_pending_network = NULL;
3175 static void connect_callback(int result, GSupplicantInterface *interface,
3178 #if defined TIZEN_EXT
3180 struct wifi_data *wifi;
3182 struct connman_network *network = user_data;
3184 DBG("network %p result %d", network, result);
3186 #if defined TIZEN_EXT
3187 set_connman_bssid(RESET_BSSID, NULL);
3189 for (list = iface_list; list; list = list->next) {
3192 if (wifi && wifi->network == network)
3196 /* wifi_data may be invalid because wifi is already disabled */
3201 if (result == -ENOKEY) {
3202 connman_network_set_error(network,
3203 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3204 } else if (result < 0) {
3205 connman_network_set_error(network,
3206 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3209 connman_network_unref(network);
3212 static GSupplicantSecurity network_security(const char *security)
3214 if (g_str_equal(security, "none"))
3215 return G_SUPPLICANT_SECURITY_NONE;
3216 else if (g_str_equal(security, "wep"))
3217 return G_SUPPLICANT_SECURITY_WEP;
3218 else if (g_str_equal(security, "psk"))
3219 return G_SUPPLICANT_SECURITY_PSK;
3220 else if (g_str_equal(security, "wpa"))
3221 return G_SUPPLICANT_SECURITY_PSK;
3222 else if (g_str_equal(security, "rsn"))
3223 return G_SUPPLICANT_SECURITY_PSK;
3224 else if (g_str_equal(security, "ieee8021x"))
3225 return G_SUPPLICANT_SECURITY_IEEE8021X;
3226 #if defined TIZEN_EXT
3227 else if (g_str_equal(security, "ft_psk") == TRUE)
3228 return G_SUPPLICANT_SECURITY_FT_PSK;
3229 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3230 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3231 else if (g_str_equal(security, "sae"))
3232 return G_SUPPLICANT_SECURITY_SAE;
3233 else if (g_str_equal(security, "owe"))
3234 return G_SUPPLICANT_SECURITY_OWE;
3237 return G_SUPPLICANT_SECURITY_UNKNOWN;
3240 #if defined TIZEN_EXT
3241 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3243 if (security == NULL)
3244 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3246 if (g_str_equal(security, "FT") == TRUE)
3247 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3248 else if (g_str_equal(security, "CCKM") == TRUE)
3249 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3251 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3255 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3257 const char *security;
3258 #if defined TIZEN_EXT
3259 const void *ssid_data;
3262 memset(ssid, 0, sizeof(*ssid));
3263 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3264 #if defined TIZEN_EXT
3265 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3267 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3272 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3274 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3277 ssid->scan_ssid = 1;
3278 security = connman_network_get_string(network, "WiFi.Security");
3279 ssid->security = network_security(security);
3280 #if defined TIZEN_EXT
3281 ssid->ieee80211w = 1;
3283 ssid->passphrase = connman_network_get_string(network,
3285 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3288 * If our private key password is unset,
3289 * we use the supplied passphrase. That is needed
3290 * for PEAP where 2 passphrases (identity and client
3291 * cert may have to be provided.
3293 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3294 connman_network_set_string(network,
3295 "WiFi.PrivateKeyPassphrase",
3297 /* We must have an identity for both PEAP and TLS */
3298 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3300 /* Use agent provided identity as a fallback */
3301 if (!ssid->identity || strlen(ssid->identity) == 0)
3302 ssid->identity = connman_network_get_string(network,
3303 "WiFi.AgentIdentity");
3305 ssid->anonymous_identity = connman_network_get_string(network,
3306 "WiFi.AnonymousIdentity");
3307 ssid->ca_cert_path = connman_network_get_string(network,
3309 ssid->subject_match = connman_network_get_string(network,
3310 "WiFi.SubjectMatch");
3311 ssid->altsubject_match = connman_network_get_string(network,
3312 "WiFi.AltSubjectMatch");
3313 ssid->domain_suffix_match = connman_network_get_string(network,
3314 "WiFi.DomainSuffixMatch");
3315 ssid->domain_match = connman_network_get_string(network,
3316 "WiFi.DomainMatch");
3317 ssid->client_cert_path = connman_network_get_string(network,
3318 "WiFi.ClientCertFile");
3319 ssid->private_key_path = connman_network_get_string(network,
3320 "WiFi.PrivateKeyFile");
3321 ssid->private_key_passphrase = connman_network_get_string(network,
3322 "WiFi.PrivateKeyPassphrase");
3323 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3325 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3326 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3328 #if defined TIZEN_EXT
3329 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3330 ssid->bssid_for_connect_len = 6;
3331 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3332 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3333 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3334 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3335 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3337 ssid->freq = connman_network_get_frequency(network);
3340 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3341 if (bssid_list && g_slist_length(bssid_list) > 1) {
3343 /* If there are more than one bssid,
3344 * the user-specified bssid is tried only once at the beginning.
3345 * After that, the bssids in the list are tried in order.
3347 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3348 set_connman_bssid(RESET_BSSID, NULL);
3353 char buff[MAC_ADDRESS_LENGTH];
3354 for (list = bssid_list; list; list = list->next) {
3355 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3357 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3358 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3359 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3360 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3362 gchar *curr_bssid = g_strdup((const gchar *)buff);
3364 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3365 DBG("bssid match, try next bssid");
3369 g_hash_table_add(failed_bssids, curr_bssid);
3371 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3372 ssid->bssid = buff_bssid;
3373 ssid->freq = (unsigned int)bssids->frequency;
3379 ssid->bssid = connman_network_get_bssid(network);
3380 g_hash_table_remove_all(failed_bssids);
3383 ssid->bssid = connman_network_get_bssid(network);
3386 ssid->eap_keymgmt = network_eap_keymgmt(
3387 connman_network_get_string(network, "WiFi.KeymgmtType"));
3388 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3390 if(g_strcmp0(ssid->eap, "fast") == 0)
3391 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3394 if (connman_setting_get_bool("BackgroundScanning"))
3395 ssid->bgscan = BGSCAN_DEFAULT;
3398 static int network_connect(struct connman_network *network)
3400 struct connman_device *device = connman_network_get_device(network);
3401 struct wifi_data *wifi;
3402 GSupplicantInterface *interface;
3403 GSupplicantSSID *ssid;
3405 DBG("network %p", network);
3410 wifi = connman_device_get_data(device);
3414 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3418 interface = wifi->interface;
3420 ssid_init(ssid, network);
3422 if (wifi->disconnecting) {
3423 wifi->pending_network = network;
3424 #if defined TIZEN_EXT
3429 wifi->network = connman_network_ref(network);
3431 #if defined TIZEN_EXT
3432 wifi->scan_pending_network = NULL;
3435 return g_supplicant_interface_connect(interface, ssid,
3436 connect_callback, network);
3439 return -EINPROGRESS;
3442 static void disconnect_callback(int result, GSupplicantInterface *interface,
3445 #if defined TIZEN_EXT
3447 struct wifi_data *wifi;
3448 struct connman_network *network = user_data;
3450 DBG("network %p result %d", network, result);
3452 for (list = iface_list; list; list = list->next) {
3455 if (wifi->network == NULL && wifi->disconnecting == true)
3456 wifi->disconnecting = false;
3458 if (wifi->network == network)
3462 /* wifi_data may be invalid because wifi is already disabled */
3467 struct wifi_data *wifi = user_data;
3470 DBG("result %d supplicant interface %p wifi %p",
3471 result, interface, wifi);
3473 if (result == -ECONNABORTED) {
3474 DBG("wifi interface no longer available");
3478 if (wifi->network) {
3479 connman_network_set_connected(wifi->network, false);
3480 wifi->network = NULL;
3483 wifi->disconnecting = false;
3484 wifi->connected = false;
3486 if (wifi->pending_network) {
3487 network_connect(wifi->pending_network);
3488 wifi->pending_network = NULL;
3491 start_autoscan(wifi->device);
3494 static int network_disconnect(struct connman_network *network)
3496 struct connman_device *device = connman_network_get_device(network);
3497 struct wifi_data *wifi;
3499 #if defined TIZEN_EXT
3500 struct connman_service *service;
3503 DBG("network %p", network);
3505 wifi = connman_device_get_data(device);
3506 if (!wifi || !wifi->interface)
3509 #if defined TIZEN_EXT
3510 if (connman_network_get_associating(network) == true) {
3511 connman_network_clear_associating(network);
3512 connman_network_set_bool(network, "WiFi.UseWPS", false);
3514 service = connman_service_lookup_from_network(network);
3516 if (service != NULL &&
3517 (__connman_service_is_connected_state(service,
3518 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3519 __connman_service_is_connected_state(service,
3520 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3521 (connman_service_get_favorite(service) == false))
3522 __connman_service_set_passphrase(service, NULL);
3525 if (wifi->pending_network == network)
3526 wifi->pending_network = NULL;
3528 if (wifi->scan_pending_network == network)
3529 wifi->scan_pending_network = NULL;
3532 connman_network_set_associating(network, false);
3534 if (wifi->disconnecting)
3537 wifi->disconnecting = true;
3539 #if defined TIZEN_EXT
3540 err = g_supplicant_interface_disconnect(wifi->interface,
3541 disconnect_callback, network);
3543 err = g_supplicant_interface_disconnect(wifi->interface,
3544 disconnect_callback, wifi);
3548 wifi->disconnecting = false;
3553 #if defined TIZEN_EXT
3554 static void set_connection_mode(struct connman_network *network,
3557 ieee80211_modes_e phy_mode;
3558 connection_mode_e conn_mode;
3560 phy_mode = connman_network_get_phy_mode(network);
3562 case IEEE80211_MODE_B:
3563 if (linkspeed > 0 && linkspeed <= 11)
3564 conn_mode = CONNECTION_MODE_IEEE80211B;
3566 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3569 case IEEE80211_MODE_BG:
3570 if (linkspeed > 0 && linkspeed <= 11)
3571 conn_mode = CONNECTION_MODE_IEEE80211B;
3572 else if (linkspeed > 11 && linkspeed <= 54)
3573 conn_mode = CONNECTION_MODE_IEEE80211G;
3575 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3578 case IEEE80211_MODE_BGN:
3579 if (linkspeed > 0 && linkspeed <= 11)
3580 conn_mode = CONNECTION_MODE_IEEE80211B;
3581 else if (linkspeed > 11 && linkspeed <= 54)
3582 conn_mode = CONNECTION_MODE_IEEE80211G;
3583 else if (linkspeed > 54 && linkspeed <= 450)
3584 conn_mode = CONNECTION_MODE_IEEE80211N;
3586 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3589 case IEEE80211_MODE_A:
3590 if (linkspeed > 0 && linkspeed <= 54)
3591 conn_mode = CONNECTION_MODE_IEEE80211A;
3593 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3596 case IEEE80211_MODE_AN:
3597 if (linkspeed > 0 && linkspeed <= 54)
3598 conn_mode = CONNECTION_MODE_IEEE80211A;
3599 else if (linkspeed > 54 && linkspeed <= 450)
3600 conn_mode = CONNECTION_MODE_IEEE80211N;
3602 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3605 case IEEE80211_MODE_ANAC:
3606 if (linkspeed > 0 && linkspeed <= 54)
3607 conn_mode = CONNECTION_MODE_IEEE80211A;
3608 else if (linkspeed > 54 && linkspeed <= 450)
3609 conn_mode = CONNECTION_MODE_IEEE80211N;
3610 else if (linkspeed > 450 && linkspeed <= 1300)
3611 conn_mode = CONNECTION_MODE_IEEE80211AC;
3613 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3617 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3621 DBG("connection mode(%d)", conn_mode);
3622 connman_network_set_connection_mode(network, conn_mode);
3625 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3627 struct connman_network *network = user_data;
3630 DBG("Failed to get maxspeed from signalpoll !");
3634 DBG("maxspeed = %d", maxspeed);
3636 connman_network_set_maxspeed(network, maxspeed);
3637 set_connection_mode(network, maxspeed);
3641 static int network_signalpoll(struct wifi_data *wifi)
3643 GSupplicantInterface *interface;
3644 struct connman_network *network;
3646 if (!wifi || !wifi->network)
3649 interface = wifi->interface;
3650 network = wifi->network;
3652 DBG("network %p", network);
3654 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3657 static gboolean autosignalpoll_timeout(gpointer data)
3659 struct wifi_data *wifi = data;
3661 if (!wifi || !wifi->automaxspeed_timeout) {
3662 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3666 int ret = network_signalpoll(wifi);
3668 DBG("Fail to get max speed !!");
3669 wifi->automaxspeed_timeout = 0;
3677 static struct connman_network_driver network_driver = {
3679 .type = CONNMAN_NETWORK_TYPE_WIFI,
3680 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3681 .probe = network_probe,
3682 .remove = network_remove,
3683 .connect = network_connect,
3684 .disconnect = network_disconnect,
3687 static void interface_added(GSupplicantInterface *interface)
3689 const char *ifname = g_supplicant_interface_get_ifname(interface);
3690 const char *driver = g_supplicant_interface_get_driver(interface);
3691 #if defined TIZEN_EXT
3692 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3695 struct wifi_data *wifi;
3697 wifi = g_supplicant_interface_get_data(interface);
3699 wifi = get_pending_wifi_data(ifname);
3703 wifi->interface = interface;
3704 g_supplicant_interface_set_data(interface, wifi);
3705 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3706 wifi->p2p_device = true;
3709 DBG("ifname %s driver %s wifi %p tethering %d",
3710 ifname, driver, wifi, wifi->tethering);
3712 if (!wifi->device) {
3713 connman_error("WiFi device not set");
3717 connman_device_set_powered(wifi->device, true);
3718 #if defined TIZEN_EXT
3719 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3720 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3721 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3722 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3726 static bool is_idle(struct wifi_data *wifi)
3728 DBG("state %d", wifi->state);
3730 switch (wifi->state) {
3731 case G_SUPPLICANT_STATE_UNKNOWN:
3732 case G_SUPPLICANT_STATE_DISABLED:
3733 case G_SUPPLICANT_STATE_DISCONNECTED:
3734 case G_SUPPLICANT_STATE_INACTIVE:
3735 case G_SUPPLICANT_STATE_SCANNING:
3738 case G_SUPPLICANT_STATE_AUTHENTICATING:
3739 case G_SUPPLICANT_STATE_ASSOCIATING:
3740 case G_SUPPLICANT_STATE_ASSOCIATED:
3741 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3742 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3743 case G_SUPPLICANT_STATE_COMPLETED:
3750 static bool is_idle_wps(GSupplicantInterface *interface,
3751 struct wifi_data *wifi)
3753 /* First, let's check if WPS processing did not went wrong */
3754 if (g_supplicant_interface_get_wps_state(interface) ==
3755 G_SUPPLICANT_WPS_STATE_FAIL)
3758 /* Unlike normal connection, being associated while processing wps
3759 * actually means that we are idling. */
3760 switch (wifi->state) {
3761 case G_SUPPLICANT_STATE_UNKNOWN:
3762 case G_SUPPLICANT_STATE_DISABLED:
3763 case G_SUPPLICANT_STATE_DISCONNECTED:
3764 case G_SUPPLICANT_STATE_INACTIVE:
3765 case G_SUPPLICANT_STATE_SCANNING:
3766 case G_SUPPLICANT_STATE_ASSOCIATED:
3768 case G_SUPPLICANT_STATE_AUTHENTICATING:
3769 case G_SUPPLICANT_STATE_ASSOCIATING:
3770 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3771 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3772 case G_SUPPLICANT_STATE_COMPLETED:
3779 static bool handle_wps_completion(GSupplicantInterface *interface,
3780 struct connman_network *network,
3781 struct connman_device *device,
3782 struct wifi_data *wifi)
3786 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3788 const unsigned char *ssid, *wps_ssid;
3789 unsigned int ssid_len, wps_ssid_len;
3790 const char *wps_key;
3792 /* Checking if we got associated with requested
3794 ssid = connman_network_get_blob(network, "WiFi.SSID",
3797 wps_ssid = g_supplicant_interface_get_wps_ssid(
3798 interface, &wps_ssid_len);
3800 if (!wps_ssid || wps_ssid_len != ssid_len ||
3801 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3802 connman_network_set_associating(network, false);
3803 #if defined TIZEN_EXT
3804 g_supplicant_interface_disconnect(wifi->interface,
3805 disconnect_callback, wifi->network);
3807 connman_network_set_bool(network, "WiFi.UseWPS", false);
3808 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3810 g_supplicant_interface_disconnect(wifi->interface,
3811 disconnect_callback, wifi);
3816 wps_key = g_supplicant_interface_get_wps_key(interface);
3817 #if defined TIZEN_EXT
3818 /* Check the passphrase and encrypt it
3821 gchar *passphrase = g_strdup(wps_key);
3823 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3825 if (check_passphrase_ext(network, passphrase) < 0) {
3826 DBG("[WPS] Invalid passphrase");
3831 ret = send_encryption_request(passphrase, network);
3836 DBG("[WPS] Encryption request succeeded");
3838 DBG("[WPS] Encryption request failed %d", ret);
3841 connman_network_set_string(network, "WiFi.Passphrase",
3844 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3851 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3852 struct wifi_data *wifi)
3854 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3855 #if defined TIZEN_EXT
3856 wifi->assoc_code > 0 &&
3858 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3860 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3861 wifi->load_shaping_retries ++;
3864 wifi->load_shaping_retries = 0;
3868 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3869 struct connman_network *network,
3870 struct wifi_data *wifi)
3872 #if defined TIZEN_EXT
3873 const char *security;
3874 struct connman_service *service;
3876 if (wifi->connected)
3879 security = connman_network_get_string(network, "WiFi.Security");
3881 if (security && g_str_equal(security, "ieee8021x") == true &&
3882 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3884 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3889 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3892 struct connman_service *service;
3894 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3897 if (wifi->connected)
3901 service = connman_service_lookup_from_network(network);
3907 if (connman_service_get_favorite(service)) {
3908 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3913 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3918 #if defined TIZEN_EXT
3919 static bool handle_wifi_assoc_retry(struct connman_network *network,
3920 struct wifi_data *wifi)
3922 const char *security;
3924 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3925 connman_network_get_connecting(network) != true) {
3926 wifi->assoc_retry_count = 0;
3930 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3931 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3932 wifi->assoc_retry_count = 0;
3936 security = connman_network_get_string(network, "WiFi.Security");
3937 if (security && g_str_equal(security, "ieee8021x") == true &&
3938 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3939 wifi->assoc_retry_count = 0;
3943 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3944 wifi->assoc_retry_count = 0;
3946 /* Honestly it's not an invalid-key error,
3947 * however QA team recommends that the invalid-key error
3948 * might be better to display for user experience.
3950 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3959 static void interface_state(GSupplicantInterface *interface)
3961 struct connman_network *network;
3962 struct connman_device *device;
3963 struct wifi_data *wifi;
3964 GSupplicantState state = g_supplicant_interface_get_state(interface);
3968 wifi = g_supplicant_interface_get_data(interface);
3970 DBG("wifi %p interface state %d", wifi, state);
3975 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3976 if (wifi->tethering_param) {
3977 g_free(wifi->tethering_param->ssid);
3978 g_free(wifi->tethering_param);
3979 wifi->tethering_param = NULL;
3983 device = wifi->device;
3987 if (g_supplicant_interface_get_ready(interface) &&
3988 !wifi->interface_ready) {
3989 wifi->interface_ready = true;
3990 finalize_interface_creation(wifi);
3993 network = wifi->network;
3998 case G_SUPPLICANT_STATE_SCANNING:
3999 if (wifi->connected)
4000 connman_network_set_connected(network, false);
4004 case G_SUPPLICANT_STATE_AUTHENTICATING:
4005 case G_SUPPLICANT_STATE_ASSOCIATING:
4006 #if defined TIZEN_EXT
4007 reset_autoscan(device);
4009 stop_autoscan(device);
4012 if (!wifi->connected)
4013 connman_network_set_associating(network, true);
4017 case G_SUPPLICANT_STATE_COMPLETED:
4018 #if defined TIZEN_EXT
4019 /* though it should be already reset: */
4020 reset_autoscan(device);
4022 wifi->assoc_retry_count = 0;
4024 wifi->scan_pending_network = NULL;
4026 /* should be cleared scanning flag */
4027 bool scanning = connman_device_get_scanning(device);
4029 connman_device_set_scanning(device,
4030 CONNMAN_SERVICE_TYPE_WIFI, false);
4031 connman_device_unref(device);
4034 if (!wifi->automaxspeed_timeout) {
4035 DBG("Going to start signalpoll timer!!");
4036 int ret = network_signalpoll(wifi);
4038 DBG("Fail to get max speed !!");
4040 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
4043 g_hash_table_remove_all(failed_bssids);
4045 /* though it should be already stopped: */
4046 stop_autoscan(device);
4049 if (!handle_wps_completion(interface, network, device, wifi))
4052 connman_network_set_connected(network, true);
4054 wifi->disconnect_code = 0;
4055 wifi->assoc_code = 0;
4056 wifi->load_shaping_retries = 0;
4059 case G_SUPPLICANT_STATE_DISCONNECTED:
4060 #if defined TIZEN_EXT
4061 connman_network_set_maxspeed(network, 0);
4063 if (wifi->automaxspeed_timeout != 0) {
4064 g_source_remove(wifi->automaxspeed_timeout);
4065 wifi->automaxspeed_timeout = 0;
4066 DBG("Remove signalpoll timer!!");
4070 * If we're in one of the idle modes, we have
4071 * not started association yet and thus setting
4072 * those ones to FALSE could cancel an association
4075 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4077 if (is_idle_wps(interface, wifi))
4083 #if defined TIZEN_EXT
4084 if (handle_assoc_status_code(interface, wifi)) {
4085 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4086 guint bssid_length = 0;
4089 bssid_length = g_slist_length(bssid_list);
4091 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4092 network_connect(network);
4096 wifi->load_shaping_retries = 0;
4099 g_hash_table_remove_all(failed_bssids);
4101 if (handle_assoc_status_code(interface, wifi))
4105 /* If previous state was 4way-handshake, then
4106 * it's either: psk was incorrect and thus we retry
4107 * or if we reach the maximum retries we declare the
4109 if (handle_4way_handshake_failure(interface,
4113 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4114 switch (wifi->disconnect_code) {
4115 case 1: /* Unspecified reason */
4116 /* Let's assume it's because we got blocked */
4118 case 6: /* Class 2 frame received from nonauthenticated STA */
4119 connman_network_set_error(network,
4120 CONNMAN_NETWORK_ERROR_BLOCKED);
4127 #if defined TIZEN_EXT
4128 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4129 * Retry association until its retry count is expired */
4130 if (handle_wifi_assoc_retry(network, wifi) == true) {
4131 throw_wifi_scan(wifi->device, scan_callback);
4132 wifi->scan_pending_network = wifi->network;
4136 if(wifi->disconnect_code > 0){
4137 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4138 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4142 connman_network_set_connected(network, false);
4143 connman_network_set_associating(network, false);
4144 wifi->disconnecting = false;
4146 start_autoscan(device);
4150 case G_SUPPLICANT_STATE_INACTIVE:
4151 #if defined TIZEN_EXT
4152 if (handle_wps_completion(interface, network, device, wifi) == false)
4155 connman_network_set_associating(network, false);
4156 start_autoscan(device);
4160 case G_SUPPLICANT_STATE_UNKNOWN:
4161 case G_SUPPLICANT_STATE_DISABLED:
4162 case G_SUPPLICANT_STATE_ASSOCIATED:
4163 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4164 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4168 old_connected = wifi->connected;
4169 wifi->state = state;
4171 /* Saving wpa_s state policy:
4172 * If connected and if the state changes are roaming related:
4173 * --> We stay connected
4175 * --> We are connected
4177 * --> We are not connected
4180 case G_SUPPLICANT_STATE_AUTHENTICATING:
4181 case G_SUPPLICANT_STATE_ASSOCIATING:
4182 case G_SUPPLICANT_STATE_ASSOCIATED:
4183 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4184 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4185 if (wifi->connected)
4186 connman_warn("Probably roaming right now!"
4187 " Staying connected...");
4189 case G_SUPPLICANT_STATE_SCANNING:
4190 wifi->connected = false;
4193 start_autoscan(device);
4195 case G_SUPPLICANT_STATE_COMPLETED:
4196 wifi->connected = true;
4199 wifi->connected = false;
4206 static void interface_removed(GSupplicantInterface *interface)
4208 const char *ifname = g_supplicant_interface_get_ifname(interface);
4209 struct wifi_data *wifi;
4211 DBG("ifname %s", ifname);
4213 wifi = g_supplicant_interface_get_data(interface);
4215 #if defined TIZEN_EXT_WIFI_MESH
4216 if (wifi && wifi->mesh_interface) {
4217 DBG("Notify mesh interface remove");
4218 connman_mesh_notify_interface_remove(true);
4219 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4220 g_free(mesh_info->parent_ifname);
4221 g_free(mesh_info->ifname);
4222 g_free(mesh_info->identifier);
4224 wifi->mesh_interface = false;
4225 wifi->mesh_info = NULL;
4231 wifi->interface = NULL;
4233 if (wifi && wifi->tethering)
4236 if (!wifi || !wifi->device) {
4237 DBG("wifi interface already removed");
4241 connman_device_set_powered(wifi->device, false);
4243 check_p2p_technology();
4244 #if defined TIZEN_EXT_WIFI_MESH
4245 check_mesh_technology();
4249 static void set_device_type(const char *type, char dev_type[17])
4251 const char *oui = "0050F204";
4252 const char *category = "0001";
4253 const char *sub_category = "0000";
4255 if (!g_strcmp0(type, "handset")) {
4257 sub_category = "0005";
4258 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4259 sub_category = "0001";
4260 else if (!g_strcmp0(type, "server"))
4261 sub_category = "0002";
4262 else if (!g_strcmp0(type, "laptop"))
4263 sub_category = "0005";
4264 else if (!g_strcmp0(type, "desktop"))
4265 sub_category = "0006";
4266 else if (!g_strcmp0(type, "tablet"))
4267 sub_category = "0009";
4268 else if (!g_strcmp0(type, "watch"))
4271 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4274 static void p2p_support(GSupplicantInterface *interface)
4276 char dev_type[17] = {};
4277 const char *hostname;
4284 if (!g_supplicant_interface_has_p2p(interface))
4287 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4288 DBG("Could not register P2P technology driver");
4292 hostname = connman_utsname_get_hostname();
4294 hostname = "ConnMan";
4296 set_device_type(connman_machine_get_type(), dev_type);
4297 g_supplicant_interface_set_p2p_device_config(interface,
4298 hostname, dev_type);
4299 connman_peer_driver_register(&peer_driver);
4302 static void scan_started(GSupplicantInterface *interface)
4307 static void scan_finished(GSupplicantInterface *interface)
4309 #if defined TIZEN_EXT
4310 struct wifi_data *wifi;
4311 bool is_associating = false;
4312 static bool is_scanning = true;
4317 #if defined TIZEN_EXT
4318 wifi = g_supplicant_interface_get_data(interface);
4319 if (wifi && wifi->scan_pending_network) {
4320 network_connect(wifi->scan_pending_network);
4321 wifi->scan_pending_network = NULL;
4324 //service state - associating
4325 if(!wifi || !wifi->network)
4328 is_associating = connman_network_get_associating(wifi->network);
4329 if(is_associating && is_scanning){
4330 is_scanning = false;
4331 DBG("send scan for connecting");
4332 throw_wifi_scan(wifi->device, scan_callback);
4343 static void ap_create_fail(GSupplicantInterface *interface)
4345 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4348 if ((wifi->tethering) && (wifi->tethering_param)) {
4349 DBG("%s create AP fail \n",
4350 g_supplicant_interface_get_ifname(wifi->interface));
4352 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4353 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4354 wifi->tethering = false;
4356 ret = tech_set_tethering(wifi->tethering_param->technology,
4357 wifi->tethering_param->ssid->ssid,
4358 wifi->tethering_param->ssid->passphrase,
4359 wifi->bridge, true);
4361 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4362 connman_technology_tethering_notify(wifi_technology,false);
4365 g_free(wifi->tethering_param->ssid);
4366 g_free(wifi->tethering_param);
4367 wifi->tethering_param = NULL;
4373 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4375 unsigned char strength;
4377 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4379 #if !defined TIZEN_EXT
4386 #if defined TIZEN_EXT_WIFI_MESH
4387 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4389 GSupplicantInterface *interface;
4390 struct wifi_data *wifi;
4391 const char *name, *security;
4392 struct connman_mesh *connman_mesh;
4393 struct wifi_mesh_info *mesh_info;
4394 const unsigned char *bssid;
4395 const char *identifier;
4400 interface = g_supplicant_network_get_interface(supplicant_network);
4401 wifi = g_supplicant_interface_get_data(interface);
4402 if (!wifi || !wifi->mesh_interface) {
4403 DBG("Virtual Mesh interface not created");
4407 bssid = g_supplicant_network_get_bssid(supplicant_network);
4408 address = g_malloc0(19);
4409 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4410 bssid[2], bssid[3], bssid[4], bssid[5]);
4412 identifier = g_supplicant_network_get_identifier(supplicant_network);
4413 name = g_supplicant_network_get_name(supplicant_network);
4414 security = g_supplicant_network_get_security(supplicant_network);
4415 frequency = g_supplicant_network_get_frequency(supplicant_network);
4417 mesh_info = wifi->mesh_info;
4418 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4422 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4424 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4425 connman_mesh_set_name(connman_mesh, name);
4426 connman_mesh_set_security(connman_mesh, security);
4427 connman_mesh_set_frequency(connman_mesh, frequency);
4428 connman_mesh_set_address(connman_mesh, address);
4429 connman_mesh_set_index(connman_mesh, mesh_info->index);
4430 connman_mesh_set_strength(connman_mesh,
4431 calculate_strength(supplicant_network));
4432 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4434 ret = connman_mesh_register(connman_mesh);
4435 if (ret == -EALREADY)
4436 DBG("Mesh Peer is already registered");
4442 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4444 GSupplicantInterface *interface;
4445 struct wifi_data *wifi;
4446 struct connman_mesh *connman_mesh;
4447 struct wifi_mesh_info *mesh_info;
4448 const char *identifier;
4450 interface = g_supplicant_network_get_interface(supplicant_network);
4451 wifi = g_supplicant_interface_get_data(interface);
4452 if (!wifi || !wifi->mesh_interface) {
4453 DBG("Virtual Mesh interface not created");
4457 identifier = g_supplicant_network_get_identifier(supplicant_network);
4459 DBG("Failed to get Mesh Peer identifier");
4463 mesh_info = wifi->mesh_info;
4464 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4466 /* Do not unregister connected mesh peer */
4467 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4468 DBG("Mesh Peer %s is connected", identifier);
4471 DBG("Mesh Peer identifier %s removed", identifier);
4472 connman_mesh_unregister(connman_mesh);
4477 static void network_added(GSupplicantNetwork *supplicant_network)
4479 struct connman_network *network;
4480 GSupplicantInterface *interface;
4481 struct wifi_data *wifi;
4482 const char *name, *identifier, *security, *group, *mode;
4483 const unsigned char *ssid;
4484 unsigned int ssid_len;
4488 bool wps_advertizing;
4490 #if defined TIZEN_EXT
4491 GSList *vsie_list = NULL;
4492 const unsigned char *country_code;
4493 ieee80211_modes_e phy_mode;
4496 mode = g_supplicant_network_get_mode(supplicant_network);
4497 identifier = g_supplicant_network_get_identifier(supplicant_network);
4499 DBG("%s", identifier);
4501 if (!g_strcmp0(mode, "adhoc"))
4504 #if defined TIZEN_EXT_WIFI_MESH
4505 if (!g_strcmp0(mode, "mesh")) {
4506 mesh_peer_added(supplicant_network);
4511 interface = g_supplicant_network_get_interface(supplicant_network);
4512 wifi = g_supplicant_interface_get_data(interface);
4513 name = g_supplicant_network_get_name(supplicant_network);
4514 security = g_supplicant_network_get_security(supplicant_network);
4515 group = g_supplicant_network_get_identifier(supplicant_network);
4516 wps = g_supplicant_network_get_wps(supplicant_network);
4517 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4518 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4519 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4520 supplicant_network);
4525 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4527 network = connman_device_get_network(wifi->device, identifier);
4530 network = connman_network_create(identifier,
4531 CONNMAN_NETWORK_TYPE_WIFI);
4535 connman_network_set_index(network, wifi->index);
4537 if (connman_device_add_network(wifi->device, network) < 0) {
4538 connman_network_unref(network);
4542 wifi->networks = g_slist_prepend(wifi->networks, network);
4545 if (name && name[0] != '\0')
4546 connman_network_set_name(network, name);
4548 connman_network_set_blob(network, "WiFi.SSID",
4550 #if defined TIZEN_EXT
4551 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4553 connman_network_set_vsie_list(network, vsie_list);
4555 DBG("vsie_list is NULL");
4556 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4557 connman_network_set_countrycode(network, country_code);
4558 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4559 connman_network_set_phy_mode(network, phy_mode);
4561 connman_network_set_string(network, "WiFi.Security", security);
4562 connman_network_set_strength(network,
4563 calculate_strength(supplicant_network));
4564 connman_network_set_bool(network, "WiFi.WPS", wps);
4567 /* Is AP advertizing for WPS association?
4568 * If so, we decide to use WPS by default */
4569 if (wps_ready && wps_pbc &&
4571 #if !defined TIZEN_EXT
4572 connman_network_set_bool(network, "WiFi.UseWPS", true);
4574 DBG("wps is activating by ap but ignore it.");
4579 connman_network_set_frequency(network,
4580 g_supplicant_network_get_frequency(supplicant_network));
4581 #if defined TIZEN_EXT
4582 connman_network_set_bssid(network,
4583 g_supplicant_network_get_bssid(supplicant_network));
4584 connman_network_set_maxrate(network,
4585 g_supplicant_network_get_maxrate(supplicant_network));
4586 connman_network_set_enc_mode(network,
4587 g_supplicant_network_get_enc_mode(supplicant_network));
4588 connman_network_set_rsn_mode(network,
4589 g_supplicant_network_get_rsn_mode(supplicant_network));
4590 connman_network_set_keymgmt(network,
4591 g_supplicant_network_get_keymgmt(supplicant_network));
4592 connman_network_set_bool(network, "WiFi.HS20AP",
4593 g_supplicant_network_is_hs20AP(supplicant_network));
4594 connman_network_set_bssid_list(network,
4595 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4597 connman_network_set_available(network, true);
4598 connman_network_set_string(network, "WiFi.Mode", mode);
4600 #if defined TIZEN_EXT
4605 connman_network_set_group(network, group);
4607 #if defined TIZEN_EXT
4608 if (wifi_first_scan == true)
4609 found_with_first_scan = true;
4612 if (wifi->hidden && ssid) {
4613 #if defined TIZEN_EXT
4614 if (network_security(wifi->hidden->security) ==
4615 network_security(security) &&
4617 if (!g_strcmp0(wifi->hidden->security, security) &&
4619 wifi->hidden->ssid_len == ssid_len &&
4620 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4621 connman_network_connect_hidden(network,
4622 wifi->hidden->identity,
4623 wifi->hidden->passphrase,
4624 wifi->hidden->user_data);
4625 wifi->hidden->user_data = NULL;
4626 hidden_free(wifi->hidden);
4627 wifi->hidden = NULL;
4632 static void network_removed(GSupplicantNetwork *network)
4634 GSupplicantInterface *interface;
4635 struct wifi_data *wifi;
4636 const char *name, *identifier;
4637 struct connman_network *connman_network;
4639 #if defined TIZEN_EXT_WIFI_MESH
4641 mode = g_supplicant_network_get_mode(network);
4642 if (!g_strcmp0(mode, "mesh")) {
4643 mesh_peer_removed(network);
4648 interface = g_supplicant_network_get_interface(network);
4649 wifi = g_supplicant_interface_get_data(interface);
4650 identifier = g_supplicant_network_get_identifier(network);
4651 name = g_supplicant_network_get_name(network);
4653 DBG("name %s", name);
4658 connman_network = connman_device_get_network(wifi->device, identifier);
4659 if (!connman_network)
4662 #if defined TIZEN_EXT
4663 if (connman_network == wifi->scan_pending_network)
4664 wifi->scan_pending_network = NULL;
4666 if (connman_network == wifi->pending_network)
4667 wifi->pending_network = NULL;
4669 if(connman_network_get_connecting(connman_network) == true){
4670 connman_network_set_connected(connman_network, false);
4674 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4676 connman_device_remove_network(wifi->device, connman_network);
4677 connman_network_unref(connman_network);
4680 static void network_changed(GSupplicantNetwork *network, const char *property)
4682 GSupplicantInterface *interface;
4683 struct wifi_data *wifi;
4684 const char *name, *identifier;
4685 struct connman_network *connman_network;
4687 #if defined TIZEN_EXT
4688 const unsigned char *bssid;
4689 unsigned int maxrate;
4692 const unsigned char *country_code;
4693 ieee80211_modes_e phy_mode;
4697 interface = g_supplicant_network_get_interface(network);
4698 wifi = g_supplicant_interface_get_data(interface);
4699 identifier = g_supplicant_network_get_identifier(network);
4700 name = g_supplicant_network_get_name(network);
4702 DBG("name %s", name);
4707 connman_network = connman_device_get_network(wifi->device, identifier);
4708 if (!connman_network)
4711 if (g_str_equal(property, "Signal")) {
4712 connman_network_set_strength(connman_network,
4713 calculate_strength(network));
4714 connman_network_update(connman_network);
4717 #if defined TIZEN_EXT
4718 bssid = g_supplicant_network_get_bssid(network);
4719 maxrate = g_supplicant_network_get_maxrate(network);
4720 frequency = g_supplicant_network_get_frequency(network);
4721 wps = g_supplicant_network_get_wps(network);
4722 phy_mode = g_supplicant_network_get_phy_mode(network);
4724 connman_network_set_bssid(connman_network, bssid);
4725 connman_network_set_maxrate(connman_network, maxrate);
4726 connman_network_set_frequency(connman_network, frequency);
4727 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4728 country_code = g_supplicant_network_get_countrycode(network);
4729 connman_network_set_countrycode(connman_network, country_code);
4730 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4731 connman_network_set_bssid_list(connman_network, bssid_list);
4732 connman_network_set_phy_mode(connman_network, phy_mode);
4734 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4735 connman_network_get_associating(connman_network))
4736 network_connect(connman_network);
4740 static void network_associated(GSupplicantNetwork *network)
4742 GSupplicantInterface *interface;
4743 struct wifi_data *wifi;
4744 struct connman_network *connman_network;
4745 const char *identifier;
4749 interface = g_supplicant_network_get_interface(network);
4753 wifi = g_supplicant_interface_get_data(interface);
4757 identifier = g_supplicant_network_get_identifier(network);
4759 connman_network = connman_device_get_network(wifi->device, identifier);
4760 if (!connman_network)
4763 if (wifi->network) {
4764 if (wifi->network == connman_network)
4768 * This should never happen, we got associated with
4769 * a network different than the one we were expecting.
4771 DBG("Associated to %p while expecting %p",
4772 connman_network, wifi->network);
4774 connman_network_set_associating(wifi->network, false);
4777 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4779 wifi->network = connman_network_ref(connman_network);
4783 * Interface state changes callback (interface_state) is always
4784 * called before network_associated callback thus we need to call
4785 * interface_state again in order to process the new state now that
4786 * we have the network properly set.
4788 interface_state(interface);
4791 static void apply_peer_services(GSupplicantPeer *peer,
4792 struct connman_peer *connman_peer)
4794 const unsigned char *data;
4799 connman_peer_reset_services(connman_peer);
4801 data = g_supplicant_peer_get_widi_ies(peer, &length);
4803 connman_peer_add_service(connman_peer,
4804 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4808 static void add_station(const char *mac)
4810 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4814 static void remove_station(const char *mac)
4816 connman_technology_tethering_remove_station(mac);
4819 static void peer_found(GSupplicantPeer *peer)
4821 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4822 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4823 struct connman_peer *connman_peer;
4824 const char *identifier, *name;
4826 #if defined TIZEN_EXT
4830 identifier = g_supplicant_peer_get_identifier(peer);
4831 name = g_supplicant_peer_get_name(peer);
4833 DBG("ident: %s", identifier);
4835 connman_peer = connman_peer_get(wifi->device, identifier);
4839 connman_peer = connman_peer_create(identifier);
4840 connman_peer_set_name(connman_peer, name);
4841 connman_peer_set_device(connman_peer, wifi->device);
4842 apply_peer_services(peer, connman_peer);
4844 ret = connman_peer_register(connman_peer);
4845 if (ret < 0 && ret != -EALREADY)
4846 connman_peer_unref(connman_peer);
4848 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4851 static void peer_lost(GSupplicantPeer *peer)
4853 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4854 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4855 struct connman_peer *connman_peer;
4856 const char *identifier;
4861 identifier = g_supplicant_peer_get_identifier(peer);
4863 DBG("ident: %s", identifier);
4865 connman_peer = connman_peer_get(wifi->device, identifier);
4867 if (wifi->p2p_connecting &&
4868 wifi->pending_peer == connman_peer) {
4869 peer_connect_timeout(wifi);
4871 connman_peer_unregister(connman_peer);
4872 connman_peer_unref(connman_peer);
4875 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4878 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4880 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4881 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4882 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4883 struct connman_peer *connman_peer;
4884 const char *identifier;
4886 identifier = g_supplicant_peer_get_identifier(peer);
4888 DBG("ident: %s", identifier);
4893 connman_peer = connman_peer_get(wifi->device, identifier);
4898 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4899 apply_peer_services(peer, connman_peer);
4900 connman_peer_services_changed(connman_peer);
4902 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4903 if (!g_supplicant_peer_is_in_a_group(peer))
4904 p_state = CONNMAN_PEER_STATE_IDLE;
4906 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4908 case G_SUPPLICANT_PEER_GROUP_STARTED:
4910 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4911 p_state = CONNMAN_PEER_STATE_IDLE;
4913 case G_SUPPLICANT_PEER_GROUP_JOINED:
4914 connman_peer_set_iface_address(connman_peer,
4915 g_supplicant_peer_get_iface_address(peer));
4917 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4918 p_state = CONNMAN_PEER_STATE_IDLE;
4920 case G_SUPPLICANT_PEER_GROUP_FAILED:
4921 if (g_supplicant_peer_has_requested_connection(peer))
4922 p_state = CONNMAN_PEER_STATE_IDLE;
4924 p_state = CONNMAN_PEER_STATE_FAILURE;
4928 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4929 p_state == CONNMAN_PEER_STATE_FAILURE) {
4930 if (wifi->p2p_connecting
4931 && connman_peer == wifi->pending_peer)
4932 peer_cancel_timeout(wifi);
4934 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4937 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4940 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4941 GSupplicantInterface *g_iface;
4942 struct wifi_data *g_wifi;
4944 g_iface = g_supplicant_peer_get_group_interface(peer);
4948 g_wifi = g_supplicant_interface_get_data(g_iface);
4952 connman_peer_set_as_master(connman_peer,
4953 !g_supplicant_peer_is_client(peer));
4954 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4957 * If wpa_supplicant didn't create a dedicated p2p-group
4958 * interface then mark this interface as p2p_device to avoid
4959 * scan and auto-scan are launched on it while P2P is connected.
4961 if (!g_list_find(p2p_iface_list, g_wifi))
4962 wifi->p2p_device = true;
4965 connman_peer_set_state(connman_peer, p_state);
4968 static void peer_request(GSupplicantPeer *peer)
4970 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4971 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4972 struct connman_peer *connman_peer;
4973 const char *identifier;
4975 #if defined TIZEN_EXT
4980 identifier = g_supplicant_peer_get_identifier(peer);
4982 DBG("ident: %s", identifier);
4984 connman_peer = connman_peer_get(wifi->device, identifier);
4988 connman_peer_request_connection(connman_peer);
4991 #if defined TIZEN_EXT
4992 static void system_power_off(void)
4995 struct wifi_data *wifi;
4996 struct connman_service *service;
4997 struct connman_ipconfig *ipconfig_ipv4;
4999 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
5000 for (list = iface_list; list; list = list->next) {
5003 if (wifi->network != NULL) {
5004 service = connman_service_lookup_from_network(wifi->network);
5005 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5006 __connman_dhcp_stop(ipconfig_ipv4);
5012 static void network_merged(GSupplicantNetwork *network)
5014 GSupplicantInterface *interface;
5015 GSupplicantState state;
5016 struct wifi_data *wifi;
5017 const char *identifier;
5018 struct connman_network *connman_network;
5022 interface = g_supplicant_network_get_interface(network);
5026 state = g_supplicant_interface_get_state(interface);
5027 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5030 wifi = g_supplicant_interface_get_data(interface);
5034 identifier = g_supplicant_network_get_identifier(network);
5036 connman_network = connman_device_get_network(wifi->device, identifier);
5037 if (!connman_network)
5040 DBG("merged identifier %s", identifier);
5042 if (wifi->connected == FALSE) {
5044 case G_SUPPLICANT_STATE_AUTHENTICATING:
5045 case G_SUPPLICANT_STATE_ASSOCIATING:
5046 case G_SUPPLICANT_STATE_ASSOCIATED:
5047 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5048 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5049 connman_network_set_associating(connman_network, TRUE);
5051 case G_SUPPLICANT_STATE_COMPLETED:
5052 connman_network_set_connected(connman_network, TRUE);
5055 DBG("Not handled the state : %d", state);
5060 ishs20AP = g_supplicant_network_is_hs20AP(network);
5063 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5064 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5065 connman_network_set_string(connman_network, "WiFi.EAP",
5067 connman_network_set_string(connman_network, "WiFi.Identity",
5068 g_supplicant_network_get_identity(network));
5069 connman_network_set_string(connman_network, "WiFi.Phase2",
5070 g_supplicant_network_get_phase2(network));
5075 wifi->network = connman_network;
5078 static void assoc_failed(void *user_data)
5080 struct connman_network *network = user_data;
5081 connman_network_set_associating(network, false);
5085 static void debug(const char *str)
5087 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5088 connman_debug("%s", str);
5091 static void disconnect_reasoncode(GSupplicantInterface *interface,
5094 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5097 wifi->disconnect_code = reasoncode;
5101 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5103 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5106 wifi->assoc_code = status_code;
5110 static const GSupplicantCallbacks callbacks = {
5111 .system_ready = system_ready,
5112 .system_killed = system_killed,
5113 .interface_added = interface_added,
5114 .interface_state = interface_state,
5115 .interface_removed = interface_removed,
5116 .p2p_support = p2p_support,
5117 .scan_started = scan_started,
5118 .scan_finished = scan_finished,
5119 .ap_create_fail = ap_create_fail,
5120 .network_added = network_added,
5121 .network_removed = network_removed,
5122 .network_changed = network_changed,
5123 .network_associated = network_associated,
5124 .add_station = add_station,
5125 .remove_station = remove_station,
5126 .peer_found = peer_found,
5127 .peer_lost = peer_lost,
5128 .peer_changed = peer_changed,
5129 .peer_request = peer_request,
5130 #if defined TIZEN_EXT
5131 .system_power_off = system_power_off,
5132 .network_merged = network_merged,
5133 .assoc_failed = assoc_failed,
5136 .disconnect_reasoncode = disconnect_reasoncode,
5137 .assoc_status_code = assoc_status_code,
5138 #if defined TIZEN_EXT_WIFI_MESH
5139 .mesh_support = mesh_support,
5140 .mesh_group_started = mesh_group_started,
5141 .mesh_group_removed = mesh_group_removed,
5142 .mesh_peer_connected = mesh_peer_connected,
5143 .mesh_peer_disconnected = mesh_peer_disconnected,
5148 static int tech_probe(struct connman_technology *technology)
5150 wifi_technology = technology;
5155 static void tech_remove(struct connman_technology *technology)
5157 wifi_technology = NULL;
5160 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5161 const char *passphrase)
5163 GSupplicantSSID *ap;
5165 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5169 ap->mode = G_SUPPLICANT_MODE_MASTER;
5170 #if defined TIZEN_EXT
5171 ap->ssid = (void *) ssid;
5175 ap->ssid_len = strlen(ssid);
5179 if (!passphrase || strlen(passphrase) == 0) {
5180 ap->security = G_SUPPLICANT_SECURITY_NONE;
5181 ap->passphrase = NULL;
5183 ap->security = G_SUPPLICANT_SECURITY_PSK;
5184 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5185 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5186 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5187 ap->passphrase = passphrase;
5193 static void ap_start_callback(int result, GSupplicantInterface *interface,
5196 struct wifi_tethering_info *info = user_data;
5198 DBG("result %d index %d bridge %s",
5199 result, info->wifi->index, info->wifi->bridge);
5201 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5202 connman_inet_remove_from_bridge(info->wifi->index,
5203 info->wifi->bridge);
5205 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5206 connman_technology_tethering_notify(info->technology, false);
5207 g_free(info->wifi->tethering_param->ssid);
5208 g_free(info->wifi->tethering_param);
5209 info->wifi->tethering_param = NULL;
5213 g_free(info->ifname);
5217 static void ap_create_callback(int result,
5218 GSupplicantInterface *interface,
5221 struct wifi_tethering_info *info = user_data;
5223 DBG("result %d ifname %s", result,
5224 g_supplicant_interface_get_ifname(interface));
5226 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5227 connman_inet_remove_from_bridge(info->wifi->index,
5228 info->wifi->bridge);
5230 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5231 connman_technology_tethering_notify(info->technology, false);
5232 g_free(info->wifi->tethering_param->ssid);
5233 g_free(info->wifi->tethering_param);
5234 info->wifi->tethering_param = NULL;
5238 g_free(info->ifname);
5244 info->wifi->interface = interface;
5245 g_supplicant_interface_set_data(interface, info->wifi);
5247 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5248 connman_error("Failed to set interface ap_scan property");
5250 g_supplicant_interface_connect(interface, info->ssid,
5251 ap_start_callback, info);
5254 static void sta_remove_callback(int result,
5255 GSupplicantInterface *interface,
5258 struct wifi_tethering_info *info = user_data;
5259 const char *driver = connman_option_get_string("wifi");
5261 DBG("ifname %s result %d ", info->ifname, result);
5263 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5264 info->wifi->tethering = false;
5265 connman_technology_tethering_notify(info->technology, false);
5267 g_free(info->ifname);
5271 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5272 g_free(info->wifi->tethering_param->ssid);
5273 g_free(info->wifi->tethering_param);
5274 info->wifi->tethering_param = NULL;
5279 info->wifi->interface = NULL;
5281 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5286 static int enable_wifi_tethering(struct connman_technology *technology,
5287 const char *bridge, const char *identifier,
5288 const char *passphrase, bool available)
5291 GSupplicantInterface *interface;
5292 struct wifi_data *wifi;
5293 struct wifi_tethering_info *info;
5298 for (list = iface_list; list; list = list->next) {
5301 DBG("wifi %p network %p pending_network %p", wifi,
5302 wifi->network, wifi->pending_network);
5304 interface = wifi->interface;
5309 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5312 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5314 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5315 DBG("%s does not support AP mode (detected)", ifname);
5319 mode = g_supplicant_interface_get_mode(interface);
5320 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5321 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5322 DBG("%s does not support AP mode (capability)", ifname);
5326 if (wifi->network && available)
5329 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5333 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5334 if (!wifi->tethering_param) {
5340 info->technology = technology;
5341 info->wifi->bridge = bridge;
5342 info->ssid = ssid_ap_init(identifier, passphrase);
5346 info->ifname = g_strdup(ifname);
5350 wifi->tethering_param->technology = technology;
5351 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5352 if (!wifi->tethering_param->ssid)
5355 info->wifi->tethering = true;
5356 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5358 berr = connman_technology_tethering_notify(technology, true);
5362 err = g_supplicant_interface_remove(interface,
5363 sta_remove_callback,
5366 DBG("tethering wifi %p ifname %s", wifi, ifname);
5371 g_free(info->ifname);
5374 g_free(wifi->tethering_param);
5375 wifi->tethering_param = NULL;
5378 * Remove bridge if it was correctly created but remove
5379 * operation failed. Instead, if bridge creation failed then
5380 * break out and do not try again on another interface,
5381 * bridge set-up does not depend on it.
5384 connman_technology_tethering_notify(technology, false);
5392 static int tech_set_tethering(struct connman_technology *technology,
5393 const char *identifier, const char *passphrase,
5394 const char *bridge, bool enabled)
5397 struct wifi_data *wifi;
5403 for (list = iface_list; list; list = list->next) {
5406 if (wifi->tethering) {
5407 wifi->tethering = false;
5409 connman_inet_remove_from_bridge(wifi->index,
5411 wifi->bridged = false;
5415 connman_technology_tethering_notify(technology, false);
5420 DBG("trying tethering for available devices");
5421 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5425 DBG("trying tethering for any device");
5426 err = enable_wifi_tethering(technology, bridge, identifier,
5433 static void regdom_callback(int result, const char *alpha2, void *user_data)
5437 if (!wifi_technology)
5443 connman_technology_regdom_notify(wifi_technology, alpha2);
5446 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5448 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5451 static struct connman_technology_driver tech_driver = {
5453 .type = CONNMAN_SERVICE_TYPE_WIFI,
5454 .probe = tech_probe,
5455 .remove = tech_remove,
5456 .set_tethering = tech_set_tethering,
5457 .set_regdom = tech_set_regdom,
5460 static int wifi_init(void)
5464 err = connman_network_driver_register(&network_driver);
5468 err = g_supplicant_register(&callbacks);
5470 connman_network_driver_unregister(&network_driver);
5474 err = connman_technology_driver_register(&tech_driver);
5476 g_supplicant_unregister(&callbacks);
5477 connman_network_driver_unregister(&network_driver);
5481 #if defined TIZEN_EXT
5482 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5487 static void wifi_exit(void)
5491 connman_technology_driver_unregister(&tech_driver);
5493 g_supplicant_unregister(&callbacks);
5495 connman_network_driver_unregister(&network_driver);
5497 #if defined TIZEN_EXT
5498 g_hash_table_unref(failed_bssids);
5502 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5503 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)