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
75 #define LOAD_SHAPING_MAX_RETRIES 3
78 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
81 static struct connman_technology *wifi_technology = NULL;
82 static struct connman_technology *p2p_technology = NULL;
84 enum wifi_ap_capability{
86 WIFI_AP_SUPPORTED = 1,
87 WIFI_AP_NOT_SUPPORTED = 2,
90 struct hidden_params {
92 unsigned int ssid_len;
94 char *anonymous_identity;
96 char *altsubject_match;
97 char *domain_suffix_match;
101 GSupplicantScanParams *scan_params;
106 * Used for autoscan "emulation".
107 * Should be removed when wpa_s autoscan support will be by default.
109 struct autoscan_params {
113 unsigned int timeout;
116 struct wifi_tethering_info {
117 struct wifi_data *wifi;
118 struct connman_technology *technology;
120 GSupplicantSSID *ssid;
125 struct connman_device *device;
126 struct connman_network *network;
127 struct connman_network *pending_network;
129 GSupplicantInterface *interface;
130 GSupplicantState state;
134 enum wifi_ap_capability ap_supported;
136 bool interface_ready;
142 int load_shaping_retries;
143 struct hidden_params *hidden;
144 bool postpone_hidden;
145 struct wifi_tethering_info *tethering_param;
147 * autoscan "emulation".
149 struct autoscan_params *autoscan;
151 GSupplicantScanParams *scan_params;
152 unsigned int p2p_find_timeout;
153 unsigned int p2p_connection_timeout;
154 struct connman_peer *pending_peer;
159 #if defined TIZEN_EXT
160 int assoc_retry_count;
161 struct connman_network *scan_pending_network;
162 bool allow_full_scan;
163 unsigned int automaxspeed_timeout;
164 GSupplicantScanParams *hidden_scan_params;
168 #if defined TIZEN_EXT_WIFI_MESH
170 struct wifi_mesh_info *mesh_info;
174 #if defined TIZEN_EXT
178 #define TIZEN_ASSOC_RETRY_COUNT 4
180 static gboolean wifi_first_scan = false;
181 static gboolean found_with_first_scan = false;
182 static gboolean is_wifi_notifier_registered = false;
186 static GList *iface_list = NULL;
188 static GList *pending_wifi_device = NULL;
189 static GList *p2p_iface_list = NULL;
190 bool wfd_service_registered = false;
192 static void start_autoscan(struct connman_device *device);
194 static int tech_set_tethering(struct connman_technology *technology,
195 const char *identifier, const char *passphrase,
196 const char *bridge, bool enabled);
198 #if defined TIZEN_EXT
199 #define NETCONFIG_SERVICE "net.netconfig"
200 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
201 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
203 struct enc_method_call_data {
204 DBusConnection *connection;
205 struct connman_network *network;
208 static struct enc_method_call_data encrypt_request_data;
210 static void encryption_request_reply(DBusPendingCall *call,
215 DBusMessageIter args;
217 struct connman_service *service;
218 gchar* encrypted_value = NULL;
219 struct connman_network *network = encrypt_request_data.network;
223 reply = dbus_pending_call_steal_reply(call);
225 dbus_error_init(&error);
226 if (dbus_set_error_from_message(&error, reply)) {
227 DBG("send_encryption_request() %s %s", error.name, error.message);
228 dbus_error_free(&error);
232 if (dbus_message_iter_init(reply, &args) == FALSE)
235 dbus_message_iter_get_basic(&args, &out_data);
237 encrypted_value = g_strdup((const gchar *)out_data);
238 service = connman_service_lookup_from_network(network);
241 DBG("encryption result: no service");
245 if (connman_service_get_favorite(service)) {
246 __connman_service_set_passphrase(service, encrypted_value);
247 __connman_service_save(service);
249 connman_network_set_string(network, "WiFi.Passphrase",
252 DBG("encryption result: succeeded");
255 dbus_message_unref(reply);
256 dbus_pending_call_unref(call);
257 dbus_connection_unref(encrypt_request_data.connection);
258 g_free(encrypted_value);
260 encrypt_request_data.connection = NULL;
261 encrypt_request_data.network = NULL;
264 static int send_encryption_request(const char *passphrase,
265 struct connman_network *network)
267 DBusConnection *connection = NULL;
268 DBusMessage *msg = NULL;
269 DBusPendingCall *call;
272 DBG("Invalid parameter");
276 connection = connman_dbus_get_connection();
278 DBG("dbus connection does not exist");
282 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
283 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
285 dbus_connection_unref(connection);
289 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
292 if (!dbus_connection_send_with_reply(connection, msg,
293 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
294 dbus_message_unref(msg);
295 dbus_connection_unref(connection);
300 dbus_message_unref(msg);
301 dbus_connection_unref(connection);
305 encrypt_request_data.connection = connection;
306 encrypt_request_data.network = network;
308 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
309 dbus_message_unref(msg);
315 static int p2p_tech_probe(struct connman_technology *technology)
317 p2p_technology = technology;
322 static void p2p_tech_remove(struct connman_technology *technology)
324 p2p_technology = NULL;
327 static struct connman_technology_driver p2p_tech_driver = {
329 .type = CONNMAN_SERVICE_TYPE_P2P,
330 .probe = p2p_tech_probe,
331 .remove = p2p_tech_remove,
334 static bool is_p2p_connecting(void)
338 for (list = iface_list; list; list = list->next) {
339 struct wifi_data *wifi = list->data;
341 if (wifi->p2p_connecting)
348 static void add_pending_wifi_device(struct wifi_data *wifi)
350 if (g_list_find(pending_wifi_device, wifi))
353 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
356 #if defined TIZEN_EXT_WIFI_MESH
357 struct wifi_mesh_info {
358 struct wifi_data *wifi;
359 GSupplicantInterface *interface;
360 struct connman_mesh *mesh;
367 struct mesh_change_peer_status_info {
369 enum connman_mesh_peer_status peer_status;
370 mesh_change_peer_status_cb_t callback;
374 static struct connman_technology_driver mesh_tech_driver = {
376 .type = CONNMAN_SERVICE_TYPE_MESH,
379 static void mesh_interface_create_callback(int result,
380 GSupplicantInterface *interface,
383 struct wifi_mesh_info *mesh_info = user_data;
384 struct wifi_data *wifi;
385 bool success = false;
387 DBG("result %d ifname %s, mesh_info %p", result,
388 g_supplicant_interface_get_ifname(interface),
391 if (result < 0 || !mesh_info)
394 wifi = mesh_info->wifi;
396 mesh_info->interface = interface;
397 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
398 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
399 DBG("Mesh Interface identifier %s", mesh_info->identifier);
400 wifi->mesh_interface = true;
401 wifi->mesh_info = mesh_info;
402 g_supplicant_interface_set_data(interface, wifi);
406 connman_mesh_notify_interface_create(success);
409 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
412 struct wifi_data *wifi;
413 struct wifi_mesh_info *mesh_info;
414 const char *wifi_ifname;
415 bool parent_found = false;
416 const char *driver = "nl80211";
418 for (list = iface_list; list; list = list->next) {
421 if (!g_supplicant_interface_has_mesh(wifi->interface))
424 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
428 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
435 DBG("Parent interface %s doesn't exist", parent_ifname);
439 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
443 mesh_info->wifi = wifi;
444 mesh_info->ifname = g_strdup(ifname);
445 mesh_info->parent_ifname = g_strdup(parent_ifname);
447 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
448 mesh_interface_create_callback, mesh_info);
452 static void mesh_interface_remove_callback(int result,
453 GSupplicantInterface *interface,
456 struct wifi_data *wifi = user_data;
457 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
458 bool success = false;
460 DBG("result %d mesh_info %p", result, mesh_info);
462 if (result < 0 || !mesh_info)
465 mesh_info->interface = NULL;
466 g_free(mesh_info->parent_ifname);
467 g_free(mesh_info->ifname);
468 g_free(mesh_info->identifier);
470 wifi->mesh_interface = false;
471 wifi->mesh_info = NULL;
475 connman_mesh_notify_interface_remove(success);
478 static int remove_mesh_interface(const char *ifname)
481 struct wifi_data *wifi;
482 struct wifi_mesh_info *mesh_info;
483 bool mesh_if_found = false;
486 for (list = iface_list; list; list = list->next) {
489 if (wifi->mesh_interface) {
490 mesh_if_found = true;
495 if (!mesh_if_found) {
496 DBG("Mesh interface %s doesn't exist", ifname);
500 mesh_info = wifi->mesh_info;
501 ret = g_supplicant_interface_remove(mesh_info->interface,
502 mesh_interface_remove_callback, wifi);
509 static void mesh_disconnect_callback(int result,
510 GSupplicantInterface *interface, void *user_data)
512 struct connman_mesh *mesh = user_data;
514 DBG("result %d interface %p mesh %p", result, interface, mesh);
517 static int mesh_peer_disconnect(struct connman_mesh *mesh)
520 struct wifi_data *wifi;
521 struct wifi_mesh_info *mesh_info;
522 bool mesh_if_found = false;
523 GSupplicantInterface *interface;
525 for (list = iface_list; list; list = list->next) {
528 if (wifi->mesh_interface) {
529 mesh_if_found = true;
534 if (!mesh_if_found) {
535 DBG("Mesh interface is not created");
539 mesh_info = wifi->mesh_info;
541 interface = mesh_info->interface;
542 return g_supplicant_interface_disconnect(interface,
543 mesh_disconnect_callback, mesh);
546 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
549 struct connman_mesh *mesh = user_data;
550 DBG("mesh %p result %d", mesh, result);
553 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
555 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
558 static GSupplicantSecurity mesh_network_security(const char *security)
560 if (g_str_equal(security, "none"))
561 return G_SUPPLICANT_SECURITY_NONE;
562 else if (g_str_equal(security, "sae"))
563 return G_SUPPLICANT_SECURITY_SAE;
565 return G_SUPPLICANT_SECURITY_UNKNOWN;
568 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
571 const char *security;
576 memset(ssid, 0, sizeof(*ssid));
577 ssid->mode = G_SUPPLICANT_MODE_MESH;
579 security = connman_mesh_get_security(mesh);
580 ssid->security = mesh_network_security(security);
582 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
583 ssid->passphrase = connman_mesh_get_passphrase(mesh);
585 ssid->freq = connman_mesh_get_frequency(mesh);
586 name = connman_mesh_get_name(mesh);
588 ssid->ssid_len = strlen(name);
589 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
590 memcpy(ssid->ssid, name, ssid->ssid_len);
595 static int mesh_peer_connect(struct connman_mesh *mesh)
598 struct wifi_data *wifi;
599 struct wifi_mesh_info *mesh_info;
600 bool mesh_if_found = false;
601 GSupplicantInterface *interface;
602 GSupplicantSSID *ssid;
604 for (list = iface_list; list; list = list->next) {
607 if (wifi->mesh_interface) {
608 mesh_if_found = true;
613 if (!mesh_if_found) {
614 DBG("Mesh interface is not created");
618 mesh_info = wifi->mesh_info;
620 interface = mesh_info->interface;
622 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
626 mesh_info->mesh = mesh;
628 mesh_ssid_init(ssid, mesh);
629 return g_supplicant_interface_connect(interface, ssid,
630 mesh_connect_callback, mesh);
633 static void mesh_peer_change_status_callback(int result,
634 GSupplicantInterface *interface,
637 struct mesh_change_peer_status_info *data = user_data;
639 DBG("result %d Peer Status %d", result, data->peer_status);
641 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
642 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
643 connman_mesh_remove_connected_peer(data->peer_address, 52);
647 data->callback(result, data->user_data);
649 g_free(data->peer_address);
654 static int mesh_change_peer_status(const char *peer_address,
655 enum connman_mesh_peer_status status,
656 mesh_change_peer_status_cb_t callback, void *user_data)
659 struct wifi_data *wifi;
660 struct wifi_mesh_info *mesh_info;
661 bool mesh_if_found = false;
662 GSupplicantInterface *interface;
663 struct mesh_change_peer_status_info *data;
666 for (list = iface_list; list; list = list->next) {
669 if (wifi->mesh_interface) {
670 mesh_if_found = true;
675 if (!mesh_if_found) {
676 DBG("Mesh interface is not created");
680 mesh_info = wifi->mesh_info;
682 interface = mesh_info->interface;
685 case CONNMAN_MESH_PEER_ADD:
686 method = "MeshPeerAdd";
688 case CONNMAN_MESH_PEER_REMOVE:
689 method = "MeshPeerRemove";
692 DBG("Invalid method");
696 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
698 DBG("Memory allocation failed");
702 data->peer_address = g_strdup(peer_address);
703 data->peer_status = status;
704 data->callback = callback;
705 data->user_data = user_data;
707 return g_supplicant_interface_mesh_peer_change_status(interface,
708 mesh_peer_change_status_callback, peer_address, method,
712 static struct connman_mesh_driver mesh_driver = {
713 .add_interface = add_mesh_interface,
714 .remove_interface = remove_mesh_interface,
715 .connect = mesh_peer_connect,
716 .disconnect = mesh_peer_disconnect,
717 .change_peer_status = mesh_change_peer_status,
720 static void mesh_support(GSupplicantInterface *interface)
724 if (!g_supplicant_interface_has_mesh(interface))
727 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
728 DBG("Could not register Mesh technology driver");
732 connman_mesh_driver_register(&mesh_driver);
735 static void check_mesh_technology(void)
737 bool mesh_exists = false;
740 for (list = iface_list; list; list = list->next) {
741 struct wifi_data *w = list->data;
744 g_supplicant_interface_has_mesh(w->interface))
749 connman_technology_driver_unregister(&mesh_tech_driver);
750 connman_mesh_driver_unregister(&mesh_driver);
754 static void mesh_group_started(GSupplicantInterface *interface)
756 struct wifi_data *wifi;
757 struct wifi_mesh_info *mesh_info;
758 struct connman_mesh *mesh;
759 const unsigned char *ssid;
760 unsigned int ssid_len;
763 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
764 memcpy(name, ssid, ssid_len);
765 name[ssid_len] = '\0';
766 DBG("name %s", name);
767 wifi = g_supplicant_interface_get_data(interface);
768 DBG("wifi %p", wifi);
773 mesh_info = wifi->mesh_info;
777 mesh = mesh_info->mesh;
781 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
784 static void mesh_group_removed(GSupplicantInterface *interface)
786 struct wifi_data *wifi;
787 struct wifi_mesh_info *mesh_info;
788 struct connman_mesh *mesh;
789 const unsigned char *ssid;
790 unsigned int ssid_len;
791 int disconnect_reason;
794 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
795 memcpy(name, ssid, ssid_len);
796 name[ssid_len] = '\0';
797 DBG("name %s", name);
799 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
800 DBG("Disconnect Reason %d", disconnect_reason);
802 wifi = g_supplicant_interface_get_data(interface);
803 DBG("wifi %p", wifi);
808 mesh_info = wifi->mesh_info;
812 mesh = connman_get_connected_mesh_from_name(name);
814 DBG("%s is not connected", name);
815 mesh = connman_get_connecting_mesh_from_name(name);
817 DBG("%s is not connecting", name);
822 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
823 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
826 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
828 const char *peer_address;
830 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
835 DBG("Peer %s connected", peer_address);
836 connman_mesh_add_connected_peer(peer_address);
839 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
841 const char *peer_address;
844 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
849 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
851 DBG("Peer %s disconnected with reason %d", peer_address, reason);
852 connman_mesh_remove_connected_peer(peer_address, reason);
856 static struct wifi_data *get_pending_wifi_data(const char *ifname)
860 for (list = pending_wifi_device; list; list = list->next) {
861 struct wifi_data *wifi;
862 const char *dev_name;
865 if (!wifi || !wifi->device)
868 dev_name = connman_device_get_string(wifi->device, "Interface");
869 if (!g_strcmp0(ifname, dev_name)) {
870 pending_wifi_device = g_list_delete_link(
871 pending_wifi_device, list);
879 static void remove_pending_wifi_device(struct wifi_data *wifi)
883 link = g_list_find(pending_wifi_device, wifi);
888 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
891 static void peer_cancel_timeout(struct wifi_data *wifi)
893 if (wifi->p2p_connection_timeout > 0)
894 g_source_remove(wifi->p2p_connection_timeout);
896 wifi->p2p_connection_timeout = 0;
897 wifi->p2p_connecting = false;
899 if (wifi->pending_peer) {
900 connman_peer_unref(wifi->pending_peer);
901 wifi->pending_peer = NULL;
905 static gboolean peer_connect_timeout(gpointer data)
907 struct wifi_data *wifi = data;
911 if (wifi->p2p_connecting) {
912 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
913 GSupplicantPeer *gs_peer =
914 g_supplicant_interface_peer_lookup(wifi->interface,
915 connman_peer_get_identifier(wifi->pending_peer));
917 if (g_supplicant_peer_has_requested_connection(gs_peer))
918 state = CONNMAN_PEER_STATE_IDLE;
920 connman_peer_set_state(wifi->pending_peer, state);
923 peer_cancel_timeout(wifi);
928 static void peer_connect_callback(int result, GSupplicantInterface *interface,
931 struct wifi_data *wifi = user_data;
932 struct connman_peer *peer = wifi->pending_peer;
934 DBG("peer %p - %d", peer, result);
940 peer_connect_timeout(wifi);
944 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
946 wifi->p2p_connection_timeout = g_timeout_add_seconds(
947 P2P_CONNECTION_TIMEOUT,
948 peer_connect_timeout, wifi);
951 static int peer_connect(struct connman_peer *peer,
952 enum connman_peer_wps_method wps_method,
955 struct connman_device *device = connman_peer_get_device(peer);
956 GSupplicantPeerParams *peer_params;
957 GSupplicantPeer *gs_peer;
958 struct wifi_data *wifi;
962 DBG("peer %p", peer);
967 wifi = connman_device_get_data(device);
968 if (!wifi || !wifi->interface)
971 if (wifi->p2p_connecting)
974 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
975 connman_peer_get_identifier(peer));
979 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
980 pin = g_supplicant_peer_is_wps_pin(gs_peer);
982 switch (wps_method) {
983 case CONNMAN_PEER_WPS_UNKNOWN:
984 if ((pbc && pin) || pin)
987 case CONNMAN_PEER_WPS_PBC:
992 case CONNMAN_PEER_WPS_PIN:
993 if (!pin || !wps_pin)
998 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1002 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1004 peer_params->wps_pin = g_strdup(wps_pin);
1006 peer_params->master = connman_peer_service_is_master();
1008 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1009 peer_connect_callback, wifi);
1010 if (ret == -EINPROGRESS) {
1011 wifi->pending_peer = connman_peer_ref(peer);
1012 wifi->p2p_connecting = true;
1013 } else if (ret < 0) {
1014 g_free(peer_params->path);
1015 g_free(peer_params->wps_pin);
1016 g_free(peer_params);
1022 static int peer_disconnect(struct connman_peer *peer)
1024 struct connman_device *device = connman_peer_get_device(peer);
1025 GSupplicantPeerParams peer_params = {};
1026 GSupplicantPeer *gs_peer;
1027 struct wifi_data *wifi;
1030 DBG("peer %p", peer);
1035 wifi = connman_device_get_data(device);
1039 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1040 connman_peer_get_identifier(peer));
1044 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1046 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1048 g_free(peer_params.path);
1050 if (ret == -EINPROGRESS) {
1051 peer_cancel_timeout(wifi);
1052 wifi->p2p_device = false;
1058 struct peer_service_registration {
1059 peer_service_registration_cb_t callback;
1063 static bool is_service_wfd(const unsigned char *specs, int length)
1065 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1071 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1073 struct wifi_data *wifi = data;
1075 if (!wifi->interface ||
1076 !g_supplicant_interface_has_p2p(wifi->interface))
1079 if (!wifi->servicing) {
1080 g_supplicant_interface_p2p_listen(wifi->interface,
1081 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1087 static void register_wfd_service_cb(int result,
1088 GSupplicantInterface *iface, void *user_data)
1090 struct peer_service_registration *reg_data = user_data;
1095 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1097 if (reg_data && reg_data->callback) {
1098 reg_data->callback(result, reg_data->user_data);
1103 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1104 const unsigned char *spec,
1105 int spec_length, const unsigned char *query,
1106 int query_length, int version)
1108 GSupplicantP2PServiceParams *params;
1110 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1115 params->version = version;
1116 params->service = g_memdup(spec, spec_length);
1117 } else if (query_length > 0 && spec_length > 0) {
1118 params->query = g_memdup(query, query_length);
1119 params->query_length = query_length;
1121 params->response = g_memdup(spec, spec_length);
1122 params->response_length = spec_length;
1124 params->wfd_ies = g_memdup(spec, spec_length);
1125 params->wfd_ies_length = spec_length;
1131 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1136 g_free(params->service);
1137 g_free(params->query);
1138 g_free(params->response);
1139 g_free(params->wfd_ies);
1144 static int peer_register_wfd_service(const unsigned char *specification,
1145 int specification_length,
1146 peer_service_registration_cb_t callback,
1149 struct peer_service_registration *reg_data = NULL;
1150 static GSupplicantP2PServiceParams *params;
1155 if (wfd_service_registered)
1158 params = fill_in_peer_service_params(specification,
1159 specification_length, NULL, 0, 0);
1163 reg_data = g_try_malloc0(sizeof(*reg_data));
1169 reg_data->callback = callback;
1170 reg_data->user_data = user_data;
1172 ret = g_supplicant_set_widi_ies(params,
1173 register_wfd_service_cb, reg_data);
1174 if (ret < 0 && ret != -EINPROGRESS)
1177 wfd_service_registered = true;
1181 free_peer_service_params(params);
1187 static void register_peer_service_cb(int result,
1188 GSupplicantInterface *iface, void *user_data)
1190 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1191 struct peer_service_registration *reg_data = user_data;
1193 #if defined TIZEN_EXT
1201 apply_p2p_listen_on_iface(wifi, NULL);
1203 if (reg_data->callback)
1204 reg_data->callback(result, reg_data->user_data);
1209 static int peer_register_service(const unsigned char *specification,
1210 int specification_length,
1211 const unsigned char *query,
1212 int query_length, int version,
1213 peer_service_registration_cb_t callback,
1216 struct peer_service_registration *reg_data;
1217 GSupplicantP2PServiceParams *params;
1224 if (specification && !version && !query &&
1225 is_service_wfd(specification, specification_length)) {
1226 return peer_register_wfd_service(specification,
1227 specification_length, callback, user_data);
1230 reg_data = g_try_malloc0(sizeof(*reg_data));
1234 reg_data->callback = callback;
1235 reg_data->user_data = user_data;
1237 ret_f = -EOPNOTSUPP;
1239 for (list = iface_list; list; list = list->next) {
1240 struct wifi_data *wifi = list->data;
1241 GSupplicantInterface *iface = wifi->interface;
1243 if (!g_supplicant_interface_has_p2p(iface))
1246 params = fill_in_peer_service_params(specification,
1247 specification_length, query,
1248 query_length, version);
1255 ret_f = g_supplicant_interface_p2p_add_service(iface,
1256 register_peer_service_cb, params, reg_data);
1257 if (ret_f == 0 || ret_f == -EINPROGRESS)
1261 ret = g_supplicant_interface_p2p_add_service(iface,
1262 register_peer_service_cb, params, NULL);
1263 if (ret != 0 && ret != -EINPROGRESS)
1264 free_peer_service_params(params);
1267 if (ret_f != 0 && ret_f != -EINPROGRESS)
1273 static int peer_unregister_wfd_service(void)
1275 GSupplicantP2PServiceParams *params;
1278 if (!wfd_service_registered)
1281 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1285 wfd_service_registered = false;
1287 g_supplicant_set_widi_ies(params, NULL, NULL);
1289 for (list = iface_list; list; list = list->next) {
1290 struct wifi_data *wifi = list->data;
1292 if (!g_supplicant_interface_has_p2p(wifi->interface))
1296 if (!wifi->servicing || wifi->servicing < 0) {
1297 g_supplicant_interface_p2p_listen(wifi->interface,
1299 wifi->servicing = 0;
1306 static int peer_unregister_service(const unsigned char *specification,
1307 int specification_length,
1308 const unsigned char *query,
1309 int query_length, int version)
1311 GSupplicantP2PServiceParams *params;
1316 if (specification && !version && !query &&
1317 is_service_wfd(specification, specification_length)) {
1318 ret = peer_unregister_wfd_service();
1319 if (ret != 0 && ret != -EINPROGRESS)
1324 for (list = iface_list; list; list = list->next) {
1325 struct wifi_data *wifi = list->data;
1326 GSupplicantInterface *iface = wifi->interface;
1329 goto stop_listening;
1331 if (!g_supplicant_interface_has_p2p(iface))
1334 params = fill_in_peer_service_params(specification,
1335 specification_length, query,
1336 query_length, version);
1342 ret = g_supplicant_interface_p2p_del_service(iface, params);
1343 if (ret != 0 && ret != -EINPROGRESS)
1344 free_peer_service_params(params);
1347 if (!wifi->servicing || wifi->servicing < 0) {
1348 g_supplicant_interface_p2p_listen(iface, 0, 0);
1349 wifi->servicing = 0;
1356 static struct connman_peer_driver peer_driver = {
1357 .connect = peer_connect,
1358 .disconnect = peer_disconnect,
1359 .register_service = peer_register_service,
1360 .unregister_service = peer_unregister_service,
1363 static void handle_tethering(struct wifi_data *wifi)
1365 if (!wifi->tethering)
1374 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1376 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1379 wifi->bridged = true;
1382 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1384 struct connman_device *device = user_data;
1385 struct wifi_data *wifi = connman_device_get_data(device);
1390 DBG("index %d flags %d change %d", wifi->index, flags, change);
1392 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1394 DBG("interface up");
1396 DBG("interface down");
1399 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1400 if (flags & IFF_LOWER_UP) {
1403 handle_tethering(wifi);
1408 wifi->flags = flags;
1411 static int wifi_probe(struct connman_device *device)
1413 struct wifi_data *wifi;
1415 DBG("device %p", device);
1417 wifi = g_try_new0(struct wifi_data, 1);
1421 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1422 wifi->ap_supported = WIFI_AP_UNKNOWN;
1423 wifi->tethering_param = NULL;
1425 connman_device_set_data(device, wifi);
1426 wifi->device = connman_device_ref(device);
1428 wifi->index = connman_device_get_index(device);
1431 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1432 wifi_newlink, device);
1433 if (is_p2p_connecting())
1434 add_pending_wifi_device(wifi);
1436 iface_list = g_list_append(iface_list, wifi);
1441 static void remove_networks(struct connman_device *device,
1442 struct wifi_data *wifi)
1446 for (list = wifi->networks; list; list = list->next) {
1447 struct connman_network *network = list->data;
1449 connman_device_remove_network(device, network);
1450 connman_network_unref(network);
1453 g_slist_free(wifi->networks);
1454 wifi->networks = NULL;
1457 static void remove_peers(struct wifi_data *wifi)
1461 for (list = wifi->peers; list; list = list->next) {
1462 struct connman_peer *peer = list->data;
1464 connman_peer_unregister(peer);
1465 connman_peer_unref(peer);
1468 g_slist_free(wifi->peers);
1472 static void reset_autoscan(struct connman_device *device)
1474 struct wifi_data *wifi = connman_device_get_data(device);
1475 struct autoscan_params *autoscan;
1479 if (!wifi || !wifi->autoscan)
1482 autoscan = wifi->autoscan;
1484 if (autoscan->timeout == 0 && autoscan->interval == 0)
1487 g_source_remove(autoscan->timeout);
1489 autoscan->timeout = 0;
1490 autoscan->interval = 0;
1492 connman_device_unref(device);
1495 static void stop_autoscan(struct connman_device *device)
1497 const struct wifi_data *wifi = connman_device_get_data(device);
1499 if (!wifi || !wifi->autoscan)
1502 reset_autoscan(device);
1504 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1507 static void check_p2p_technology(void)
1509 bool p2p_exists = false;
1512 for (list = iface_list; list; list = list->next) {
1513 struct wifi_data *w = list->data;
1516 g_supplicant_interface_has_p2p(w->interface))
1521 connman_technology_driver_unregister(&p2p_tech_driver);
1522 connman_peer_driver_unregister(&peer_driver);
1526 static void wifi_remove(struct connman_device *device)
1528 struct wifi_data *wifi = connman_device_get_data(device);
1530 DBG("device %p wifi %p", device, wifi);
1535 stop_autoscan(device);
1537 if (wifi->p2p_device)
1538 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1540 iface_list = g_list_remove(iface_list, wifi);
1542 check_p2p_technology();
1543 #if defined TIZEN_EXT_WIFI_MESH
1544 check_mesh_technology();
1547 remove_pending_wifi_device(wifi);
1549 if (wifi->p2p_find_timeout) {
1550 g_source_remove(wifi->p2p_find_timeout);
1551 connman_device_unref(wifi->device);
1554 if (wifi->p2p_connection_timeout)
1555 g_source_remove(wifi->p2p_connection_timeout);
1557 #if defined TIZEN_EXT
1558 if (wifi->automaxspeed_timeout != 0) {
1559 g_source_remove(wifi->automaxspeed_timeout);
1560 wifi->automaxspeed_timeout = 0;
1564 remove_networks(device, wifi);
1567 connman_device_set_powered(device, false);
1568 connman_device_set_data(device, NULL);
1569 connman_device_unref(wifi->device);
1570 connman_rtnl_remove_watch(wifi->watch);
1572 g_supplicant_interface_set_data(wifi->interface, NULL);
1574 g_supplicant_interface_cancel(wifi->interface);
1576 if (wifi->scan_params)
1577 g_supplicant_free_scan_params(wifi->scan_params);
1578 #if defined TIZEN_EXT
1579 if (wifi->hidden_scan_params) {
1580 while (wifi->hidden_scan_params->ssids) {
1581 struct scan_ssid *ssid;
1582 ssid = wifi->hidden_scan_params->ssids->data;
1583 wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
1585 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1589 g_free(wifi->autoscan);
1590 g_free(wifi->identifier);
1594 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1598 for (iter = list; iter; iter = g_slist_next(iter)) {
1599 struct scan_ssid *scan_ssid = iter->data;
1601 if (ssid_len == scan_ssid->ssid_len &&
1602 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1609 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1610 int freq, GSupplicantScanParams *scan_data,
1611 int driver_max_scan_ssids, char *ssid_name)
1614 struct scan_ssid *scan_ssid;
1616 if ((driver_max_scan_ssids == 0 ||
1617 driver_max_scan_ssids > scan_data->num_ssids) &&
1618 (hex_ssid || raw_ssid)) {
1620 unsigned int j = 0, hex;
1623 size_t hex_ssid_len = strlen(hex_ssid);
1625 ssid = g_try_malloc0(hex_ssid_len / 2);
1629 for (i = 0; i < hex_ssid_len; i += 2) {
1630 sscanf(hex_ssid + i, "%02x", &hex);
1639 * If we have already added hidden AP to the list,
1640 * then do not do it again. This might happen if you have
1641 * used or are using multiple wifi cards, so in that case
1642 * you might have multiple service files for same AP.
1644 if (is_duplicate(scan_data->ssids, ssid, j)) {
1650 scan_ssid = g_try_new(struct scan_ssid, 1);
1657 memcpy(scan_ssid->ssid, ssid, j);
1658 scan_ssid->ssid_len = j;
1659 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1662 scan_data->num_ssids++;
1664 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1665 scan_data->num_ssids);
1672 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1674 if (!scan_data->freqs) {
1675 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1676 if (!scan_data->freqs) {
1677 g_slist_free_full(scan_data->ssids, g_free);
1681 scan_data->num_freqs = 1;
1682 scan_data->freqs[0] = freq;
1684 bool duplicate = false;
1686 /* Don't add duplicate entries */
1687 for (i = 0; i < scan_data->num_freqs; i++) {
1688 if (scan_data->freqs[i] == freq) {
1695 scan_data->num_freqs++;
1696 scan_data->freqs = g_try_realloc(scan_data->freqs,
1697 sizeof(uint16_t) * scan_data->num_freqs);
1698 if (!scan_data->freqs) {
1699 g_slist_free_full(scan_data->ssids, g_free);
1702 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1709 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1711 struct connman_config_entry **entries;
1717 int num_ssids = 0, add_param_failed = 0;
1719 services = connman_storage_get_services();
1720 for (i = 0; services && services[i]; i++) {
1721 if (strncmp(services[i], "wifi_", 5) != 0)
1724 keyfile = connman_storage_load_service(services[i]);
1728 value = g_key_file_get_boolean(keyfile,
1729 services[i], "Hidden", NULL);
1731 g_key_file_free(keyfile);
1735 value = g_key_file_get_boolean(keyfile,
1736 services[i], "Favorite", NULL);
1738 g_key_file_free(keyfile);
1742 #if defined TIZEN_EXT
1743 value = g_key_file_get_boolean(keyfile,
1744 services[i], "AutoConnect", NULL);
1746 g_key_file_free(keyfile);
1751 ssid = g_key_file_get_string(keyfile,
1752 services[i], "SSID", NULL);
1754 name = g_key_file_get_string(keyfile, services[i], "Name",
1757 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1765 g_key_file_free(keyfile);
1769 * Check if there are any hidden AP that needs to be provisioned.
1771 entries = connman_config_get_entries("wifi");
1772 for (i = 0; entries && entries[i]; i++) {
1775 if (!entries[i]->hidden)
1778 if (!entries[i]->ssid) {
1779 ssid = entries[i]->name;
1782 ssid = entries[i]->ssid;
1783 len = entries[i]->ssid_len;
1789 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1796 connman_config_free_entries(entries);
1798 if (add_param_failed > 0)
1799 DBG("Unable to scan %d out of %d SSIDs",
1800 add_param_failed, num_ssids);
1802 g_strfreev(services);
1807 static int get_hidden_connections_params(struct wifi_data *wifi,
1808 GSupplicantScanParams *scan_params)
1810 int driver_max_ssids, i;
1811 GSupplicantScanParams *orig_params;
1814 * Scan hidden networks so that we can autoconnect to them.
1815 * We will assume 1 as a default number of ssid to scan.
1817 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1819 if (driver_max_ssids == 0)
1820 driver_max_ssids = 1;
1822 DBG("max ssids %d", driver_max_ssids);
1824 #if defined TIZEN_EXT
1825 if (!wifi->hidden_scan_params) {
1826 wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1827 if (!wifi->hidden_scan_params)
1830 if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
1831 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1832 wifi->hidden_scan_params = NULL;
1838 orig_params = wifi->hidden_scan_params;
1840 if (!wifi->scan_params) {
1841 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1842 if (!wifi->scan_params)
1845 if (get_hidden_connections(wifi->scan_params) == 0) {
1846 g_supplicant_free_scan_params(wifi->scan_params);
1847 wifi->scan_params = NULL;
1853 orig_params = wifi->scan_params;
1856 /* Let's transfer driver_max_ssids params */
1857 for (i = 0; i < driver_max_ssids; i++) {
1858 struct scan_ssid *ssid;
1860 #if defined TIZEN_EXT
1861 if (!wifi->hidden_scan_params->ssids)
1863 if (!wifi->scan_params->ssids)
1867 ssid = orig_params->ssids->data;
1868 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1869 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1873 scan_params->num_ssids = i;
1874 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1876 scan_params->freqs = g_memdup(orig_params->freqs,
1877 sizeof(uint16_t) * orig_params->num_freqs);
1878 if (!scan_params->freqs)
1881 scan_params->num_freqs = orig_params->num_freqs;
1886 orig_params->num_ssids -= scan_params->num_ssids;
1888 return scan_params->num_ssids;
1891 g_slist_free_full(scan_params->ssids, g_free);
1892 #if defined TIZEN_EXT
1893 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1894 wifi->hidden_scan_params = NULL;
1896 g_supplicant_free_scan_params(wifi->scan_params);
1897 wifi->scan_params = NULL;
1903 static int throw_wifi_scan(struct connman_device *device,
1904 GSupplicantInterfaceCallback callback)
1906 struct wifi_data *wifi = connman_device_get_data(device);
1912 DBG("device %p %p", device, wifi->interface);
1914 if (wifi->tethering)
1916 #if defined TIZEN_EXT
1917 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1919 if (connman_device_get_scanning(device))
1923 connman_device_ref(device);
1925 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1928 connman_device_set_scanning(device,
1929 CONNMAN_SERVICE_TYPE_WIFI, true);
1931 connman_device_unref(device);
1936 static void hidden_free(struct hidden_params *hidden)
1941 if (hidden->scan_params)
1942 g_supplicant_free_scan_params(hidden->scan_params);
1943 g_free(hidden->identity);
1944 g_free(hidden->passphrase);
1945 g_free(hidden->security);
1949 #if defined TIZEN_EXT
1950 static void service_state_changed(struct connman_service *service,
1951 enum connman_service_state state);
1953 static int network_connect(struct connman_network *network);
1955 static struct connman_notifier notifier = {
1957 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1958 .service_state_changed = service_state_changed,
1961 static void service_state_changed(struct connman_service *service,
1962 enum connman_service_state state)
1964 enum connman_service_type type;
1966 type = connman_service_get_type(service);
1967 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1970 DBG("service %p state %d", service, state);
1973 case CONNMAN_SERVICE_STATE_READY:
1974 case CONNMAN_SERVICE_STATE_ONLINE:
1975 case CONNMAN_SERVICE_STATE_FAILURE:
1976 connman_notifier_unregister(¬ifier);
1977 is_wifi_notifier_registered = FALSE;
1979 __connman_device_request_scan(type);
1988 static void scan_callback(int result, GSupplicantInterface *interface,
1991 struct connman_device *device = user_data;
1992 struct wifi_data *wifi = connman_device_get_data(device);
1995 DBG("result %d wifi %p", result, wifi);
1998 if (wifi->hidden && !wifi->postpone_hidden) {
1999 connman_network_clear_hidden(wifi->hidden->user_data);
2000 hidden_free(wifi->hidden);
2001 wifi->hidden = NULL;
2004 if (wifi->scan_params) {
2005 g_supplicant_free_scan_params(wifi->scan_params);
2006 wifi->scan_params = NULL;
2009 #if defined TIZEN_EXT
2010 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2011 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2012 wifi->hidden_scan_params = NULL;
2018 connman_device_reset_scanning(device);
2020 /* User is connecting to a hidden AP, let's wait for finished event */
2021 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2022 GSupplicantScanParams *scan_params;
2025 wifi->postpone_hidden = false;
2026 scan_params = wifi->hidden->scan_params;
2027 wifi->hidden->scan_params = NULL;
2029 reset_autoscan(device);
2031 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2032 scan_callback, device);
2036 /* On error, let's recall scan_callback, which will cleanup */
2037 return scan_callback(ret, interface, user_data);
2040 #if defined TIZEN_EXT
2041 if (wifi && wifi->allow_full_scan) {
2043 DBG("Trigger Full Channel Scan");
2044 wifi->allow_full_scan = FALSE;
2046 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2047 scan_callback, device);
2051 /* On error, let's recall scan_callback, which will cleanup */
2052 return scan_callback(ret, interface, user_data);
2056 scanning = connman_device_get_scanning(device);
2058 connman_device_set_scanning(device,
2059 CONNMAN_SERVICE_TYPE_WIFI, false);
2061 if (result != -ENOLINK)
2062 #if defined TIZEN_EXT
2065 start_autoscan(device);
2068 * If we are here then we were scanning; however, if we are
2069 * also mid-flight disabling the interface, then wifi_disable
2070 * has already cleared the device scanning state and
2071 * unreferenced the device, obviating the need to do it here.
2075 connman_device_unref(device);
2077 #if defined TIZEN_EXT
2078 if (wifi && wifi->scan_pending_network && result != -EIO) {
2079 network_connect(wifi->scan_pending_network);
2080 wifi->scan_pending_network = NULL;
2081 connman_network_set_connecting(wifi->network);
2084 if (is_wifi_notifier_registered != true &&
2085 wifi_first_scan == true && found_with_first_scan == true) {
2086 wifi_first_scan = false;
2087 found_with_first_scan = false;
2089 connman_notifier_register(¬ifier);
2090 is_wifi_notifier_registered = true;
2095 static void scan_callback_hidden(int result,
2096 GSupplicantInterface *interface, void *user_data)
2098 struct connman_device *device = user_data;
2099 struct wifi_data *wifi = connman_device_get_data(device);
2100 GSupplicantScanParams *scan_params;
2103 DBG("result %d wifi %p", result, wifi);
2108 /* User is trying to connect to a hidden AP */
2109 if (wifi->hidden && wifi->postpone_hidden)
2112 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2116 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2117 ret = g_supplicant_interface_scan(wifi->interface,
2119 #if defined TIZEN_EXT
2122 scan_callback_hidden,
2130 g_supplicant_free_scan_params(scan_params);
2133 scan_callback(result, interface, user_data);
2136 static gboolean autoscan_timeout(gpointer data)
2138 struct connman_device *device = data;
2139 struct wifi_data *wifi = connman_device_get_data(device);
2140 struct autoscan_params *autoscan;
2146 autoscan = wifi->autoscan;
2148 if (autoscan->interval <= 0) {
2149 interval = autoscan->base;
2152 interval = autoscan->interval * autoscan->base;
2154 #if defined TIZEN_EXT
2155 if (autoscan->interval >= autoscan->limit)
2157 if (interval > autoscan->limit)
2159 interval = autoscan->limit;
2161 throw_wifi_scan(wifi->device, scan_callback_hidden);
2164 DBG("interval %d", interval);
2166 autoscan->interval = interval;
2168 autoscan->timeout = g_timeout_add_seconds(interval,
2169 autoscan_timeout, device);
2174 static void start_autoscan(struct connman_device *device)
2176 struct wifi_data *wifi = connman_device_get_data(device);
2177 struct autoscan_params *autoscan;
2184 if (wifi->p2p_device)
2187 if (wifi->connected)
2190 autoscan = wifi->autoscan;
2194 if (autoscan->timeout > 0 || autoscan->interval > 0)
2197 connman_device_ref(device);
2199 autoscan_timeout(device);
2202 static struct autoscan_params *parse_autoscan_params(const char *params)
2204 struct autoscan_params *autoscan;
2209 DBG("Emulating autoscan");
2211 list_params = g_strsplit(params, ":", 0);
2212 if (list_params == 0)
2215 if (g_strv_length(list_params) < 3) {
2216 g_strfreev(list_params);
2220 base = atoi(list_params[1]);
2221 limit = atoi(list_params[2]);
2223 g_strfreev(list_params);
2225 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2227 DBG("Could not allocate memory for autoscan");
2231 DBG("base %d - limit %d", base, limit);
2232 autoscan->base = base;
2233 autoscan->limit = limit;
2238 static void setup_autoscan(struct wifi_data *wifi)
2240 if (!wifi->autoscan)
2241 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2243 start_autoscan(wifi->device);
2246 static void finalize_interface_creation(struct wifi_data *wifi)
2248 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2250 if (!wifi->device) {
2251 connman_error("WiFi device not set");
2255 connman_device_set_powered(wifi->device, true);
2257 if (!connman_setting_get_bool("BackgroundScanning"))
2260 if (wifi->p2p_device)
2263 setup_autoscan(wifi);
2266 static void interface_create_callback(int result,
2267 GSupplicantInterface *interface,
2270 struct wifi_data *wifi = user_data;
2272 DBG("result %d ifname %s, wifi %p", result,
2273 g_supplicant_interface_get_ifname(interface),
2276 if (result < 0 || !wifi)
2279 wifi->interface = interface;
2280 g_supplicant_interface_set_data(interface, wifi);
2282 if (g_supplicant_interface_get_ready(interface)) {
2283 wifi->interface_ready = true;
2284 finalize_interface_creation(wifi);
2288 static int wifi_enable(struct connman_device *device)
2290 struct wifi_data *wifi = connman_device_get_data(device);
2293 const char *driver = connman_option_get_string("wifi");
2296 DBG("device %p %p", device, wifi);
2298 index = connman_device_get_index(device);
2299 if (!wifi || index < 0)
2302 if (is_p2p_connecting())
2303 return -EINPROGRESS;
2305 interface = connman_inet_ifname(index);
2306 ret = g_supplicant_interface_create(interface, driver, NULL,
2307 interface_create_callback,
2314 return -EINPROGRESS;
2317 static int wifi_disable(struct connman_device *device)
2319 struct wifi_data *wifi = connman_device_get_data(device);
2322 DBG("device %p wifi %p", device, wifi);
2327 wifi->connected = false;
2328 wifi->disconnecting = false;
2330 if (wifi->pending_network)
2331 wifi->pending_network = NULL;
2333 stop_autoscan(device);
2335 if (wifi->p2p_find_timeout) {
2336 g_source_remove(wifi->p2p_find_timeout);
2337 wifi->p2p_find_timeout = 0;
2338 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2339 connman_device_unref(wifi->device);
2342 #if defined TIZEN_EXT
2343 if (wifi->automaxspeed_timeout != 0) {
2344 g_source_remove(wifi->automaxspeed_timeout);
2345 wifi->automaxspeed_timeout = 0;
2349 /* In case of a user scan, device is still referenced */
2350 if (connman_device_get_scanning(device)) {
2351 connman_device_set_scanning(device,
2352 CONNMAN_SERVICE_TYPE_WIFI, false);
2353 connman_device_unref(wifi->device);
2356 remove_networks(device, wifi);
2359 #if defined TIZEN_EXT
2360 wifi->scan_pending_network = NULL;
2362 if (is_wifi_notifier_registered == true) {
2363 connman_notifier_unregister(¬ifier);
2364 is_wifi_notifier_registered = false;
2368 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2372 return -EINPROGRESS;
2375 struct last_connected {
2381 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
2383 GTimeVal *aval = (GTimeVal *)a;
2384 GTimeVal *bval = (GTimeVal *)b;
2386 /* Note that the sort order is descending */
2387 if (aval->tv_sec < bval->tv_sec)
2390 if (aval->tv_sec > bval->tv_sec)
2396 static void free_entry(gpointer data)
2398 struct last_connected *entry = data;
2400 g_free(entry->ssid);
2404 static int get_latest_connections(int max_ssids,
2405 GSupplicantScanParams *scan_data)
2407 GSequenceIter *iter;
2408 GSequence *latest_list;
2409 struct last_connected *entry;
2418 latest_list = g_sequence_new(free_entry);
2422 services = connman_storage_get_services();
2423 for (i = 0; services && services[i]; i++) {
2424 if (strncmp(services[i], "wifi_", 5) != 0)
2427 keyfile = connman_storage_load_service(services[i]);
2431 str = g_key_file_get_string(keyfile,
2432 services[i], "Favorite", NULL);
2433 if (!str || g_strcmp0(str, "true")) {
2435 g_key_file_free(keyfile);
2440 str = g_key_file_get_string(keyfile,
2441 services[i], "AutoConnect", 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], "Modified", NULL);
2452 g_key_file_free(keyfile);
2455 g_time_val_from_iso8601(str, &modified);
2458 ssid = g_key_file_get_string(keyfile,
2459 services[i], "SSID", NULL);
2461 freq = g_key_file_get_integer(keyfile, services[i],
2464 entry = g_try_new(struct last_connected, 1);
2466 g_sequence_free(latest_list);
2467 g_key_file_free(keyfile);
2473 entry->modified = modified;
2476 g_sequence_insert_sorted(latest_list, entry,
2482 g_key_file_free(keyfile);
2485 g_strfreev(services);
2487 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2489 iter = g_sequence_get_begin_iter(latest_list);
2491 for (i = 0; i < num_ssids; i++) {
2492 entry = g_sequence_get(iter);
2494 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2495 entry->modified.tv_sec);
2497 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2498 max_ssids, entry->ssid);
2500 iter = g_sequence_iter_next(iter);
2503 g_sequence_free(latest_list);
2507 static int wifi_scan_simple(struct connman_device *device)
2509 reset_autoscan(device);
2511 return throw_wifi_scan(device, scan_callback_hidden);
2514 static gboolean p2p_find_stop(gpointer data)
2516 struct connman_device *device = data;
2517 struct wifi_data *wifi = connman_device_get_data(device);
2522 wifi->p2p_find_timeout = 0;
2524 g_supplicant_interface_p2p_stop_find(wifi->interface);
2527 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2529 connman_device_unref(device);
2530 reset_autoscan(device);
2535 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2538 struct connman_device *device = user_data;
2539 struct wifi_data *wifi = connman_device_get_data(device);
2541 DBG("result %d wifi %p", result, wifi);
2546 if (wifi->p2p_find_timeout) {
2547 g_source_remove(wifi->p2p_find_timeout);
2548 wifi->p2p_find_timeout = 0;
2554 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2555 p2p_find_stop, device);
2556 if (!wifi->p2p_find_timeout)
2561 p2p_find_stop(device);
2564 static int p2p_find(struct connman_device *device)
2566 struct wifi_data *wifi;
2571 if (!p2p_technology)
2574 wifi = connman_device_get_data(device);
2576 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2579 reset_autoscan(device);
2580 connman_device_ref(device);
2582 ret = g_supplicant_interface_p2p_find(wifi->interface,
2583 p2p_find_callback, device);
2585 connman_device_unref(device);
2586 start_autoscan(device);
2588 connman_device_set_scanning(device,
2589 CONNMAN_SERVICE_TYPE_P2P, true);
2595 #if defined TIZEN_EXT
2596 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2599 struct connman_device *device = user_data;
2600 struct wifi_data *wifi = connman_device_get_data(device);
2603 DBG("result %d wifi %p", result, wifi);
2605 if (wifi && wifi->scan_params) {
2606 g_supplicant_free_scan_params(wifi->scan_params);
2607 wifi->scan_params = NULL;
2610 scanning = connman_device_get_scanning(device);
2612 connman_device_set_scanning(device,
2613 CONNMAN_SERVICE_TYPE_WIFI, false);
2614 connman_device_unref(device);
2618 static int wifi_specific_scan(enum connman_service_type type,
2619 struct connman_device *device, int scan_type,
2620 GSList *specific_scan_list, void *user_data)
2622 GSList *list = NULL;
2624 struct wifi_data *wifi = connman_device_get_data(device);
2625 GSupplicantScanParams *scan_params = NULL;
2626 struct scan_ssid *scan_ssid = NULL;
2635 if (wifi->p2p_device)
2638 if (type == CONNMAN_SERVICE_TYPE_P2P)
2639 return p2p_find(device);
2641 if (wifi->tethering)
2644 scanning = connman_device_get_scanning(device);
2648 DBG("scan_type: %d", scan_type);
2649 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2650 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2652 DBG("Failed to allocate memory.");
2656 for (list = specific_scan_list; list; list = list->next) {
2657 ssid = (char *)list->data;
2658 int ssid_len = strlen(ssid);
2660 scan_ssid = g_try_new0(struct scan_ssid, 1);
2662 DBG("Failed to allocate memory.");
2663 g_supplicant_free_scan_params(scan_params);
2667 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2668 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2669 scan_ssid->ssid_len = ssid_len;
2670 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2673 scan_params->num_ssids = count;
2675 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2677 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2679 DBG("Failed to allocate memory.");
2683 guint num_freqs = g_slist_length(specific_scan_list);
2684 DBG("num_freqs: %d", num_freqs);
2686 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2687 if (!scan_params->freqs) {
2688 DBG("Failed to allocate memory.");
2689 g_free(scan_params);
2694 for (list = specific_scan_list; list; list = list->next) {
2695 freq = (int)list->data;
2697 scan_params->freqs[count] = freq;
2698 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2701 scan_params->num_freqs = count;
2703 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2704 int freq_count, ap_count;
2705 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2707 DBG("Failed to allocate memory.");
2711 guint size = g_slist_length(specific_scan_list);
2713 scan_params->freqs = g_try_new0(uint16_t, size/2);
2714 if (!scan_params->freqs) {
2715 DBG("Failed to allocate memory.");
2716 g_free(scan_params);
2720 ap_count = freq_count = 0;
2721 for (list = specific_scan_list; list; list = list->next) {
2722 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2723 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2724 int ssid_len = strlen(ssid);
2726 scan_ssid = g_try_new0(struct scan_ssid, 1);
2728 DBG("Failed to allocate memory.");
2729 g_supplicant_free_scan_params(scan_params);
2733 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2734 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2735 scan_ssid->ssid_len = ssid_len;
2736 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2740 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2741 scan_params->freqs[freq_count] = freq;
2742 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2746 scan_params->num_ssids = ap_count;
2747 scan_params->num_freqs = freq_count;
2749 DBG("Invalid scan");
2753 reset_autoscan(device);
2754 connman_device_ref(device);
2756 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2757 specific_scan_callback, device);
2760 connman_device_set_scanning(device,
2761 CONNMAN_SERVICE_TYPE_WIFI, true);
2763 g_supplicant_free_scan_params(scan_params);
2764 connman_device_unref(device);
2771 #if defined TIZEN_EXT_WIFI_MESH
2772 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2775 struct connman_device *device = user_data;
2776 struct wifi_data *wifi = connman_device_get_data(device);
2779 DBG("result %d wifi %p", result, wifi);
2781 scanning = connman_device_get_scanning(device);
2783 connman_device_set_scanning(device,
2784 CONNMAN_SERVICE_TYPE_MESH, false);
2787 connman_device_unref(device);
2790 static int mesh_scan(struct connman_device *device)
2792 struct wifi_data *wifi;
2793 struct wifi_mesh_info *mesh_info;
2798 wifi = connman_device_get_data(device);
2800 if (!wifi->mesh_interface)
2803 mesh_info = wifi->mesh_info;
2804 reset_autoscan(device);
2805 connman_device_ref(device);
2807 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2808 mesh_scan_callback, device);
2810 connman_device_unref(device);
2812 connman_device_set_scanning(device,
2813 CONNMAN_SERVICE_TYPE_MESH, true);
2818 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2821 struct connman_device *device = user_data;
2822 struct wifi_data *wifi = connman_device_get_data(device);
2824 DBG("result %d wifi %p", result, wifi);
2826 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2829 static int mesh_abort_scan(enum connman_service_type type,
2830 struct connman_device *device)
2832 struct wifi_data *wifi = connman_device_get_data(device);
2833 struct wifi_mesh_info *mesh_info;
2837 if (!wifi || !wifi->mesh_interface)
2840 if (type != CONNMAN_SERVICE_TYPE_MESH)
2843 mesh_info = wifi->mesh_info;
2845 scanning = connman_device_get_scanning(device);
2849 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2850 abort_scan_callback, device);
2855 static int mesh_specific_scan(enum connman_service_type type,
2856 struct connman_device *device, const char *ssid,
2857 unsigned int freq, void *user_data)
2859 struct wifi_data *wifi = connman_device_get_data(device);
2860 GSupplicantScanParams *scan_params = NULL;
2861 struct wifi_mesh_info *mesh_info;
2862 struct scan_ssid *scan_ssid;
2866 if (!wifi || !wifi->mesh_interface)
2869 if (type != CONNMAN_SERVICE_TYPE_MESH)
2872 if (wifi->p2p_device)
2875 mesh_info = wifi->mesh_info;
2877 scanning = connman_device_get_scanning(device);
2881 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2885 scan_ssid = g_try_new(struct scan_ssid, 1);
2887 g_free(scan_params);
2891 scan_ssid->ssid_len = strlen(ssid);
2892 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2893 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2894 scan_params->num_ssids = 1;
2896 scan_params->freqs = g_try_new(uint16_t, 1);
2897 if (!scan_params->freqs) {
2898 g_slist_free_full(scan_params->ssids, g_free);
2899 g_free(scan_params);
2903 scan_params->freqs[0] = freq;
2904 scan_params->num_freqs = 1;
2906 reset_autoscan(device);
2907 connman_device_ref(device);
2909 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2910 mesh_scan_callback, device);
2913 connman_device_set_scanning(device,
2914 CONNMAN_SERVICE_TYPE_MESH, true);
2916 g_supplicant_free_scan_params(scan_params);
2917 connman_device_unref(device);
2925 * Note that the hidden scan is only used when connecting to this specific
2926 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2928 static int wifi_scan(enum connman_service_type type,
2929 struct connman_device *device,
2930 const char *ssid, unsigned int ssid_len,
2931 const char *identity, const char* passphrase,
2932 const char *security, void *user_data)
2934 struct wifi_data *wifi = connman_device_get_data(device);
2935 GSupplicantScanParams *scan_params = NULL;
2936 struct scan_ssid *scan_ssid;
2937 struct hidden_params *hidden;
2939 int driver_max_ssids = 0;
2946 if (wifi->p2p_device)
2949 if (wifi->tethering)
2952 if (type == CONNMAN_SERVICE_TYPE_P2P)
2953 return p2p_find(device);
2955 #if defined TIZEN_EXT_WIFI_MESH
2956 if (type == CONNMAN_SERVICE_TYPE_MESH)
2957 return mesh_scan(device);
2960 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2962 scanning = connman_device_get_scanning(device);
2964 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2968 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2970 DBG("max ssids %d", driver_max_ssids);
2971 if (driver_max_ssids == 0)
2972 return wifi_scan_simple(device);
2976 if (scanning && wifi->hidden && wifi->postpone_hidden)
2982 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2987 scan_ssid = g_try_new(struct scan_ssid, 1);
2989 g_free(scan_params);
2993 memcpy(scan_ssid->ssid, ssid, ssid_len);
2994 scan_ssid->ssid_len = ssid_len;
2995 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2997 scan_params->num_ssids = 1;
2999 hidden = g_try_new0(struct hidden_params, 1);
3001 g_supplicant_free_scan_params(scan_params);
3006 hidden_free(wifi->hidden);
3007 wifi->hidden = NULL;
3010 memcpy(hidden->ssid, ssid, ssid_len);
3011 hidden->ssid_len = ssid_len;
3012 hidden->identity = g_strdup(identity);
3013 hidden->passphrase = g_strdup(passphrase);
3014 hidden->security = g_strdup(security);
3015 hidden->user_data = user_data;
3016 wifi->hidden = hidden;
3019 /* Let's keep this active scan for later,
3020 * when current scan will be over. */
3021 wifi->postpone_hidden = TRUE;
3022 hidden->scan_params = scan_params;
3026 } else if (wifi->connected) {
3027 g_supplicant_free_scan_params(scan_params);
3028 return wifi_scan_simple(device);
3030 ret = get_latest_connections(driver_max_ssids, scan_params);
3032 g_supplicant_free_scan_params(scan_params);
3033 return wifi_scan_simple(device);
3037 connman_device_ref(device);
3039 reset_autoscan(device);
3041 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3042 scan_callback, device);
3045 connman_device_set_scanning(device,
3046 CONNMAN_SERVICE_TYPE_WIFI, true);
3047 #if defined TIZEN_EXT
3048 /*To allow the Full Scan after ssid based scan, set the flag here
3049 It is required because Tizen does not use the ConnMan specific
3050 backgroung Scan feature.Tizen has added the BG Scan feature in
3051 net-config. To sync with up ConnMan, we need to issue the Full Scan
3052 after SSID specific scan.*/
3053 wifi->allow_full_scan = TRUE;
3056 g_supplicant_free_scan_params(scan_params);
3057 connman_device_unref(device);
3060 hidden_free(wifi->hidden);
3061 wifi->hidden = NULL;
3068 static void wifi_regdom_callback(int result,
3072 struct connman_device *device = user_data;
3074 connman_device_regdom_notify(device, result, alpha2);
3076 connman_device_unref(device);
3079 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3081 struct wifi_data *wifi = connman_device_get_data(device);
3087 connman_device_ref(device);
3089 ret = g_supplicant_interface_set_country(wifi->interface,
3090 wifi_regdom_callback,
3093 connman_device_unref(device);
3098 static struct connman_device_driver wifi_ng_driver = {
3100 .type = CONNMAN_DEVICE_TYPE_WIFI,
3101 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3102 .probe = wifi_probe,
3103 .remove = wifi_remove,
3104 .enable = wifi_enable,
3105 .disable = wifi_disable,
3107 .set_regdom = wifi_set_regdom,
3108 #if defined TIZEN_EXT
3109 .specific_scan = wifi_specific_scan,
3111 #if defined TIZEN_EXT_WIFI_MESH
3112 .abort_scan = mesh_abort_scan,
3113 .mesh_specific_scan = mesh_specific_scan,
3117 static void system_ready(void)
3121 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3122 connman_error("Failed to register WiFi driver");
3125 static void system_killed(void)
3129 connman_device_driver_unregister(&wifi_ng_driver);
3132 static int network_probe(struct connman_network *network)
3134 DBG("network %p", network);
3139 static void network_remove(struct connman_network *network)
3141 struct connman_device *device = connman_network_get_device(network);
3142 struct wifi_data *wifi;
3144 DBG("network %p", network);
3146 wifi = connman_device_get_data(device);
3150 if (wifi->network != network)
3153 wifi->network = NULL;
3155 #if defined TIZEN_EXT
3156 wifi->disconnecting = false;
3158 if (wifi->pending_network == network)
3159 wifi->pending_network = NULL;
3161 if (wifi->scan_pending_network == network)
3162 wifi->scan_pending_network = NULL;
3166 static void connect_callback(int result, GSupplicantInterface *interface,
3169 #if defined TIZEN_EXT
3171 struct wifi_data *wifi;
3173 struct connman_network *network = user_data;
3175 DBG("network %p result %d", network, result);
3177 #if defined TIZEN_EXT
3178 set_connman_bssid(RESET_BSSID, NULL);
3180 for (list = iface_list; list; list = list->next) {
3183 if (wifi && wifi->network == network)
3187 /* wifi_data may be invalid because wifi is already disabled */
3192 if (result == -ENOKEY) {
3193 connman_network_set_error(network,
3194 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3195 } else if (result < 0) {
3196 connman_network_set_error(network,
3197 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3200 connman_network_unref(network);
3203 static GSupplicantSecurity network_security(const char *security)
3205 if (g_str_equal(security, "none"))
3206 return G_SUPPLICANT_SECURITY_NONE;
3207 else if (g_str_equal(security, "wep"))
3208 return G_SUPPLICANT_SECURITY_WEP;
3209 else if (g_str_equal(security, "psk"))
3210 return G_SUPPLICANT_SECURITY_PSK;
3211 else if (g_str_equal(security, "wpa"))
3212 return G_SUPPLICANT_SECURITY_PSK;
3213 else if (g_str_equal(security, "rsn"))
3214 return G_SUPPLICANT_SECURITY_PSK;
3215 else if (g_str_equal(security, "ieee8021x"))
3216 return G_SUPPLICANT_SECURITY_IEEE8021X;
3217 #if defined TIZEN_EXT
3218 else if (g_str_equal(security, "ft_psk") == TRUE)
3219 return G_SUPPLICANT_SECURITY_FT_PSK;
3220 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3221 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3224 return G_SUPPLICANT_SECURITY_UNKNOWN;
3227 #if defined TIZEN_EXT
3228 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3230 if (security == NULL)
3231 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3233 if (g_str_equal(security, "FT") == TRUE)
3234 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3235 else if (g_str_equal(security, "CCKM") == TRUE)
3236 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3238 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3242 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3244 const char *security;
3245 #if defined TIZEN_EXT
3246 const void *ssid_data;
3249 memset(ssid, 0, sizeof(*ssid));
3250 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3251 #if defined TIZEN_EXT
3252 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3254 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3259 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3261 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3264 ssid->scan_ssid = 1;
3265 security = connman_network_get_string(network, "WiFi.Security");
3266 ssid->security = network_security(security);
3267 ssid->passphrase = connman_network_get_string(network,
3269 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3272 * If our private key password is unset,
3273 * we use the supplied passphrase. That is needed
3274 * for PEAP where 2 passphrases (identity and client
3275 * cert may have to be provided.
3277 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3278 connman_network_set_string(network,
3279 "WiFi.PrivateKeyPassphrase",
3281 /* We must have an identity for both PEAP and TLS */
3282 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3284 /* Use agent provided identity as a fallback */
3285 if (!ssid->identity || strlen(ssid->identity) == 0)
3286 ssid->identity = connman_network_get_string(network,
3287 "WiFi.AgentIdentity");
3289 ssid->anonymous_identity = connman_network_get_string(network,
3290 "WiFi.AnonymousIdentity");
3291 ssid->ca_cert_path = connman_network_get_string(network,
3293 ssid->subject_match = connman_network_get_string(network,
3294 "WiFi.SubjectMatch");
3295 ssid->altsubject_match = connman_network_get_string(network,
3296 "WiFi.AltSubjectMatch");
3297 ssid->domain_suffix_match = connman_network_get_string(network,
3298 "WiFi.DomainSuffixMatch");
3299 ssid->domain_match = connman_network_get_string(network,
3300 "WiFi.DomainMatch");
3301 ssid->client_cert_path = connman_network_get_string(network,
3302 "WiFi.ClientCertFile");
3303 ssid->private_key_path = connman_network_get_string(network,
3304 "WiFi.PrivateKeyFile");
3305 ssid->private_key_passphrase = connman_network_get_string(network,
3306 "WiFi.PrivateKeyPassphrase");
3307 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3309 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3310 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3312 #if defined TIZEN_EXT
3313 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3314 if (bssid_list && g_slist_length(bssid_list) > 1) {
3316 char buff[MAC_ADDRESS_LENGTH];
3317 for (list = bssid_list; list; list = list->next) {
3318 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3320 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3321 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3322 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3323 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3325 char *last_bssid = connman_network_get_last_bssid(network);
3327 if (strcmp(last_bssid, buff) == 0) {
3328 DBG("last_bssid match, try next bssid");
3331 connman_network_set_last_bssid(network, buff);
3333 ssid->bssid = &(bssids->bssid[0]);
3338 ssid->bssid = connman_network_get_bssid(network);
3340 ssid->eap_keymgmt = network_eap_keymgmt(
3341 connman_network_get_string(network, "WiFi.KeymgmtType"));
3342 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3344 if(g_strcmp0(ssid->eap, "fast") == 0)
3345 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3347 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3348 ssid->bssid_for_connect_len = 6;
3349 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3350 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3351 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3352 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3353 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3355 ssid->freq = connman_network_get_frequency(network);
3359 if (connman_setting_get_bool("BackgroundScanning"))
3360 ssid->bgscan = BGSCAN_DEFAULT;
3363 static int network_connect(struct connman_network *network)
3365 struct connman_device *device = connman_network_get_device(network);
3366 struct wifi_data *wifi;
3367 GSupplicantInterface *interface;
3368 GSupplicantSSID *ssid;
3370 DBG("network %p", network);
3375 wifi = connman_device_get_data(device);
3379 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3383 interface = wifi->interface;
3385 ssid_init(ssid, network);
3387 if (wifi->disconnecting) {
3388 wifi->pending_network = network;
3389 #if defined TIZEN_EXT
3394 wifi->network = connman_network_ref(network);
3396 #if defined TIZEN_EXT
3397 wifi->scan_pending_network = NULL;
3400 return g_supplicant_interface_connect(interface, ssid,
3401 connect_callback, network);
3404 return -EINPROGRESS;
3407 static void disconnect_callback(int result, GSupplicantInterface *interface,
3410 #if defined TIZEN_EXT
3412 struct wifi_data *wifi;
3413 struct connman_network *network = user_data;
3415 DBG("network %p result %d", network, result);
3417 for (list = iface_list; list; list = list->next) {
3420 if (wifi->network == NULL && wifi->disconnecting == true)
3421 wifi->disconnecting = false;
3423 if (wifi->network == network)
3427 /* wifi_data may be invalid because wifi is already disabled */
3432 struct wifi_data *wifi = user_data;
3435 DBG("result %d supplicant interface %p wifi %p",
3436 result, interface, wifi);
3438 if (result == -ECONNABORTED) {
3439 DBG("wifi interface no longer available");
3443 if (wifi->network) {
3444 connman_network_set_connected(wifi->network, false);
3445 wifi->network = NULL;
3448 wifi->disconnecting = false;
3449 wifi->connected = false;
3451 if (wifi->pending_network) {
3452 network_connect(wifi->pending_network);
3453 wifi->pending_network = NULL;
3456 start_autoscan(wifi->device);
3459 static int network_disconnect(struct connman_network *network)
3461 struct connman_device *device = connman_network_get_device(network);
3462 struct wifi_data *wifi;
3464 #if defined TIZEN_EXT
3465 struct connman_service *service;
3468 DBG("network %p", network);
3470 wifi = connman_device_get_data(device);
3471 if (!wifi || !wifi->interface)
3474 #if defined TIZEN_EXT
3475 if (connman_network_get_associating(network) == true) {
3476 connman_network_clear_associating(network);
3477 connman_network_set_bool(network, "WiFi.UseWPS", false);
3479 service = connman_service_lookup_from_network(network);
3481 if (service != NULL &&
3482 (__connman_service_is_connected_state(service,
3483 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3484 __connman_service_is_connected_state(service,
3485 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3486 (connman_service_get_favorite(service) == false))
3487 __connman_service_set_passphrase(service, NULL);
3490 if (wifi->pending_network == network)
3491 wifi->pending_network = NULL;
3493 if (wifi->scan_pending_network == network)
3494 wifi->scan_pending_network = NULL;
3497 connman_network_set_associating(network, false);
3499 if (wifi->disconnecting)
3502 wifi->disconnecting = true;
3504 #if defined TIZEN_EXT
3505 err = g_supplicant_interface_disconnect(wifi->interface,
3506 disconnect_callback, network);
3508 err = g_supplicant_interface_disconnect(wifi->interface,
3509 disconnect_callback, wifi);
3513 wifi->disconnecting = false;
3518 #if defined TIZEN_EXT
3519 static void set_connection_mode(struct connman_network *network,
3522 ieee80211_modes_e phy_mode;
3523 connection_mode_e conn_mode;
3525 phy_mode = connman_network_get_phy_mode(network);
3527 case IEEE80211_MODE_B:
3528 if (linkspeed > 0 && linkspeed <= 11)
3529 conn_mode = CONNECTION_MODE_IEEE80211B;
3531 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3534 case IEEE80211_MODE_BG:
3535 if (linkspeed > 0 && linkspeed <= 11)
3536 conn_mode = CONNECTION_MODE_IEEE80211B;
3537 else if (linkspeed > 11 && linkspeed <= 54)
3538 conn_mode = CONNECTION_MODE_IEEE80211G;
3540 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3543 case IEEE80211_MODE_BGN:
3544 if (linkspeed > 0 && linkspeed <= 11)
3545 conn_mode = CONNECTION_MODE_IEEE80211B;
3546 else if (linkspeed > 11 && linkspeed <= 54)
3547 conn_mode = CONNECTION_MODE_IEEE80211G;
3548 else if (linkspeed > 54 && linkspeed <= 450)
3549 conn_mode = CONNECTION_MODE_IEEE80211N;
3551 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3554 case IEEE80211_MODE_A:
3555 if (linkspeed > 0 && linkspeed <= 54)
3556 conn_mode = CONNECTION_MODE_IEEE80211A;
3558 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3561 case IEEE80211_MODE_AN:
3562 if (linkspeed > 0 && linkspeed <= 54)
3563 conn_mode = CONNECTION_MODE_IEEE80211A;
3564 else if (linkspeed > 54 && linkspeed <= 450)
3565 conn_mode = CONNECTION_MODE_IEEE80211N;
3567 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3570 case IEEE80211_MODE_ANAC:
3571 if (linkspeed > 0 && linkspeed <= 54)
3572 conn_mode = CONNECTION_MODE_IEEE80211A;
3573 else if (linkspeed > 54 && linkspeed <= 450)
3574 conn_mode = CONNECTION_MODE_IEEE80211N;
3575 else if (linkspeed > 450 && linkspeed <= 1300)
3576 conn_mode = CONNECTION_MODE_IEEE80211AC;
3578 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3582 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3586 DBG("connection mode(%d)", conn_mode);
3587 connman_network_set_connection_mode(network, conn_mode);
3590 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3592 struct connman_network *network = user_data;
3595 DBG("Failed to get maxspeed from signalpoll !");
3599 DBG("maxspeed = %d", maxspeed);
3601 connman_network_set_maxspeed(network, maxspeed);
3602 set_connection_mode(network, maxspeed);
3606 static int network_signalpoll(struct wifi_data *wifi)
3608 GSupplicantInterface *interface;
3609 struct connman_network *network;
3611 if (!wifi || !wifi->network)
3614 interface = wifi->interface;
3615 network = wifi->network;
3617 DBG("network %p", network);
3619 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3622 static gboolean autosignalpoll_timeout(gpointer data)
3624 struct wifi_data *wifi = data;
3626 if (!wifi || !wifi->automaxspeed_timeout) {
3627 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3631 int ret = network_signalpoll(wifi);
3633 DBG("Fail to get max speed !!");
3634 wifi->automaxspeed_timeout = 0;
3642 static struct connman_network_driver network_driver = {
3644 .type = CONNMAN_NETWORK_TYPE_WIFI,
3645 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3646 .probe = network_probe,
3647 .remove = network_remove,
3648 .connect = network_connect,
3649 .disconnect = network_disconnect,
3652 static void interface_added(GSupplicantInterface *interface)
3654 const char *ifname = g_supplicant_interface_get_ifname(interface);
3655 const char *driver = g_supplicant_interface_get_driver(interface);
3656 #if defined TIZEN_EXT
3657 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3660 struct wifi_data *wifi;
3662 wifi = g_supplicant_interface_get_data(interface);
3664 wifi = get_pending_wifi_data(ifname);
3668 wifi->interface = interface;
3669 g_supplicant_interface_set_data(interface, wifi);
3670 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3671 wifi->p2p_device = true;
3674 DBG("ifname %s driver %s wifi %p tethering %d",
3675 ifname, driver, wifi, wifi->tethering);
3677 if (!wifi->device) {
3678 connman_error("WiFi device not set");
3682 connman_device_set_powered(wifi->device, true);
3683 #if defined TIZEN_EXT
3684 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3688 static bool is_idle(struct wifi_data *wifi)
3690 DBG("state %d", wifi->state);
3692 switch (wifi->state) {
3693 case G_SUPPLICANT_STATE_UNKNOWN:
3694 case G_SUPPLICANT_STATE_DISABLED:
3695 case G_SUPPLICANT_STATE_DISCONNECTED:
3696 case G_SUPPLICANT_STATE_INACTIVE:
3697 case G_SUPPLICANT_STATE_SCANNING:
3700 case G_SUPPLICANT_STATE_AUTHENTICATING:
3701 case G_SUPPLICANT_STATE_ASSOCIATING:
3702 case G_SUPPLICANT_STATE_ASSOCIATED:
3703 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3704 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3705 case G_SUPPLICANT_STATE_COMPLETED:
3712 static bool is_idle_wps(GSupplicantInterface *interface,
3713 struct wifi_data *wifi)
3715 /* First, let's check if WPS processing did not went wrong */
3716 if (g_supplicant_interface_get_wps_state(interface) ==
3717 G_SUPPLICANT_WPS_STATE_FAIL)
3720 /* Unlike normal connection, being associated while processing wps
3721 * actually means that we are idling. */
3722 switch (wifi->state) {
3723 case G_SUPPLICANT_STATE_UNKNOWN:
3724 case G_SUPPLICANT_STATE_DISABLED:
3725 case G_SUPPLICANT_STATE_DISCONNECTED:
3726 case G_SUPPLICANT_STATE_INACTIVE:
3727 case G_SUPPLICANT_STATE_SCANNING:
3728 case G_SUPPLICANT_STATE_ASSOCIATED:
3730 case G_SUPPLICANT_STATE_AUTHENTICATING:
3731 case G_SUPPLICANT_STATE_ASSOCIATING:
3732 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3733 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3734 case G_SUPPLICANT_STATE_COMPLETED:
3741 static bool handle_wps_completion(GSupplicantInterface *interface,
3742 struct connman_network *network,
3743 struct connman_device *device,
3744 struct wifi_data *wifi)
3748 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3750 const unsigned char *ssid, *wps_ssid;
3751 unsigned int ssid_len, wps_ssid_len;
3752 const char *wps_key;
3754 /* Checking if we got associated with requested
3756 ssid = connman_network_get_blob(network, "WiFi.SSID",
3759 wps_ssid = g_supplicant_interface_get_wps_ssid(
3760 interface, &wps_ssid_len);
3762 if (!wps_ssid || wps_ssid_len != ssid_len ||
3763 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3764 connman_network_set_associating(network, false);
3765 #if defined TIZEN_EXT
3766 g_supplicant_interface_disconnect(wifi->interface,
3767 disconnect_callback, wifi->network);
3769 connman_network_set_bool(network, "WiFi.UseWPS", false);
3770 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3772 g_supplicant_interface_disconnect(wifi->interface,
3773 disconnect_callback, wifi);
3778 wps_key = g_supplicant_interface_get_wps_key(interface);
3779 #if defined TIZEN_EXT
3780 /* Check the passphrase and encrypt it
3783 gchar *passphrase = g_strdup(wps_key);
3785 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3787 if (check_passphrase_ext(network, passphrase) < 0) {
3788 DBG("[WPS] Invalid passphrase");
3793 ret = send_encryption_request(passphrase, network);
3798 DBG("[WPS] Encryption request succeeded");
3800 DBG("[WPS] Encryption request failed %d", ret);
3803 connman_network_set_string(network, "WiFi.Passphrase",
3806 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3813 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3814 struct wifi_data *wifi)
3816 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3817 #if defined TIZEN_EXT
3818 wifi->assoc_code > 0 &&
3820 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3822 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3823 wifi->load_shaping_retries ++;
3826 wifi->load_shaping_retries = 0;
3830 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3831 struct connman_network *network,
3832 struct wifi_data *wifi)
3834 #if defined TIZEN_EXT
3835 const char *security;
3836 struct connman_service *service;
3838 if (wifi->connected)
3841 security = connman_network_get_string(network, "WiFi.Security");
3843 if (security && g_str_equal(security, "ieee8021x") == true &&
3844 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3846 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3851 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3854 struct connman_service *service;
3856 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3859 if (wifi->connected)
3863 service = connman_service_lookup_from_network(network);
3869 if (connman_service_get_favorite(service)) {
3870 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3875 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3880 #if defined TIZEN_EXT
3881 static bool handle_wifi_assoc_retry(struct connman_network *network,
3882 struct wifi_data *wifi)
3884 const char *security;
3886 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3887 connman_network_get_connecting(network) != true) {
3888 wifi->assoc_retry_count = 0;
3892 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3893 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3894 wifi->assoc_retry_count = 0;
3898 security = connman_network_get_string(network, "WiFi.Security");
3899 if (security && g_str_equal(security, "ieee8021x") == true &&
3900 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3901 wifi->assoc_retry_count = 0;
3905 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3906 wifi->assoc_retry_count = 0;
3908 /* Honestly it's not an invalid-key error,
3909 * however QA team recommends that the invalid-key error
3910 * might be better to display for user experience.
3912 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3921 static void interface_state(GSupplicantInterface *interface)
3923 struct connman_network *network;
3924 struct connman_device *device;
3925 struct wifi_data *wifi;
3926 GSupplicantState state = g_supplicant_interface_get_state(interface);
3930 wifi = g_supplicant_interface_get_data(interface);
3932 DBG("wifi %p interface state %d", wifi, state);
3937 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3938 if (wifi->tethering_param) {
3939 g_free(wifi->tethering_param->ssid);
3940 g_free(wifi->tethering_param);
3941 wifi->tethering_param = NULL;
3945 device = wifi->device;
3949 if (g_supplicant_interface_get_ready(interface) &&
3950 !wifi->interface_ready) {
3951 wifi->interface_ready = true;
3952 finalize_interface_creation(wifi);
3955 network = wifi->network;
3960 case G_SUPPLICANT_STATE_SCANNING:
3961 if (wifi->connected)
3962 connman_network_set_connected(network, false);
3966 case G_SUPPLICANT_STATE_AUTHENTICATING:
3967 case G_SUPPLICANT_STATE_ASSOCIATING:
3968 #if defined TIZEN_EXT
3969 reset_autoscan(device);
3971 stop_autoscan(device);
3974 if (!wifi->connected)
3975 connman_network_set_associating(network, true);
3979 case G_SUPPLICANT_STATE_COMPLETED:
3980 #if defined TIZEN_EXT
3981 /* though it should be already reset: */
3982 reset_autoscan(device);
3984 wifi->assoc_retry_count = 0;
3986 wifi->scan_pending_network = NULL;
3988 /* should be cleared scanning flag */
3989 bool scanning = connman_device_get_scanning(device);
3991 connman_device_set_scanning(device,
3992 CONNMAN_SERVICE_TYPE_WIFI, false);
3993 connman_device_unref(device);
3996 if (!wifi->automaxspeed_timeout) {
3997 DBG("Going to start signalpoll timer!!");
3998 int ret = network_signalpoll(wifi);
4000 DBG("Fail to get max speed !!");
4002 wifi->automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, wifi);
4005 /* though it should be already stopped: */
4006 stop_autoscan(device);
4009 if (!handle_wps_completion(interface, network, device, wifi))
4012 connman_network_set_connected(network, true);
4014 wifi->disconnect_code = 0;
4015 wifi->assoc_code = 0;
4016 wifi->load_shaping_retries = 0;
4019 case G_SUPPLICANT_STATE_DISCONNECTED:
4020 #if defined TIZEN_EXT
4021 connman_network_set_maxspeed(network, 0);
4023 if (wifi->automaxspeed_timeout != 0) {
4024 g_source_remove(wifi->automaxspeed_timeout);
4025 wifi->automaxspeed_timeout = 0;
4026 DBG("Remove signalpoll timer!!");
4030 * If we're in one of the idle modes, we have
4031 * not started association yet and thus setting
4032 * those ones to FALSE could cancel an association
4035 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4037 if (is_idle_wps(interface, wifi))
4043 #if defined TIZEN_EXT
4044 if (handle_assoc_status_code(interface, wifi)) {
4045 network_connect(network);
4049 if (handle_assoc_status_code(interface, wifi))
4053 /* If previous state was 4way-handshake, then
4054 * it's either: psk was incorrect and thus we retry
4055 * or if we reach the maximum retries we declare the
4057 if (handle_4way_handshake_failure(interface,
4061 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4062 switch (wifi->disconnect_code) {
4063 case 1: /* Unspecified reason */
4064 /* Let's assume it's because we got blocked */
4066 case 6: /* Class 2 frame received from nonauthenticated STA */
4067 connman_network_set_error(network,
4068 CONNMAN_NETWORK_ERROR_BLOCKED);
4075 #if defined TIZEN_EXT
4076 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4077 * Retry association until its retry count is expired */
4078 if (handle_wifi_assoc_retry(network, wifi) == true) {
4079 throw_wifi_scan(wifi->device, scan_callback);
4080 wifi->scan_pending_network = wifi->network;
4084 if(wifi->disconnect_code > 0){
4085 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4086 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4090 connman_network_set_connected(network, false);
4091 connman_network_set_associating(network, false);
4092 wifi->disconnecting = false;
4094 start_autoscan(device);
4098 case G_SUPPLICANT_STATE_INACTIVE:
4099 #if defined TIZEN_EXT
4100 if (handle_wps_completion(interface, network, device, wifi) == false)
4103 connman_network_set_associating(network, false);
4104 start_autoscan(device);
4108 case G_SUPPLICANT_STATE_UNKNOWN:
4109 case G_SUPPLICANT_STATE_DISABLED:
4110 case G_SUPPLICANT_STATE_ASSOCIATED:
4111 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4112 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4116 old_connected = wifi->connected;
4117 wifi->state = state;
4119 /* Saving wpa_s state policy:
4120 * If connected and if the state changes are roaming related:
4121 * --> We stay connected
4123 * --> We are connected
4125 * --> We are not connected
4128 case G_SUPPLICANT_STATE_AUTHENTICATING:
4129 case G_SUPPLICANT_STATE_ASSOCIATING:
4130 case G_SUPPLICANT_STATE_ASSOCIATED:
4131 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4132 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4133 if (wifi->connected)
4134 connman_warn("Probably roaming right now!"
4135 " Staying connected...");
4137 case G_SUPPLICANT_STATE_SCANNING:
4138 wifi->connected = false;
4141 start_autoscan(device);
4143 case G_SUPPLICANT_STATE_COMPLETED:
4144 wifi->connected = true;
4147 wifi->connected = false;
4154 static void interface_removed(GSupplicantInterface *interface)
4156 const char *ifname = g_supplicant_interface_get_ifname(interface);
4157 struct wifi_data *wifi;
4159 DBG("ifname %s", ifname);
4161 wifi = g_supplicant_interface_get_data(interface);
4163 #if defined TIZEN_EXT_WIFI_MESH
4164 if (wifi && wifi->mesh_interface) {
4165 DBG("Notify mesh interface remove");
4166 connman_mesh_notify_interface_remove(true);
4167 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4168 g_free(mesh_info->parent_ifname);
4169 g_free(mesh_info->ifname);
4170 g_free(mesh_info->identifier);
4172 wifi->mesh_interface = false;
4173 wifi->mesh_info = NULL;
4179 wifi->interface = NULL;
4181 if (wifi && wifi->tethering)
4184 if (!wifi || !wifi->device) {
4185 DBG("wifi interface already removed");
4189 connman_device_set_powered(wifi->device, false);
4191 check_p2p_technology();
4192 #if defined TIZEN_EXT_WIFI_MESH
4193 check_mesh_technology();
4197 static void set_device_type(const char *type, char dev_type[17])
4199 const char *oui = "0050F204";
4200 const char *category = "0001";
4201 const char *sub_category = "0000";
4203 if (!g_strcmp0(type, "handset")) {
4205 sub_category = "0005";
4206 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4207 sub_category = "0001";
4208 else if (!g_strcmp0(type, "server"))
4209 sub_category = "0002";
4210 else if (!g_strcmp0(type, "laptop"))
4211 sub_category = "0005";
4212 else if (!g_strcmp0(type, "desktop"))
4213 sub_category = "0006";
4214 else if (!g_strcmp0(type, "tablet"))
4215 sub_category = "0009";
4216 else if (!g_strcmp0(type, "watch"))
4219 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4222 static void p2p_support(GSupplicantInterface *interface)
4224 char dev_type[17] = {};
4225 const char *hostname;
4232 if (!g_supplicant_interface_has_p2p(interface))
4235 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4236 DBG("Could not register P2P technology driver");
4240 hostname = connman_utsname_get_hostname();
4242 hostname = "ConnMan";
4244 set_device_type(connman_machine_get_type(), dev_type);
4245 g_supplicant_interface_set_p2p_device_config(interface,
4246 hostname, dev_type);
4247 connman_peer_driver_register(&peer_driver);
4250 static void scan_started(GSupplicantInterface *interface)
4255 static void scan_finished(GSupplicantInterface *interface)
4257 #if defined TIZEN_EXT
4258 struct wifi_data *wifi;
4259 bool is_associating = false;
4260 static bool is_scanning = true;
4265 #if defined TIZEN_EXT
4266 wifi = g_supplicant_interface_get_data(interface);
4267 if (wifi && wifi->scan_pending_network) {
4268 network_connect(wifi->scan_pending_network);
4269 wifi->scan_pending_network = NULL;
4272 //service state - associating
4273 if(!wifi || !wifi->network)
4276 is_associating = connman_network_get_associating(wifi->network);
4277 if(is_associating && is_scanning){
4278 is_scanning = false;
4279 DBG("send scan for connecting");
4280 throw_wifi_scan(wifi->device, scan_callback);
4291 static void ap_create_fail(GSupplicantInterface *interface)
4293 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4296 if ((wifi->tethering) && (wifi->tethering_param)) {
4297 DBG("%s create AP fail \n",
4298 g_supplicant_interface_get_ifname(wifi->interface));
4300 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4301 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4302 wifi->tethering = false;
4304 ret = tech_set_tethering(wifi->tethering_param->technology,
4305 wifi->tethering_param->ssid->ssid,
4306 wifi->tethering_param->ssid->passphrase,
4307 wifi->bridge, true);
4309 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4310 connman_technology_tethering_notify(wifi_technology,false);
4313 g_free(wifi->tethering_param->ssid);
4314 g_free(wifi->tethering_param);
4315 wifi->tethering_param = NULL;
4321 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4323 unsigned char strength;
4325 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4327 #if !defined TIZEN_EXT
4334 #if defined TIZEN_EXT_WIFI_MESH
4335 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4337 GSupplicantInterface *interface;
4338 struct wifi_data *wifi;
4339 const char *name, *security;
4340 struct connman_mesh *connman_mesh;
4341 struct wifi_mesh_info *mesh_info;
4342 const unsigned char *bssid;
4343 const char *identifier;
4348 interface = g_supplicant_network_get_interface(supplicant_network);
4349 wifi = g_supplicant_interface_get_data(interface);
4350 if (!wifi || !wifi->mesh_interface) {
4351 DBG("Virtual Mesh interface not created");
4355 bssid = g_supplicant_network_get_bssid(supplicant_network);
4356 address = g_malloc0(19);
4357 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4358 bssid[2], bssid[3], bssid[4], bssid[5]);
4360 identifier = g_supplicant_network_get_identifier(supplicant_network);
4361 name = g_supplicant_network_get_name(supplicant_network);
4362 security = g_supplicant_network_get_security(supplicant_network);
4363 frequency = g_supplicant_network_get_frequency(supplicant_network);
4365 mesh_info = wifi->mesh_info;
4366 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4370 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4372 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4373 connman_mesh_set_name(connman_mesh, name);
4374 connman_mesh_set_security(connman_mesh, security);
4375 connman_mesh_set_frequency(connman_mesh, frequency);
4376 connman_mesh_set_address(connman_mesh, address);
4377 connman_mesh_set_index(connman_mesh, mesh_info->index);
4378 connman_mesh_set_strength(connman_mesh,
4379 calculate_strength(supplicant_network));
4380 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4382 ret = connman_mesh_register(connman_mesh);
4383 if (ret == -EALREADY)
4384 DBG("Mesh Peer is already registered");
4390 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4392 GSupplicantInterface *interface;
4393 struct wifi_data *wifi;
4394 struct connman_mesh *connman_mesh;
4395 struct wifi_mesh_info *mesh_info;
4396 const char *identifier;
4398 interface = g_supplicant_network_get_interface(supplicant_network);
4399 wifi = g_supplicant_interface_get_data(interface);
4400 if (!wifi || !wifi->mesh_interface) {
4401 DBG("Virtual Mesh interface not created");
4405 identifier = g_supplicant_network_get_identifier(supplicant_network);
4407 DBG("Failed to get Mesh Peer identifier");
4411 mesh_info = wifi->mesh_info;
4412 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4414 /* Do not unregister connected mesh peer */
4415 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4416 DBG("Mesh Peer %s is connected", identifier);
4419 DBG("Mesh Peer identifier %s removed", identifier);
4420 connman_mesh_unregister(connman_mesh);
4425 static void network_added(GSupplicantNetwork *supplicant_network)
4427 struct connman_network *network;
4428 GSupplicantInterface *interface;
4429 struct wifi_data *wifi;
4430 const char *name, *identifier, *security, *group, *mode;
4431 const unsigned char *ssid;
4432 unsigned int ssid_len;
4436 bool wps_advertizing;
4438 #if defined TIZEN_EXT
4439 GSList *vsie_list = NULL;
4440 const unsigned char *country_code;
4441 ieee80211_modes_e phy_mode;
4444 mode = g_supplicant_network_get_mode(supplicant_network);
4445 identifier = g_supplicant_network_get_identifier(supplicant_network);
4447 DBG("%s", identifier);
4449 if (!g_strcmp0(mode, "adhoc"))
4452 #if defined TIZEN_EXT_WIFI_MESH
4453 if (!g_strcmp0(mode, "mesh")) {
4454 mesh_peer_added(supplicant_network);
4459 interface = g_supplicant_network_get_interface(supplicant_network);
4460 wifi = g_supplicant_interface_get_data(interface);
4461 name = g_supplicant_network_get_name(supplicant_network);
4462 security = g_supplicant_network_get_security(supplicant_network);
4463 group = g_supplicant_network_get_identifier(supplicant_network);
4464 wps = g_supplicant_network_get_wps(supplicant_network);
4465 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4466 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4467 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4468 supplicant_network);
4473 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4475 network = connman_device_get_network(wifi->device, identifier);
4478 network = connman_network_create(identifier,
4479 CONNMAN_NETWORK_TYPE_WIFI);
4483 connman_network_set_index(network, wifi->index);
4485 if (connman_device_add_network(wifi->device, network) < 0) {
4486 connman_network_unref(network);
4490 wifi->networks = g_slist_prepend(wifi->networks, network);
4493 if (name && name[0] != '\0')
4494 connman_network_set_name(network, name);
4496 connman_network_set_blob(network, "WiFi.SSID",
4498 #if defined TIZEN_EXT
4499 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4501 connman_network_set_vsie_list(network, vsie_list);
4503 DBG("vsie_list is NULL");
4504 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4505 connman_network_set_countrycode(network, country_code);
4506 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4507 connman_network_set_phy_mode(network, phy_mode);
4509 connman_network_set_string(network, "WiFi.Security", security);
4510 connman_network_set_strength(network,
4511 calculate_strength(supplicant_network));
4512 connman_network_set_bool(network, "WiFi.WPS", wps);
4515 /* Is AP advertizing for WPS association?
4516 * If so, we decide to use WPS by default */
4517 if (wps_ready && wps_pbc &&
4519 #if !defined TIZEN_EXT
4520 connman_network_set_bool(network, "WiFi.UseWPS", true);
4522 DBG("wps is activating by ap but ignore it.");
4527 connman_network_set_frequency(network,
4528 g_supplicant_network_get_frequency(supplicant_network));
4529 #if defined TIZEN_EXT
4530 connman_network_set_bssid(network,
4531 g_supplicant_network_get_bssid(supplicant_network));
4532 connman_network_set_maxrate(network,
4533 g_supplicant_network_get_maxrate(supplicant_network));
4534 connman_network_set_enc_mode(network,
4535 g_supplicant_network_get_enc_mode(supplicant_network));
4536 connman_network_set_rsn_mode(network,
4537 g_supplicant_network_get_rsn_mode(supplicant_network));
4538 connman_network_set_keymgmt(network,
4539 g_supplicant_network_get_keymgmt(supplicant_network));
4540 connman_network_set_bool(network, "WiFi.HS20AP",
4541 g_supplicant_network_is_hs20AP(supplicant_network));
4542 connman_network_set_bssid_list(network,
4543 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4545 connman_network_set_available(network, true);
4546 connman_network_set_string(network, "WiFi.Mode", mode);
4548 #if defined TIZEN_EXT
4553 connman_network_set_group(network, group);
4555 #if defined TIZEN_EXT
4556 if (wifi_first_scan == true)
4557 found_with_first_scan = true;
4560 if (wifi->hidden && ssid) {
4561 #if defined TIZEN_EXT
4562 if (network_security(wifi->hidden->security) ==
4563 network_security(security) &&
4565 if (!g_strcmp0(wifi->hidden->security, security) &&
4567 wifi->hidden->ssid_len == ssid_len &&
4568 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4569 connman_network_connect_hidden(network,
4570 wifi->hidden->identity,
4571 wifi->hidden->passphrase,
4572 wifi->hidden->user_data);
4573 wifi->hidden->user_data = NULL;
4574 hidden_free(wifi->hidden);
4575 wifi->hidden = NULL;
4580 static void network_removed(GSupplicantNetwork *network)
4582 GSupplicantInterface *interface;
4583 struct wifi_data *wifi;
4584 const char *name, *identifier;
4585 struct connman_network *connman_network;
4587 #if defined TIZEN_EXT_WIFI_MESH
4589 mode = g_supplicant_network_get_mode(network);
4590 if (!g_strcmp0(mode, "mesh")) {
4591 mesh_peer_removed(network);
4596 interface = g_supplicant_network_get_interface(network);
4597 wifi = g_supplicant_interface_get_data(interface);
4598 identifier = g_supplicant_network_get_identifier(network);
4599 name = g_supplicant_network_get_name(network);
4601 DBG("name %s", name);
4606 connman_network = connman_device_get_network(wifi->device, identifier);
4607 if (!connman_network)
4610 #if defined TIZEN_EXT
4611 if (connman_network == wifi->scan_pending_network)
4612 wifi->scan_pending_network = NULL;
4614 if (connman_network == wifi->pending_network)
4615 wifi->pending_network = NULL;
4617 if(connman_network_get_connecting(connman_network) == true){
4618 connman_network_set_connected(connman_network, false);
4622 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4624 connman_device_remove_network(wifi->device, connman_network);
4625 connman_network_unref(connman_network);
4628 static void network_changed(GSupplicantNetwork *network, const char *property)
4630 GSupplicantInterface *interface;
4631 struct wifi_data *wifi;
4632 const char *name, *identifier;
4633 struct connman_network *connman_network;
4635 #if defined TIZEN_EXT
4636 const unsigned char *bssid;
4637 unsigned int maxrate;
4640 const unsigned char *country_code;
4641 ieee80211_modes_e phy_mode;
4645 interface = g_supplicant_network_get_interface(network);
4646 wifi = g_supplicant_interface_get_data(interface);
4647 identifier = g_supplicant_network_get_identifier(network);
4648 name = g_supplicant_network_get_name(network);
4650 DBG("name %s", name);
4655 connman_network = connman_device_get_network(wifi->device, identifier);
4656 if (!connman_network)
4659 if (g_str_equal(property, "Signal")) {
4660 connman_network_set_strength(connman_network,
4661 calculate_strength(network));
4662 connman_network_update(connman_network);
4665 #if defined TIZEN_EXT
4666 bssid = g_supplicant_network_get_bssid(network);
4667 maxrate = g_supplicant_network_get_maxrate(network);
4668 frequency = g_supplicant_network_get_frequency(network);
4669 wps = g_supplicant_network_get_wps(network);
4670 phy_mode = g_supplicant_network_get_phy_mode(network);
4672 connman_network_set_bssid(connman_network, bssid);
4673 connman_network_set_maxrate(connman_network, maxrate);
4674 connman_network_set_frequency(connman_network, frequency);
4675 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4676 country_code = g_supplicant_network_get_countrycode(network);
4677 connman_network_set_countrycode(connman_network, country_code);
4678 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4679 connman_network_set_bssid_list(connman_network, bssid_list);
4680 connman_network_set_phy_mode(connman_network, phy_mode);
4682 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4683 connman_network_get_associating(connman_network))
4684 network_connect(connman_network);
4688 static void network_associated(GSupplicantNetwork *network)
4690 GSupplicantInterface *interface;
4691 struct wifi_data *wifi;
4692 struct connman_network *connman_network;
4693 const char *identifier;
4697 interface = g_supplicant_network_get_interface(network);
4701 wifi = g_supplicant_interface_get_data(interface);
4705 identifier = g_supplicant_network_get_identifier(network);
4707 connman_network = connman_device_get_network(wifi->device, identifier);
4708 if (!connman_network)
4711 if (wifi->network) {
4712 if (wifi->network == connman_network)
4716 * This should never happen, we got associated with
4717 * a network different than the one we were expecting.
4719 DBG("Associated to %p while expecting %p",
4720 connman_network, wifi->network);
4722 connman_network_set_associating(wifi->network, false);
4725 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4727 wifi->network = connman_network_ref(connman_network);
4731 * Interface state changes callback (interface_state) is always
4732 * called before network_associated callback thus we need to call
4733 * interface_state again in order to process the new state now that
4734 * we have the network properly set.
4736 interface_state(interface);
4739 static void apply_peer_services(GSupplicantPeer *peer,
4740 struct connman_peer *connman_peer)
4742 const unsigned char *data;
4747 connman_peer_reset_services(connman_peer);
4749 data = g_supplicant_peer_get_widi_ies(peer, &length);
4751 connman_peer_add_service(connman_peer,
4752 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4756 static void add_station(const char *mac)
4758 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4762 static void remove_station(const char *mac)
4764 connman_technology_tethering_remove_station(mac);
4767 static void peer_found(GSupplicantPeer *peer)
4769 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4770 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4771 struct connman_peer *connman_peer;
4772 const char *identifier, *name;
4774 #if defined TIZEN_EXT
4778 identifier = g_supplicant_peer_get_identifier(peer);
4779 name = g_supplicant_peer_get_name(peer);
4781 DBG("ident: %s", identifier);
4783 connman_peer = connman_peer_get(wifi->device, identifier);
4787 connman_peer = connman_peer_create(identifier);
4788 connman_peer_set_name(connman_peer, name);
4789 connman_peer_set_device(connman_peer, wifi->device);
4790 apply_peer_services(peer, connman_peer);
4792 ret = connman_peer_register(connman_peer);
4793 if (ret < 0 && ret != -EALREADY)
4794 connman_peer_unref(connman_peer);
4796 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4799 static void peer_lost(GSupplicantPeer *peer)
4801 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4802 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4803 struct connman_peer *connman_peer;
4804 const char *identifier;
4809 identifier = g_supplicant_peer_get_identifier(peer);
4811 DBG("ident: %s", identifier);
4813 connman_peer = connman_peer_get(wifi->device, identifier);
4815 if (wifi->p2p_connecting &&
4816 wifi->pending_peer == connman_peer) {
4817 peer_connect_timeout(wifi);
4819 connman_peer_unregister(connman_peer);
4820 connman_peer_unref(connman_peer);
4823 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4826 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4828 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4829 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4830 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4831 struct connman_peer *connman_peer;
4832 const char *identifier;
4834 identifier = g_supplicant_peer_get_identifier(peer);
4836 DBG("ident: %s", identifier);
4841 connman_peer = connman_peer_get(wifi->device, identifier);
4846 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4847 apply_peer_services(peer, connman_peer);
4848 connman_peer_services_changed(connman_peer);
4850 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4851 if (!g_supplicant_peer_is_in_a_group(peer))
4852 p_state = CONNMAN_PEER_STATE_IDLE;
4854 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4856 case G_SUPPLICANT_PEER_GROUP_STARTED:
4858 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4859 p_state = CONNMAN_PEER_STATE_IDLE;
4861 case G_SUPPLICANT_PEER_GROUP_JOINED:
4862 connman_peer_set_iface_address(connman_peer,
4863 g_supplicant_peer_get_iface_address(peer));
4865 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4866 p_state = CONNMAN_PEER_STATE_IDLE;
4868 case G_SUPPLICANT_PEER_GROUP_FAILED:
4869 if (g_supplicant_peer_has_requested_connection(peer))
4870 p_state = CONNMAN_PEER_STATE_IDLE;
4872 p_state = CONNMAN_PEER_STATE_FAILURE;
4876 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4877 p_state == CONNMAN_PEER_STATE_FAILURE) {
4878 if (wifi->p2p_connecting
4879 && connman_peer == wifi->pending_peer)
4880 peer_cancel_timeout(wifi);
4882 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4885 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4888 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4889 GSupplicantInterface *g_iface;
4890 struct wifi_data *g_wifi;
4892 g_iface = g_supplicant_peer_get_group_interface(peer);
4896 g_wifi = g_supplicant_interface_get_data(g_iface);
4900 connman_peer_set_as_master(connman_peer,
4901 !g_supplicant_peer_is_client(peer));
4902 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4905 * If wpa_supplicant didn't create a dedicated p2p-group
4906 * interface then mark this interface as p2p_device to avoid
4907 * scan and auto-scan are launched on it while P2P is connected.
4909 if (!g_list_find(p2p_iface_list, g_wifi))
4910 wifi->p2p_device = true;
4913 connman_peer_set_state(connman_peer, p_state);
4916 static void peer_request(GSupplicantPeer *peer)
4918 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4919 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4920 struct connman_peer *connman_peer;
4921 const char *identifier;
4923 #if defined TIZEN_EXT
4928 identifier = g_supplicant_peer_get_identifier(peer);
4930 DBG("ident: %s", identifier);
4932 connman_peer = connman_peer_get(wifi->device, identifier);
4936 connman_peer_request_connection(connman_peer);
4939 #if defined TIZEN_EXT
4940 static void system_power_off(void)
4943 struct wifi_data *wifi;
4944 struct connman_service *service;
4945 struct connman_ipconfig *ipconfig_ipv4;
4947 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4948 for (list = iface_list; list; list = list->next) {
4951 if (wifi->network != NULL) {
4952 service = connman_service_lookup_from_network(wifi->network);
4953 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4954 __connman_dhcp_stop(ipconfig_ipv4);
4960 static void network_merged(GSupplicantNetwork *network)
4962 GSupplicantInterface *interface;
4963 GSupplicantState state;
4964 struct wifi_data *wifi;
4965 const char *identifier;
4966 struct connman_network *connman_network;
4970 interface = g_supplicant_network_get_interface(network);
4974 state = g_supplicant_interface_get_state(interface);
4975 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4978 wifi = g_supplicant_interface_get_data(interface);
4982 identifier = g_supplicant_network_get_identifier(network);
4984 connman_network = connman_device_get_network(wifi->device, identifier);
4985 if (!connman_network)
4988 DBG("merged identifier %s", identifier);
4990 if (wifi->connected == FALSE) {
4992 case G_SUPPLICANT_STATE_AUTHENTICATING:
4993 case G_SUPPLICANT_STATE_ASSOCIATING:
4994 case G_SUPPLICANT_STATE_ASSOCIATED:
4995 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4996 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4997 connman_network_set_associating(connman_network, TRUE);
4999 case G_SUPPLICANT_STATE_COMPLETED:
5000 connman_network_set_connected(connman_network, TRUE);
5003 DBG("Not handled the state : %d", state);
5008 ishs20AP = g_supplicant_network_is_hs20AP(network);
5011 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5012 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5013 connman_network_set_string(connman_network, "WiFi.EAP",
5015 connman_network_set_string(connman_network, "WiFi.Identity",
5016 g_supplicant_network_get_identity(network));
5017 connman_network_set_string(connman_network, "WiFi.Phase2",
5018 g_supplicant_network_get_phase2(network));
5023 wifi->network = connman_network;
5026 static void assoc_failed(void *user_data)
5028 struct connman_network *network = user_data;
5029 connman_network_set_associating(network, false);
5033 static void debug(const char *str)
5035 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5036 connman_debug("%s", str);
5039 static void disconnect_reasoncode(GSupplicantInterface *interface,
5042 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5045 wifi->disconnect_code = reasoncode;
5049 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5051 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5054 wifi->assoc_code = status_code;
5058 static const GSupplicantCallbacks callbacks = {
5059 .system_ready = system_ready,
5060 .system_killed = system_killed,
5061 .interface_added = interface_added,
5062 .interface_state = interface_state,
5063 .interface_removed = interface_removed,
5064 .p2p_support = p2p_support,
5065 .scan_started = scan_started,
5066 .scan_finished = scan_finished,
5067 .ap_create_fail = ap_create_fail,
5068 .network_added = network_added,
5069 .network_removed = network_removed,
5070 .network_changed = network_changed,
5071 .network_associated = network_associated,
5072 .add_station = add_station,
5073 .remove_station = remove_station,
5074 .peer_found = peer_found,
5075 .peer_lost = peer_lost,
5076 .peer_changed = peer_changed,
5077 .peer_request = peer_request,
5078 #if defined TIZEN_EXT
5079 .system_power_off = system_power_off,
5080 .network_merged = network_merged,
5081 .assoc_failed = assoc_failed,
5084 .disconnect_reasoncode = disconnect_reasoncode,
5085 .assoc_status_code = assoc_status_code,
5086 #if defined TIZEN_EXT_WIFI_MESH
5087 .mesh_support = mesh_support,
5088 .mesh_group_started = mesh_group_started,
5089 .mesh_group_removed = mesh_group_removed,
5090 .mesh_peer_connected = mesh_peer_connected,
5091 .mesh_peer_disconnected = mesh_peer_disconnected,
5096 static int tech_probe(struct connman_technology *technology)
5098 wifi_technology = technology;
5103 static void tech_remove(struct connman_technology *technology)
5105 wifi_technology = NULL;
5108 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5109 const char *passphrase)
5111 GSupplicantSSID *ap;
5113 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5117 ap->mode = G_SUPPLICANT_MODE_MASTER;
5118 #if defined TIZEN_EXT
5119 ap->ssid = (void *) ssid;
5123 ap->ssid_len = strlen(ssid);
5127 if (!passphrase || strlen(passphrase) == 0) {
5128 ap->security = G_SUPPLICANT_SECURITY_NONE;
5129 ap->passphrase = NULL;
5131 ap->security = G_SUPPLICANT_SECURITY_PSK;
5132 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5133 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5134 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5135 ap->passphrase = passphrase;
5141 static void ap_start_callback(int result, GSupplicantInterface *interface,
5144 struct wifi_tethering_info *info = user_data;
5146 DBG("result %d index %d bridge %s",
5147 result, info->wifi->index, info->wifi->bridge);
5149 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5150 connman_inet_remove_from_bridge(info->wifi->index,
5151 info->wifi->bridge);
5153 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5154 connman_technology_tethering_notify(info->technology, false);
5155 g_free(info->wifi->tethering_param->ssid);
5156 g_free(info->wifi->tethering_param);
5157 info->wifi->tethering_param = NULL;
5161 g_free(info->ifname);
5165 static void ap_create_callback(int result,
5166 GSupplicantInterface *interface,
5169 struct wifi_tethering_info *info = user_data;
5171 DBG("result %d ifname %s", result,
5172 g_supplicant_interface_get_ifname(interface));
5174 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5175 connman_inet_remove_from_bridge(info->wifi->index,
5176 info->wifi->bridge);
5178 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5179 connman_technology_tethering_notify(info->technology, false);
5180 g_free(info->wifi->tethering_param->ssid);
5181 g_free(info->wifi->tethering_param);
5182 info->wifi->tethering_param = NULL;
5186 g_free(info->ifname);
5192 info->wifi->interface = interface;
5193 g_supplicant_interface_set_data(interface, info->wifi);
5195 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5196 connman_error("Failed to set interface ap_scan property");
5198 g_supplicant_interface_connect(interface, info->ssid,
5199 ap_start_callback, info);
5202 static void sta_remove_callback(int result,
5203 GSupplicantInterface *interface,
5206 struct wifi_tethering_info *info = user_data;
5207 const char *driver = connman_option_get_string("wifi");
5209 DBG("ifname %s result %d ", info->ifname, result);
5211 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5212 info->wifi->tethering = false;
5213 connman_technology_tethering_notify(info->technology, false);
5215 g_free(info->ifname);
5219 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5220 g_free(info->wifi->tethering_param->ssid);
5221 g_free(info->wifi->tethering_param);
5222 info->wifi->tethering_param = NULL;
5227 info->wifi->interface = NULL;
5229 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5234 static int enable_wifi_tethering(struct connman_technology *technology,
5235 const char *bridge, const char *identifier,
5236 const char *passphrase, bool available)
5239 GSupplicantInterface *interface;
5240 struct wifi_data *wifi;
5241 struct wifi_tethering_info *info;
5246 for (list = iface_list; list; list = list->next) {
5249 DBG("wifi %p network %p pending_network %p", wifi,
5250 wifi->network, wifi->pending_network);
5252 interface = wifi->interface;
5257 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5260 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5262 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5263 DBG("%s does not support AP mode (detected)", ifname);
5267 mode = g_supplicant_interface_get_mode(interface);
5268 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5269 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5270 DBG("%s does not support AP mode (capability)", ifname);
5274 if (wifi->network && available)
5277 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5281 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5282 if (!wifi->tethering_param) {
5288 info->technology = technology;
5289 info->wifi->bridge = bridge;
5290 info->ssid = ssid_ap_init(identifier, passphrase);
5294 info->ifname = g_strdup(ifname);
5298 wifi->tethering_param->technology = technology;
5299 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5300 if (!wifi->tethering_param->ssid)
5303 info->wifi->tethering = true;
5304 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5306 berr = connman_technology_tethering_notify(technology, true);
5310 err = g_supplicant_interface_remove(interface,
5311 sta_remove_callback,
5314 DBG("tethering wifi %p ifname %s", wifi, ifname);
5319 g_free(info->ifname);
5322 g_free(wifi->tethering_param);
5323 wifi->tethering_param = NULL;
5326 * Remove bridge if it was correctly created but remove
5327 * operation failed. Instead, if bridge creation failed then
5328 * break out and do not try again on another interface,
5329 * bridge set-up does not depend on it.
5332 connman_technology_tethering_notify(technology, false);
5340 static int tech_set_tethering(struct connman_technology *technology,
5341 const char *identifier, const char *passphrase,
5342 const char *bridge, bool enabled)
5345 struct wifi_data *wifi;
5351 for (list = iface_list; list; list = list->next) {
5354 if (wifi->tethering) {
5355 wifi->tethering = false;
5357 connman_inet_remove_from_bridge(wifi->index,
5359 wifi->bridged = false;
5363 connman_technology_tethering_notify(technology, false);
5368 DBG("trying tethering for available devices");
5369 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5373 DBG("trying tethering for any device");
5374 err = enable_wifi_tethering(technology, bridge, identifier,
5381 static void regdom_callback(int result, const char *alpha2, void *user_data)
5385 if (!wifi_technology)
5391 connman_technology_regdom_notify(wifi_technology, alpha2);
5394 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5396 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5399 static struct connman_technology_driver tech_driver = {
5401 .type = CONNMAN_SERVICE_TYPE_WIFI,
5402 .probe = tech_probe,
5403 .remove = tech_remove,
5404 .set_tethering = tech_set_tethering,
5405 .set_regdom = tech_set_regdom,
5408 static int wifi_init(void)
5412 err = connman_network_driver_register(&network_driver);
5416 err = g_supplicant_register(&callbacks);
5418 connman_network_driver_unregister(&network_driver);
5422 err = connman_technology_driver_register(&tech_driver);
5424 g_supplicant_unregister(&callbacks);
5425 connman_network_driver_unregister(&network_driver);
5432 static void wifi_exit(void)
5436 connman_technology_driver_unregister(&tech_driver);
5438 g_supplicant_unregister(&callbacks);
5440 connman_network_driver_unregister(&network_driver);
5443 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5444 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)