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 <net/ethernet.h>
34 #include <linux/wireless.h>
37 #define IFF_LOWER_UP 0x10000
40 #include <dbus/dbus.h>
43 #define CONNMAN_API_SUBJECT_TO_CHANGE
44 #include <connman/plugin.h>
45 #include <connman/inet.h>
46 #include <connman/device.h>
47 #include <connman/rtnl.h>
48 #include <connman/technology.h>
49 #include <connman/service.h>
50 #include <connman/peer.h>
51 #include <connman/log.h>
52 #include <connman/option.h>
53 #include <connman/storage.h>
54 #include <include/setting.h>
55 #include <connman/provision.h>
56 #include <connman/utsname.h>
57 #include <connman/machine.h>
58 #include <connman/tethering.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_EXPONENTIAL "exponential:3:300"
68 #define AUTOSCAN_SINGLE "single:3"
70 #define P2P_FIND_TIMEOUT 30
71 #define P2P_CONNECTION_TIMEOUT 100
72 #define P2P_LISTEN_PERIOD 500
73 #define P2P_LISTEN_INTERVAL 2000
75 #define ASSOC_STATUS_NO_CLIENT 17
77 #define LOAD_SHAPING_MAX_RETRIES 7
79 #define LOAD_SHAPING_MAX_RETRIES 3
83 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
86 static struct connman_technology *wifi_technology = NULL;
87 static struct connman_technology *p2p_technology = NULL;
89 enum wifi_ap_capability{
91 WIFI_AP_SUPPORTED = 1,
92 WIFI_AP_NOT_SUPPORTED = 2,
95 enum wifi_scanning_type {
96 WIFI_SCANNING_UNKNOWN = 0,
97 WIFI_SCANNING_PASSIVE = 1,
98 WIFI_SCANNING_ACTIVE = 2,
101 struct hidden_params {
103 unsigned int ssid_len;
105 char *anonymous_identity;
107 char *altsubject_match;
108 char *domain_suffix_match;
112 GSupplicantScanParams *scan_params;
117 * Used for autoscan "emulation".
118 * Should be removed when wpa_s autoscan support will be by default.
120 struct autoscan_params {
124 unsigned int timeout;
127 struct wifi_tethering_info {
128 struct wifi_data *wifi;
129 struct connman_technology *technology;
131 GSupplicantSSID *ssid;
136 struct connman_device *device;
137 struct connman_network *network;
138 struct connman_network *pending_network;
140 GSupplicantInterface *interface;
141 GSupplicantState state;
145 enum wifi_ap_capability ap_supported;
147 bool interface_ready;
153 int load_shaping_retries;
154 struct hidden_params *hidden;
155 bool postpone_hidden;
156 struct wifi_tethering_info *tethering_param;
158 * autoscan "emulation".
160 struct autoscan_params *autoscan;
161 enum wifi_scanning_type scanning_type;
162 GSupplicantScanParams *scan_params;
163 unsigned int p2p_find_timeout;
164 unsigned int p2p_connection_timeout;
165 struct connman_peer *pending_peer;
170 #if defined TIZEN_EXT
171 int assoc_retry_count;
172 struct connman_network *scan_pending_network;
173 bool allow_full_scan;
174 unsigned int automaxspeed_timeout;
175 GSupplicantScanParams *hidden_scan_params;
179 #if defined TIZEN_EXT_WIFI_MESH
181 struct wifi_mesh_info *mesh_info;
185 #if defined TIZEN_EXT
189 #define TIZEN_ASSOC_RETRY_COUNT 4
191 static gboolean wifi_first_scan = false;
192 static gboolean found_with_first_scan = false;
193 static gboolean is_wifi_notifier_registered = false;
194 static GHashTable *failed_bssids = NULL;
195 static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
199 static GList *iface_list = NULL;
201 static GList *pending_wifi_device = NULL;
202 static GList *p2p_iface_list = NULL;
203 static bool wfd_service_registered = false;
205 static void start_autoscan(struct connman_device *device);
206 static int tech_set_tethering(struct connman_technology *technology,
207 const char *identifier, const char *passphrase,
208 const char *bridge, bool enabled);
210 #if defined TIZEN_EXT
211 #define NETCONFIG_SERVICE "net.netconfig"
212 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
213 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
215 struct enc_method_call_data {
216 DBusConnection *connection;
217 struct connman_network *network;
220 static struct enc_method_call_data encrypt_request_data;
222 static void encryption_request_reply(DBusPendingCall *call,
227 DBusMessageIter args;
229 struct connman_service *service;
230 gchar* encrypted_value = NULL;
231 struct connman_network *network = encrypt_request_data.network;
235 reply = dbus_pending_call_steal_reply(call);
237 dbus_error_init(&error);
238 if (dbus_set_error_from_message(&error, reply)) {
239 DBG("send_encryption_request() %s %s", error.name, error.message);
240 dbus_error_free(&error);
244 if (dbus_message_iter_init(reply, &args) == FALSE)
247 dbus_message_iter_get_basic(&args, &out_data);
249 encrypted_value = g_strdup((const gchar *)out_data);
250 service = connman_service_lookup_from_network(network);
253 DBG("encryption result: no service");
257 if (connman_service_get_favorite(service)) {
258 __connman_service_set_passphrase(service, encrypted_value);
259 __connman_service_save(service);
261 connman_network_set_string(network, "WiFi.Passphrase",
264 DBG("encryption result: succeeded");
267 dbus_message_unref(reply);
268 dbus_pending_call_unref(call);
269 dbus_connection_unref(encrypt_request_data.connection);
270 g_free(encrypted_value);
272 encrypt_request_data.connection = NULL;
273 encrypt_request_data.network = NULL;
276 static int send_encryption_request(const char *passphrase,
277 struct connman_network *network)
279 DBusConnection *connection = NULL;
280 DBusMessage *msg = NULL;
281 DBusPendingCall *call;
284 DBG("Invalid parameter");
288 connection = connman_dbus_get_connection();
290 DBG("dbus connection does not exist");
294 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
295 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
297 dbus_connection_unref(connection);
301 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
304 if (!dbus_connection_send_with_reply(connection, msg,
305 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
306 dbus_message_unref(msg);
307 dbus_connection_unref(connection);
312 dbus_message_unref(msg);
313 dbus_connection_unref(connection);
317 encrypt_request_data.connection = connection;
318 encrypt_request_data.network = network;
320 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
321 dbus_message_unref(msg);
327 static int p2p_tech_probe(struct connman_technology *technology)
329 p2p_technology = technology;
334 static void p2p_tech_remove(struct connman_technology *technology)
336 p2p_technology = NULL;
339 static struct connman_technology_driver p2p_tech_driver = {
341 .type = CONNMAN_SERVICE_TYPE_P2P,
342 .probe = p2p_tech_probe,
343 .remove = p2p_tech_remove,
346 static bool is_p2p_connecting(void)
350 for (list = iface_list; list; list = list->next) {
351 struct wifi_data *wifi = list->data;
353 if (wifi->p2p_connecting)
360 static void add_pending_wifi_device(struct wifi_data *wifi)
362 if (g_list_find(pending_wifi_device, wifi))
365 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
368 #if defined TIZEN_EXT_WIFI_MESH
369 struct wifi_mesh_info {
370 struct wifi_data *wifi;
371 GSupplicantInterface *interface;
372 struct connman_mesh *mesh;
379 struct mesh_change_peer_status_info {
381 enum connman_mesh_peer_status peer_status;
382 mesh_change_peer_status_cb_t callback;
386 static struct connman_technology_driver mesh_tech_driver = {
388 .type = CONNMAN_SERVICE_TYPE_MESH,
391 static void mesh_interface_create_callback(int result,
392 GSupplicantInterface *interface,
395 struct wifi_mesh_info *mesh_info = user_data;
396 struct wifi_data *wifi;
397 bool success = false;
399 DBG("result %d ifname %s, mesh_info %p", result,
400 g_supplicant_interface_get_ifname(interface),
403 if (result < 0 || !mesh_info)
406 wifi = mesh_info->wifi;
408 mesh_info->interface = interface;
409 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
410 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
411 DBG("Mesh Interface identifier %s", mesh_info->identifier);
412 wifi->mesh_interface = true;
413 wifi->mesh_info = mesh_info;
414 g_supplicant_interface_set_data(interface, wifi);
418 connman_mesh_notify_interface_create(success);
421 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
424 struct wifi_data *wifi;
425 struct wifi_mesh_info *mesh_info;
426 const char *wifi_ifname;
427 bool parent_found = false;
428 const char *driver = "nl80211";
430 for (list = iface_list; list; list = list->next) {
433 if (!g_supplicant_interface_has_mesh(wifi->interface))
436 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
440 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
447 DBG("Parent interface %s doesn't exist", parent_ifname);
451 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
455 mesh_info->wifi = wifi;
456 mesh_info->ifname = g_strdup(ifname);
457 mesh_info->parent_ifname = g_strdup(parent_ifname);
459 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
460 mesh_interface_create_callback, mesh_info);
464 static void mesh_interface_remove_callback(int result,
465 GSupplicantInterface *interface,
468 struct wifi_data *wifi = user_data;
469 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
470 bool success = false;
472 DBG("result %d mesh_info %p", result, mesh_info);
474 if (result < 0 || !mesh_info)
477 mesh_info->interface = NULL;
478 g_free(mesh_info->parent_ifname);
479 g_free(mesh_info->ifname);
480 g_free(mesh_info->identifier);
482 wifi->mesh_interface = false;
483 wifi->mesh_info = NULL;
487 connman_mesh_notify_interface_remove(success);
490 static int remove_mesh_interface(const char *ifname)
493 struct wifi_data *wifi;
494 struct wifi_mesh_info *mesh_info;
495 bool mesh_if_found = false;
498 for (list = iface_list; list; list = list->next) {
501 if (wifi->mesh_interface) {
502 mesh_if_found = true;
507 if (!mesh_if_found) {
508 DBG("Mesh interface %s doesn't exist", ifname);
512 mesh_info = wifi->mesh_info;
513 ret = g_supplicant_interface_remove(mesh_info->interface,
514 mesh_interface_remove_callback, wifi);
521 static void mesh_disconnect_callback(int result,
522 GSupplicantInterface *interface, void *user_data)
524 struct connman_mesh *mesh = user_data;
526 DBG("result %d interface %p mesh %p", result, interface, mesh);
529 static int mesh_peer_disconnect(struct connman_mesh *mesh)
532 struct wifi_data *wifi;
533 struct wifi_mesh_info *mesh_info;
534 bool mesh_if_found = false;
535 GSupplicantInterface *interface;
537 for (list = iface_list; list; list = list->next) {
540 if (wifi->mesh_interface) {
541 mesh_if_found = true;
546 if (!mesh_if_found) {
547 DBG("Mesh interface is not created");
551 mesh_info = wifi->mesh_info;
553 interface = mesh_info->interface;
554 return g_supplicant_interface_disconnect(interface,
555 mesh_disconnect_callback, mesh);
558 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
561 struct connman_mesh *mesh = user_data;
562 DBG("mesh %p result %d", mesh, result);
565 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
567 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
570 static GSupplicantSecurity mesh_network_security(const char *security)
572 if (g_str_equal(security, "none"))
573 return G_SUPPLICANT_SECURITY_NONE;
574 else if (g_str_equal(security, "sae"))
575 return G_SUPPLICANT_SECURITY_SAE;
577 return G_SUPPLICANT_SECURITY_UNKNOWN;
580 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
583 const char *security;
588 memset(ssid, 0, sizeof(*ssid));
589 ssid->mode = G_SUPPLICANT_MODE_MESH;
591 security = connman_mesh_get_security(mesh);
592 ssid->security = mesh_network_security(security);
594 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
595 ssid->passphrase = connman_mesh_get_passphrase(mesh);
597 ssid->freq = connman_mesh_get_frequency(mesh);
598 name = connman_mesh_get_name(mesh);
600 ssid->ssid_len = strlen(name);
601 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
602 memcpy(ssid->ssid, name, ssid->ssid_len);
607 static int mesh_peer_connect(struct connman_mesh *mesh)
610 struct wifi_data *wifi;
611 struct wifi_mesh_info *mesh_info;
612 bool mesh_if_found = false;
613 GSupplicantInterface *interface;
614 GSupplicantSSID *ssid;
616 for (list = iface_list; list; list = list->next) {
619 if (wifi->mesh_interface) {
620 mesh_if_found = true;
625 if (!mesh_if_found) {
626 DBG("Mesh interface is not created");
630 mesh_info = wifi->mesh_info;
632 interface = mesh_info->interface;
634 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
638 mesh_info->mesh = mesh;
640 mesh_ssid_init(ssid, mesh);
641 return g_supplicant_interface_connect(interface, ssid,
642 mesh_connect_callback, mesh);
645 static void mesh_peer_change_status_callback(int result,
646 GSupplicantInterface *interface,
649 struct mesh_change_peer_status_info *data = user_data;
651 DBG("result %d Peer Status %d", result, data->peer_status);
653 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
654 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
655 connman_mesh_remove_connected_peer(data->peer_address, 52);
659 data->callback(result, data->user_data);
661 g_free(data->peer_address);
666 static int mesh_change_peer_status(const char *peer_address,
667 enum connman_mesh_peer_status status,
668 mesh_change_peer_status_cb_t callback, void *user_data)
671 struct wifi_data *wifi;
672 struct wifi_mesh_info *mesh_info;
673 bool mesh_if_found = false;
674 GSupplicantInterface *interface;
675 struct mesh_change_peer_status_info *data;
678 for (list = iface_list; list; list = list->next) {
681 if (wifi->mesh_interface) {
682 mesh_if_found = true;
687 if (!mesh_if_found) {
688 DBG("Mesh interface is not created");
692 mesh_info = wifi->mesh_info;
694 interface = mesh_info->interface;
697 case CONNMAN_MESH_PEER_ADD:
698 method = "MeshPeerAdd";
700 case CONNMAN_MESH_PEER_REMOVE:
701 method = "MeshPeerRemove";
704 DBG("Invalid method");
708 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
710 DBG("Memory allocation failed");
714 data->peer_address = g_strdup(peer_address);
715 data->peer_status = status;
716 data->callback = callback;
717 data->user_data = user_data;
719 return g_supplicant_interface_mesh_peer_change_status(interface,
720 mesh_peer_change_status_callback, peer_address, method,
724 static struct connman_mesh_driver mesh_driver = {
725 .add_interface = add_mesh_interface,
726 .remove_interface = remove_mesh_interface,
727 .connect = mesh_peer_connect,
728 .disconnect = mesh_peer_disconnect,
729 .change_peer_status = mesh_change_peer_status,
732 static void mesh_support(GSupplicantInterface *interface)
736 if (!g_supplicant_interface_has_mesh(interface))
739 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
740 DBG("Could not register Mesh technology driver");
744 connman_mesh_driver_register(&mesh_driver);
747 static void check_mesh_technology(void)
749 bool mesh_exists = false;
752 for (list = iface_list; list; list = list->next) {
753 struct wifi_data *w = list->data;
756 g_supplicant_interface_has_mesh(w->interface))
761 connman_technology_driver_unregister(&mesh_tech_driver);
762 connman_mesh_driver_unregister(&mesh_driver);
766 static void mesh_group_started(GSupplicantInterface *interface)
768 struct wifi_data *wifi;
769 struct wifi_mesh_info *mesh_info;
770 struct connman_mesh *mesh;
771 const unsigned char *ssid;
772 unsigned int ssid_len;
775 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
776 memcpy(name, ssid, ssid_len);
777 name[ssid_len] = '\0';
778 DBG("name %s", name);
779 wifi = g_supplicant_interface_get_data(interface);
780 DBG("wifi %p", wifi);
785 mesh_info = wifi->mesh_info;
789 mesh = mesh_info->mesh;
793 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
796 static void mesh_group_removed(GSupplicantInterface *interface)
798 struct wifi_data *wifi;
799 struct wifi_mesh_info *mesh_info;
800 struct connman_mesh *mesh;
801 const unsigned char *ssid;
802 unsigned int ssid_len;
803 int disconnect_reason;
806 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
807 memcpy(name, ssid, ssid_len);
808 name[ssid_len] = '\0';
809 DBG("name %s", name);
811 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
812 DBG("Disconnect Reason %d", disconnect_reason);
814 wifi = g_supplicant_interface_get_data(interface);
815 DBG("wifi %p", wifi);
820 mesh_info = wifi->mesh_info;
824 mesh = connman_get_connected_mesh_from_name(name);
826 DBG("%s is not connected", name);
827 mesh = connman_get_connecting_mesh_from_name(name);
829 DBG("%s is not connecting", name);
834 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
835 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
838 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
840 const char *peer_address;
842 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
847 DBG("Peer %s connected", peer_address);
848 connman_mesh_add_connected_peer(peer_address);
851 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
853 const char *peer_address;
856 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
861 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
863 DBG("Peer %s disconnected with reason %d", peer_address, reason);
864 connman_mesh_remove_connected_peer(peer_address, reason);
868 static struct wifi_data *get_pending_wifi_data(const char *ifname)
872 for (list = pending_wifi_device; list; list = list->next) {
873 struct wifi_data *wifi;
874 const char *dev_name;
877 if (!wifi || !wifi->device)
880 dev_name = connman_device_get_string(wifi->device, "Interface");
881 if (!g_strcmp0(ifname, dev_name)) {
882 pending_wifi_device = g_list_delete_link(
883 pending_wifi_device, list);
891 static void remove_pending_wifi_device(struct wifi_data *wifi)
895 link = g_list_find(pending_wifi_device, wifi);
900 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
903 static void peer_cancel_timeout(struct wifi_data *wifi)
905 if (wifi->p2p_connection_timeout > 0)
906 g_source_remove(wifi->p2p_connection_timeout);
908 wifi->p2p_connection_timeout = 0;
909 wifi->p2p_connecting = false;
911 if (wifi->pending_peer) {
912 connman_peer_unref(wifi->pending_peer);
913 wifi->pending_peer = NULL;
917 static gboolean peer_connect_timeout(gpointer data)
919 struct wifi_data *wifi = data;
923 if (wifi->p2p_connecting) {
924 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
925 GSupplicantPeer *gs_peer =
926 g_supplicant_interface_peer_lookup(wifi->interface,
927 connman_peer_get_identifier(wifi->pending_peer));
929 if (g_supplicant_peer_has_requested_connection(gs_peer))
930 state = CONNMAN_PEER_STATE_IDLE;
932 connman_peer_set_state(wifi->pending_peer, state);
935 peer_cancel_timeout(wifi);
940 static void peer_connect_callback(int result, GSupplicantInterface *interface,
943 struct wifi_data *wifi = user_data;
944 struct connman_peer *peer = wifi->pending_peer;
946 DBG("peer %p - %d", peer, result);
952 peer_connect_timeout(wifi);
956 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
958 wifi->p2p_connection_timeout = g_timeout_add_seconds(
959 P2P_CONNECTION_TIMEOUT,
960 peer_connect_timeout, wifi);
963 static int peer_connect(struct connman_peer *peer,
964 enum connman_peer_wps_method wps_method,
967 struct connman_device *device = connman_peer_get_device(peer);
968 GSupplicantPeerParams *peer_params;
969 GSupplicantPeer *gs_peer;
970 struct wifi_data *wifi;
974 DBG("peer %p", peer);
979 wifi = connman_device_get_data(device);
980 if (!wifi || !wifi->interface)
983 if (wifi->p2p_connecting)
986 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
987 connman_peer_get_identifier(peer));
991 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
992 pin = g_supplicant_peer_is_wps_pin(gs_peer);
994 switch (wps_method) {
995 case CONNMAN_PEER_WPS_UNKNOWN:
996 if ((pbc && pin) || pin)
999 case CONNMAN_PEER_WPS_PBC:
1004 case CONNMAN_PEER_WPS_PIN:
1005 if (!pin || !wps_pin)
1010 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1014 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1016 peer_params->wps_pin = g_strdup(wps_pin);
1018 peer_params->master = connman_peer_service_is_master();
1020 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1021 peer_connect_callback, wifi);
1022 if (ret == -EINPROGRESS) {
1023 wifi->pending_peer = connman_peer_ref(peer);
1024 wifi->p2p_connecting = true;
1025 } else if (ret < 0) {
1026 g_free(peer_params->path);
1027 g_free(peer_params->wps_pin);
1028 g_free(peer_params);
1034 static int peer_disconnect(struct connman_peer *peer)
1036 struct connman_device *device = connman_peer_get_device(peer);
1037 GSupplicantPeerParams peer_params = {};
1038 GSupplicantPeer *gs_peer;
1039 struct wifi_data *wifi;
1042 DBG("peer %p", peer);
1047 wifi = connman_device_get_data(device);
1051 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1052 connman_peer_get_identifier(peer));
1056 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1058 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1060 g_free(peer_params.path);
1062 if (ret == -EINPROGRESS) {
1063 peer_cancel_timeout(wifi);
1064 wifi->p2p_device = false;
1070 struct peer_service_registration {
1071 peer_service_registration_cb_t callback;
1075 static bool is_service_wfd(const unsigned char *specs, int length)
1077 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1083 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1085 struct wifi_data *wifi = data;
1087 if (!wifi->interface ||
1088 !g_supplicant_interface_has_p2p(wifi->interface))
1091 if (!wifi->servicing) {
1092 g_supplicant_interface_p2p_listen(wifi->interface,
1093 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1099 static void register_wfd_service_cb(int result,
1100 GSupplicantInterface *iface, void *user_data)
1102 struct peer_service_registration *reg_data = user_data;
1107 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1109 if (reg_data && reg_data->callback) {
1110 reg_data->callback(result, reg_data->user_data);
1115 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1116 const unsigned char *spec,
1117 int spec_length, const unsigned char *query,
1118 int query_length, int version)
1120 GSupplicantP2PServiceParams *params;
1122 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1127 params->version = version;
1128 params->service = g_memdup(spec, spec_length);
1129 } else if (query_length > 0 && spec_length > 0) {
1130 params->query = g_memdup(query, query_length);
1131 params->query_length = query_length;
1133 params->response = g_memdup(spec, spec_length);
1134 params->response_length = spec_length;
1136 params->wfd_ies = g_memdup(spec, spec_length);
1137 params->wfd_ies_length = spec_length;
1143 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1148 g_free(params->service);
1149 g_free(params->query);
1150 g_free(params->response);
1151 g_free(params->wfd_ies);
1156 static int peer_register_wfd_service(const unsigned char *specification,
1157 int specification_length,
1158 peer_service_registration_cb_t callback,
1161 struct peer_service_registration *reg_data = NULL;
1162 static GSupplicantP2PServiceParams *params;
1167 if (wfd_service_registered)
1170 params = fill_in_peer_service_params(specification,
1171 specification_length, NULL, 0, 0);
1175 reg_data = g_try_malloc0(sizeof(*reg_data));
1181 reg_data->callback = callback;
1182 reg_data->user_data = user_data;
1184 ret = g_supplicant_set_widi_ies(params,
1185 register_wfd_service_cb, reg_data);
1186 if (ret < 0 && ret != -EINPROGRESS)
1189 wfd_service_registered = true;
1193 free_peer_service_params(params);
1199 static void register_peer_service_cb(int result,
1200 GSupplicantInterface *iface, void *user_data)
1202 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1203 struct peer_service_registration *reg_data = user_data;
1205 #if defined TIZEN_EXT
1213 apply_p2p_listen_on_iface(wifi, NULL);
1215 if (reg_data->callback)
1216 reg_data->callback(result, reg_data->user_data);
1221 static int peer_register_service(const unsigned char *specification,
1222 int specification_length,
1223 const unsigned char *query,
1224 int query_length, int version,
1225 peer_service_registration_cb_t callback,
1228 struct peer_service_registration *reg_data;
1229 GSupplicantP2PServiceParams *params;
1236 if (specification && !version && !query &&
1237 is_service_wfd(specification, specification_length)) {
1238 return peer_register_wfd_service(specification,
1239 specification_length, callback, user_data);
1242 reg_data = g_try_malloc0(sizeof(*reg_data));
1246 reg_data->callback = callback;
1247 reg_data->user_data = user_data;
1249 ret_f = -EOPNOTSUPP;
1251 for (list = iface_list; list; list = list->next) {
1252 struct wifi_data *wifi = list->data;
1253 GSupplicantInterface *iface = wifi->interface;
1255 if (!g_supplicant_interface_has_p2p(iface))
1258 params = fill_in_peer_service_params(specification,
1259 specification_length, query,
1260 query_length, version);
1265 ret_f = g_supplicant_interface_p2p_add_service(iface,
1266 register_peer_service_cb, params, reg_data);
1267 if (ret_f == 0 || ret_f == -EINPROGRESS)
1271 ret = g_supplicant_interface_p2p_add_service(iface,
1272 register_peer_service_cb, params, NULL);
1273 if (ret != 0 && ret != -EINPROGRESS)
1274 free_peer_service_params(params);
1277 if (ret_f != 0 && ret_f != -EINPROGRESS)
1283 static int peer_unregister_wfd_service(void)
1285 GSupplicantP2PServiceParams *params;
1288 if (!wfd_service_registered)
1291 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1295 wfd_service_registered = false;
1297 g_supplicant_set_widi_ies(params, NULL, NULL);
1299 for (list = iface_list; list; list = list->next) {
1300 struct wifi_data *wifi = list->data;
1302 if (!g_supplicant_interface_has_p2p(wifi->interface))
1306 if (!wifi->servicing || wifi->servicing < 0) {
1307 g_supplicant_interface_p2p_listen(wifi->interface,
1309 wifi->servicing = 0;
1316 static int peer_unregister_service(const unsigned char *specification,
1317 int specification_length,
1318 const unsigned char *query,
1319 int query_length, int version)
1321 GSupplicantP2PServiceParams *params;
1326 if (specification && !version && !query &&
1327 is_service_wfd(specification, specification_length)) {
1328 ret = peer_unregister_wfd_service();
1329 if (ret != 0 && ret != -EINPROGRESS)
1334 for (list = iface_list; list; list = list->next) {
1335 struct wifi_data *wifi = list->data;
1336 GSupplicantInterface *iface = wifi->interface;
1339 goto stop_listening;
1341 if (!g_supplicant_interface_has_p2p(iface))
1344 params = fill_in_peer_service_params(specification,
1345 specification_length, query,
1346 query_length, version);
1350 ret = g_supplicant_interface_p2p_del_service(iface, params);
1351 if (ret != 0 && ret != -EINPROGRESS)
1352 free_peer_service_params(params);
1355 if (!wifi->servicing || wifi->servicing < 0) {
1356 g_supplicant_interface_p2p_listen(iface, 0, 0);
1357 wifi->servicing = 0;
1364 static struct connman_peer_driver peer_driver = {
1365 .connect = peer_connect,
1366 .disconnect = peer_disconnect,
1367 .register_service = peer_register_service,
1368 .unregister_service = peer_unregister_service,
1371 static void handle_tethering(struct wifi_data *wifi)
1373 if (!wifi->tethering)
1382 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1384 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1387 wifi->bridged = true;
1390 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1392 struct connman_device *device = user_data;
1393 struct wifi_data *wifi = connman_device_get_data(device);
1398 DBG("index %d flags %d change %d", wifi->index, flags, change);
1400 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1402 DBG("interface up");
1404 DBG("interface down");
1407 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1408 if (flags & IFF_LOWER_UP) {
1411 handle_tethering(wifi);
1416 wifi->flags = flags;
1419 static int wifi_probe(struct connman_device *device)
1421 struct wifi_data *wifi;
1423 DBG("device %p", device);
1425 wifi = g_try_new0(struct wifi_data, 1);
1429 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1430 wifi->ap_supported = WIFI_AP_UNKNOWN;
1431 wifi->tethering_param = NULL;
1433 connman_device_set_data(device, wifi);
1434 wifi->device = connman_device_ref(device);
1436 wifi->index = connman_device_get_index(device);
1439 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1440 wifi_newlink, device);
1441 if (is_p2p_connecting())
1442 add_pending_wifi_device(wifi);
1444 iface_list = g_list_append(iface_list, wifi);
1449 static void remove_networks(struct connman_device *device,
1450 struct wifi_data *wifi)
1454 for (list = wifi->networks; list; list = list->next) {
1455 struct connman_network *network = list->data;
1457 connman_device_remove_network(device, network);
1458 connman_network_unref(network);
1461 g_slist_free(wifi->networks);
1462 wifi->networks = NULL;
1465 static void remove_peers(struct wifi_data *wifi)
1469 for (list = wifi->peers; list; list = list->next) {
1470 struct connman_peer *peer = list->data;
1472 connman_peer_unregister(peer);
1473 connman_peer_unref(peer);
1476 g_slist_free(wifi->peers);
1480 static void reset_autoscan(struct connman_device *device)
1482 struct wifi_data *wifi = connman_device_get_data(device);
1483 struct autoscan_params *autoscan;
1487 if (!wifi || !wifi->autoscan)
1490 autoscan = wifi->autoscan;
1492 autoscan->interval = 0;
1494 if (autoscan->timeout == 0)
1497 g_source_remove(autoscan->timeout);
1498 autoscan->timeout = 0;
1500 connman_device_unref(device);
1503 static void stop_autoscan(struct connman_device *device)
1505 const struct wifi_data *wifi = connman_device_get_data(device);
1507 if (!wifi || !wifi->autoscan)
1510 reset_autoscan(device);
1512 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1515 static void check_p2p_technology(void)
1517 bool p2p_exists = false;
1520 for (list = iface_list; list; list = list->next) {
1521 struct wifi_data *w = list->data;
1524 g_supplicant_interface_has_p2p(w->interface))
1529 connman_technology_driver_unregister(&p2p_tech_driver);
1530 connman_peer_driver_unregister(&peer_driver);
1534 struct last_connected {
1540 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1542 GTimeVal *aval = (GTimeVal *)a;
1543 GTimeVal *bval = (GTimeVal *)b;
1545 /* Note that the sort order is descending */
1546 if (aval->tv_sec < bval->tv_sec)
1549 if (aval->tv_sec > bval->tv_sec)
1555 static void free_entry(gpointer data)
1557 struct last_connected *entry = data;
1559 g_free(entry->ssid);
1563 static void wifi_remove(struct connman_device *device)
1565 struct wifi_data *wifi = connman_device_get_data(device);
1567 DBG("device %p wifi %p", device, wifi);
1572 stop_autoscan(device);
1574 if (wifi->p2p_device)
1575 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1577 iface_list = g_list_remove(iface_list, wifi);
1579 check_p2p_technology();
1580 #if defined TIZEN_EXT_WIFI_MESH
1581 check_mesh_technology();
1584 remove_pending_wifi_device(wifi);
1586 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
1587 g_source_remove(wifi->p2p_find_timeout);
1588 connman_device_unref(wifi->device);
1591 if (wifi->p2p_connection_timeout)
1592 g_source_remove(wifi->p2p_connection_timeout);
1594 #if defined TIZEN_EXT
1595 if (wifi->automaxspeed_timeout != 0) {
1596 g_source_remove(wifi->automaxspeed_timeout);
1597 wifi->automaxspeed_timeout = 0;
1601 remove_networks(device, wifi);
1604 connman_device_set_powered(device, false);
1605 connman_device_set_data(device, NULL);
1606 connman_device_unref(wifi->device);
1607 connman_rtnl_remove_watch(wifi->watch);
1609 g_supplicant_interface_set_data(wifi->interface, NULL);
1611 g_supplicant_interface_cancel(wifi->interface);
1613 if (wifi->scan_params)
1614 g_supplicant_free_scan_params(wifi->scan_params);
1615 #if defined TIZEN_EXT
1616 if (wifi->hidden_scan_params) {
1617 while (wifi->hidden_scan_params->ssids) {
1618 struct scan_ssid *ssid;
1619 ssid = wifi->hidden_scan_params->ssids->data;
1620 wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
1622 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1626 g_free(wifi->autoscan);
1627 g_free(wifi->identifier);
1631 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1635 for (iter = list; iter; iter = g_slist_next(iter)) {
1636 struct scan_ssid *scan_ssid = iter->data;
1638 if (ssid_len == scan_ssid->ssid_len &&
1639 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1646 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1647 int freq, GSupplicantScanParams *scan_data,
1648 int driver_max_scan_ssids, char *ssid_name)
1651 struct scan_ssid *scan_ssid;
1653 if ((driver_max_scan_ssids == 0 ||
1654 driver_max_scan_ssids > scan_data->num_ssids) &&
1655 (hex_ssid || raw_ssid)) {
1657 unsigned int j = 0, hex;
1660 size_t hex_ssid_len = strlen(hex_ssid);
1662 ssid = g_try_malloc0(hex_ssid_len / 2);
1666 for (i = 0; i < hex_ssid_len; i += 2) {
1667 sscanf(hex_ssid + i, "%02x", &hex);
1676 * If we have already added hidden AP to the list,
1677 * then do not do it again. This might happen if you have
1678 * used or are using multiple wifi cards, so in that case
1679 * you might have multiple service files for same AP.
1681 if (is_duplicate(scan_data->ssids, ssid, j)) {
1687 scan_ssid = g_try_new(struct scan_ssid, 1);
1694 memcpy(scan_ssid->ssid, ssid, j);
1695 scan_ssid->ssid_len = j;
1696 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1699 scan_data->num_ssids++;
1701 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1702 scan_data->num_ssids);
1709 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1711 if (!scan_data->freqs) {
1712 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1713 if (!scan_data->freqs) {
1714 g_slist_free_full(scan_data->ssids, g_free);
1718 scan_data->num_freqs = 1;
1719 scan_data->freqs[0] = freq;
1721 bool duplicate = false;
1723 /* Don't add duplicate entries */
1724 for (i = 0; i < scan_data->num_freqs; i++) {
1725 if (scan_data->freqs[i] == freq) {
1732 scan_data->num_freqs++;
1733 scan_data->freqs = g_try_realloc(scan_data->freqs,
1734 sizeof(uint16_t) * scan_data->num_freqs);
1735 if (!scan_data->freqs) {
1736 g_slist_free_full(scan_data->ssids, g_free);
1739 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1746 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1748 struct connman_config_entry **entries;
1750 #if defined TIZEN_EXT
1751 gchar **services = NULL;
1754 #endif /* defined TIZEN_EXT */
1758 int num_ssids = 0, add_param_failed = 0;
1759 #if defined TIZEN_EXT
1760 GSequenceIter *iter;
1761 GSequence *latest_list;
1762 struct last_connected *entry;
1765 latest_list = g_sequence_new(free_entry);
1769 services = connman_storage_get_services();
1770 for (i = 0; services && services[i]; i++) {
1771 if (strncmp(services[i], "wifi_", 5) != 0)
1774 keyfile = connman_storage_load_service(services[i]);
1778 value = g_key_file_get_boolean(keyfile,
1779 services[i], "Hidden", NULL);
1781 g_key_file_free(keyfile);
1785 value = g_key_file_get_boolean(keyfile,
1786 services[i], "Favorite", NULL);
1788 g_key_file_free(keyfile);
1792 #if defined TIZEN_EXT
1793 value = g_key_file_get_boolean(keyfile,
1794 services[i], "AutoConnect", NULL);
1796 g_key_file_free(keyfile);
1800 gchar *str = g_key_file_get_string(keyfile,
1801 services[i], "Modified", NULL);
1803 g_key_file_free(keyfile);
1806 g_time_val_from_iso8601(str, &modified);
1810 ssid = g_key_file_get_string(keyfile,
1811 services[i], "SSID", NULL);
1813 name = g_key_file_get_string(keyfile, services[i], "Name",
1816 #if defined TIZEN_EXT
1817 entry = g_try_new(struct last_connected, 1);
1819 g_sequence_free(latest_list);
1822 g_key_file_free(keyfile);
1826 entry->modified = modified;
1829 g_sequence_insert_sorted(latest_list, entry,
1832 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1841 g_key_file_free(keyfile);
1844 #if defined TIZEN_EXT
1845 gint length = g_sequence_get_length(latest_list);
1846 iter = g_sequence_get_begin_iter(latest_list);
1848 for (i = 0; i < length; i++) {
1849 entry = g_sequence_get(iter);
1851 ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid);
1857 iter = g_sequence_iter_next(iter);
1860 g_sequence_free(latest_list);
1864 * Check if there are any hidden AP that needs to be provisioned.
1866 entries = connman_config_get_entries("wifi");
1867 for (i = 0; entries && entries[i]; i++) {
1870 if (!entries[i]->hidden)
1873 if (!entries[i]->ssid) {
1874 ssid = entries[i]->name;
1877 ssid = entries[i]->ssid;
1878 len = entries[i]->ssid_len;
1884 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1891 connman_config_free_entries(entries);
1893 if (add_param_failed > 0)
1894 DBG("Unable to scan %d out of %d SSIDs",
1895 add_param_failed, num_ssids);
1897 g_strfreev(services);
1902 static int get_hidden_connections_params(struct wifi_data *wifi,
1903 GSupplicantScanParams *scan_params)
1905 int driver_max_ssids, i;
1906 GSupplicantScanParams *orig_params;
1909 * Scan hidden networks so that we can autoconnect to them.
1910 * We will assume 1 as a default number of ssid to scan.
1912 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1914 if (driver_max_ssids == 0)
1915 driver_max_ssids = 1;
1917 DBG("max ssids %d", driver_max_ssids);
1919 #if defined TIZEN_EXT
1920 if (!wifi->hidden_scan_params) {
1921 wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1922 if (!wifi->hidden_scan_params)
1925 if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
1926 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1927 wifi->hidden_scan_params = NULL;
1933 orig_params = wifi->hidden_scan_params;
1935 if (!wifi->scan_params) {
1936 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1937 if (!wifi->scan_params)
1940 if (get_hidden_connections(wifi->scan_params) == 0) {
1941 g_supplicant_free_scan_params(wifi->scan_params);
1942 wifi->scan_params = NULL;
1948 orig_params = wifi->scan_params;
1951 /* Let's transfer driver_max_ssids params */
1952 for (i = 0; i < driver_max_ssids; i++) {
1953 struct scan_ssid *ssid;
1955 #if defined TIZEN_EXT
1956 if (!wifi->hidden_scan_params->ssids)
1958 if (!wifi->scan_params->ssids)
1962 ssid = orig_params->ssids->data;
1963 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1964 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1968 scan_params->num_ssids = i;
1969 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1971 scan_params->freqs = g_memdup(orig_params->freqs,
1972 sizeof(uint16_t) * orig_params->num_freqs);
1973 if (!scan_params->freqs)
1976 scan_params->num_freqs = orig_params->num_freqs;
1981 orig_params->num_ssids -= scan_params->num_ssids;
1983 return scan_params->num_ssids;
1986 g_slist_free_full(scan_params->ssids, g_free);
1987 #if defined TIZEN_EXT
1988 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1989 wifi->hidden_scan_params = NULL;
1991 g_supplicant_free_scan_params(wifi->scan_params);
1992 wifi->scan_params = NULL;
1998 static int throw_wifi_scan(struct connman_device *device,
1999 GSupplicantInterfaceCallback callback)
2001 struct wifi_data *wifi = connman_device_get_data(device);
2007 DBG("device %p %p", device, wifi->interface);
2009 if (wifi->tethering)
2012 #if defined TIZEN_EXT
2013 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)
2014 && !wifi->allow_full_scan)
2016 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
2020 connman_device_ref(device);
2022 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2025 connman_device_set_scanning(device,
2026 CONNMAN_SERVICE_TYPE_WIFI, true);
2028 connman_device_unref(device);
2033 static void hidden_free(struct hidden_params *hidden)
2038 if (hidden->scan_params)
2039 g_supplicant_free_scan_params(hidden->scan_params);
2040 g_free(hidden->identity);
2041 g_free(hidden->passphrase);
2042 g_free(hidden->security);
2046 #if defined TIZEN_EXT
2047 static void service_state_changed(struct connman_service *service,
2048 enum connman_service_state state);
2050 static int network_connect(struct connman_network *network);
2052 static struct connman_notifier notifier = {
2054 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
2055 .service_state_changed = service_state_changed,
2058 static void service_state_changed(struct connman_service *service,
2059 enum connman_service_state state)
2061 enum connman_service_type type;
2063 type = connman_service_get_type(service);
2064 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2067 DBG("service %p state %d", service, state);
2070 case CONNMAN_SERVICE_STATE_READY:
2071 case CONNMAN_SERVICE_STATE_ONLINE:
2072 case CONNMAN_SERVICE_STATE_FAILURE:
2073 connman_notifier_unregister(¬ifier);
2074 is_wifi_notifier_registered = FALSE;
2076 __connman_device_request_scan(type);
2084 static void scan_callback_hidden(int result,
2085 GSupplicantInterface *interface, void *user_data);
2088 static void scan_callback(int result, GSupplicantInterface *interface,
2091 struct connman_device *device = user_data;
2092 struct wifi_data *wifi = connman_device_get_data(device);
2094 #if defined TIZEN_EXT
2095 GSList *list = NULL;
2096 bool favorite_exists = false;
2097 struct connman_network *network = NULL;
2098 struct connman_service *service = NULL;
2101 DBG("result %d wifi %p", result, wifi);
2104 if (wifi->hidden && !wifi->postpone_hidden) {
2105 connman_network_clear_hidden(wifi->hidden->user_data);
2106 hidden_free(wifi->hidden);
2107 wifi->hidden = NULL;
2110 if (wifi->scan_params) {
2111 g_supplicant_free_scan_params(wifi->scan_params);
2112 wifi->scan_params = NULL;
2115 #if defined TIZEN_EXT
2116 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2117 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2118 wifi->hidden_scan_params = NULL;
2124 connman_device_reset_scanning(device);
2126 /* User is connecting to a hidden AP, let's wait for finished event */
2127 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2128 GSupplicantScanParams *scan_params;
2131 wifi->postpone_hidden = false;
2132 scan_params = wifi->hidden->scan_params;
2133 wifi->hidden->scan_params = NULL;
2135 reset_autoscan(device);
2137 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2138 scan_callback, device);
2142 /* On error, let's recall scan_callback, which will cleanup */
2143 return scan_callback(ret, interface, user_data);
2146 #if defined TIZEN_EXT
2148 for (list = wifi->networks; list; list = list->next) {
2149 network = list->data;
2150 service = connman_service_lookup_from_network(network);
2152 if (service != NULL &&
2153 (connman_service_get_favorite(service) == true) &&
2154 (connman_service_get_autoconnect(service) == true)) {
2155 DBG("Favorite service exists [%s]", connman_network_get_string(network, "Name"));
2156 favorite_exists = true;
2162 if (favorite_exists == false) {
2163 if (wifi && wifi->allow_full_scan) {
2165 DBG("Trigger full channel scan");
2166 wifi->allow_full_scan = false;
2168 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2169 scan_callback_hidden, device);
2173 /* On error, let's recall scan_callback, which will cleanup */
2174 return scan_callback(ret, interface, user_data);
2179 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
2182 connman_device_set_scanning(device,
2183 CONNMAN_SERVICE_TYPE_WIFI, false);
2186 if (result != -ENOLINK)
2187 #if defined TIZEN_EXT
2190 start_autoscan(device);
2193 * If we are here then we were scanning; however, if we are
2194 * also mid-flight disabling the interface, then wifi_disable
2195 * has already cleared the device scanning state and
2196 * unreferenced the device, obviating the need to do it here.
2200 connman_device_unref(device);
2202 #if defined TIZEN_EXT
2203 if (wifi && wifi->scan_pending_network && result != -EIO) {
2204 network_connect(wifi->scan_pending_network);
2205 wifi->scan_pending_network = NULL;
2206 connman_network_set_connecting(wifi->network);
2209 if (is_wifi_notifier_registered != true &&
2210 wifi_first_scan == true && found_with_first_scan == true) {
2211 wifi_first_scan = false;
2212 found_with_first_scan = false;
2214 connman_notifier_register(¬ifier);
2215 is_wifi_notifier_registered = true;
2220 static void scan_callback_hidden(int result,
2221 GSupplicantInterface *interface, void *user_data)
2223 struct connman_device *device = user_data;
2224 struct wifi_data *wifi = connman_device_get_data(device);
2225 GSupplicantScanParams *scan_params;
2228 DBG("result %d wifi %p", result, wifi);
2233 /* User is trying to connect to a hidden AP */
2234 if (wifi->hidden && wifi->postpone_hidden)
2237 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2241 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2242 ret = g_supplicant_interface_scan(wifi->interface,
2244 #if defined TIZEN_EXT
2247 scan_callback_hidden,
2254 g_supplicant_free_scan_params(scan_params);
2257 scan_callback(result, interface, user_data);
2260 static gboolean autoscan_timeout(gpointer data)
2262 struct connman_device *device = data;
2263 struct wifi_data *wifi = connman_device_get_data(device);
2264 struct autoscan_params *autoscan;
2270 autoscan = wifi->autoscan;
2272 #if defined TIZEN_EXT
2277 if (autoscan->interval <= 0) {
2278 interval = autoscan->base;
2281 interval = autoscan->interval * autoscan->base;
2283 #if defined TIZEN_EXT
2284 if (autoscan->interval >= autoscan->limit)
2286 if (interval > autoscan->limit)
2288 interval = autoscan->limit;
2290 throw_wifi_scan(wifi->device, scan_callback_hidden);
2293 * In case BackgroundScanning is disabled, interval will reach the
2294 * limit exactly after the very first passive scanning. It allows
2295 * to ensure at most one passive scan is performed in such cases.
2297 if (!connman_setting_get_bool("BackgroundScanning") &&
2298 interval == autoscan->limit) {
2299 g_source_remove(autoscan->timeout);
2300 autoscan->timeout = 0;
2302 connman_device_unref(device);
2308 DBG("interval %d", interval);
2310 autoscan->interval = interval;
2312 autoscan->timeout = g_timeout_add_seconds(interval,
2313 autoscan_timeout, device);
2318 static void start_autoscan(struct connman_device *device)
2320 struct wifi_data *wifi = connman_device_get_data(device);
2321 struct autoscan_params *autoscan;
2328 if (wifi->p2p_device)
2331 if (wifi->connected)
2334 autoscan = wifi->autoscan;
2338 if (autoscan->timeout > 0 || autoscan->interval > 0)
2341 connman_device_ref(device);
2343 autoscan_timeout(device);
2346 static struct autoscan_params *parse_autoscan_params(const char *params)
2348 struct autoscan_params *autoscan;
2355 list_params = g_strsplit(params, ":", 0);
2356 if (list_params == 0)
2359 if (!g_strcmp0(list_params[0], "exponential") &&
2360 g_strv_length(list_params) == 3) {
2361 base = atoi(list_params[1]);
2362 limit = atoi(list_params[2]);
2363 } else if (!g_strcmp0(list_params[0], "single") &&
2364 g_strv_length(list_params) == 2)
2365 base = limit = atoi(list_params[1]);
2367 g_strfreev(list_params);
2371 DBG("Setup %s autoscanning", list_params[0]);
2373 g_strfreev(list_params);
2375 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2377 DBG("Could not allocate memory for autoscan");
2381 DBG("base %d - limit %d", base, limit);
2382 autoscan->base = base;
2383 autoscan->limit = limit;
2388 static void setup_autoscan(struct wifi_data *wifi)
2391 * If BackgroundScanning is enabled, setup exponential
2392 * autoscanning if it has not been previously done.
2394 if (connman_setting_get_bool("BackgroundScanning")) {
2395 wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
2400 * On the contrary, if BackgroundScanning is disabled, update autoscan
2401 * parameters based on the type of scanning that is being performed.
2403 if (wifi->autoscan) {
2404 g_free(wifi->autoscan);
2405 wifi->autoscan = NULL;
2408 switch (wifi->scanning_type) {
2409 case WIFI_SCANNING_PASSIVE:
2410 /* Do not setup autoscan. */
2412 case WIFI_SCANNING_ACTIVE:
2413 /* Setup one single passive scan after active. */
2414 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2416 case WIFI_SCANNING_UNKNOWN:
2417 /* Setup autoscan in this case but we should never fall here. */
2418 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2423 static void finalize_interface_creation(struct wifi_data *wifi)
2425 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2427 if (!wifi->device) {
2428 connman_error("WiFi device not set");
2432 connman_device_set_powered(wifi->device, true);
2434 if (wifi->p2p_device)
2437 if (!wifi->autoscan)
2438 setup_autoscan(wifi);
2440 start_autoscan(wifi->device);
2443 static void interface_create_callback(int result,
2444 GSupplicantInterface *interface,
2447 struct wifi_data *wifi = user_data;
2449 DBG("result %d ifname %s, wifi %p", result,
2450 g_supplicant_interface_get_ifname(interface),
2453 if (result < 0 || !wifi)
2456 wifi->interface = interface;
2457 g_supplicant_interface_set_data(interface, wifi);
2459 if (g_supplicant_interface_get_ready(interface)) {
2460 wifi->interface_ready = true;
2461 finalize_interface_creation(wifi);
2465 static int wifi_enable(struct connman_device *device)
2467 struct wifi_data *wifi = connman_device_get_data(device);
2470 const char *driver = connman_option_get_string("wifi");
2473 DBG("device %p %p", device, wifi);
2475 index = connman_device_get_index(device);
2476 if (!wifi || index < 0)
2479 if (is_p2p_connecting())
2480 return -EINPROGRESS;
2482 interface = connman_inet_ifname(index);
2483 ret = g_supplicant_interface_create(interface, driver, NULL,
2484 interface_create_callback,
2491 return -EINPROGRESS;
2494 static int wifi_disable(struct connman_device *device)
2496 struct wifi_data *wifi = connman_device_get_data(device);
2499 DBG("device %p wifi %p", device, wifi);
2504 wifi->connected = false;
2505 wifi->disconnecting = false;
2507 if (wifi->pending_network)
2508 wifi->pending_network = NULL;
2510 #if !defined TIZEN_EXT
2511 stop_autoscan(device);
2514 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
2515 g_source_remove(wifi->p2p_find_timeout);
2516 wifi->p2p_find_timeout = 0;
2517 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2518 connman_device_unref(wifi->device);
2521 #if defined TIZEN_EXT
2522 if (wifi->automaxspeed_timeout != 0) {
2523 g_source_remove(wifi->automaxspeed_timeout);
2524 wifi->automaxspeed_timeout = 0;
2528 /* In case of a user scan, device is still referenced */
2529 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) {
2530 connman_device_set_scanning(device,
2531 CONNMAN_SERVICE_TYPE_WIFI, false);
2532 connman_device_unref(wifi->device);
2535 #if defined TIZEN_EXT
2536 stop_autoscan(device);
2539 remove_networks(device, wifi);
2542 #if defined TIZEN_EXT
2543 wifi->scan_pending_network = NULL;
2545 if (is_wifi_notifier_registered == true) {
2546 connman_notifier_unregister(¬ifier);
2547 is_wifi_notifier_registered = false;
2551 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2555 return -EINPROGRESS;
2558 static int get_latest_connections(int max_ssids,
2559 GSupplicantScanParams *scan_data)
2561 GSequenceIter *iter;
2562 GSequence *latest_list;
2563 struct last_connected *entry;
2572 latest_list = g_sequence_new(free_entry);
2576 services = connman_storage_get_services();
2577 for (i = 0; services && services[i]; i++) {
2578 if (strncmp(services[i], "wifi_", 5) != 0)
2581 keyfile = connman_storage_load_service(services[i]);
2585 str = g_key_file_get_string(keyfile,
2586 services[i], "Favorite", NULL);
2587 if (!str || g_strcmp0(str, "true")) {
2589 g_key_file_free(keyfile);
2594 str = g_key_file_get_string(keyfile,
2595 services[i], "AutoConnect", NULL);
2596 if (!str || g_strcmp0(str, "true")) {
2598 g_key_file_free(keyfile);
2603 str = g_key_file_get_string(keyfile,
2604 services[i], "Modified", NULL);
2606 g_key_file_free(keyfile);
2609 g_time_val_from_iso8601(str, &modified);
2612 ssid = g_key_file_get_string(keyfile,
2613 services[i], "SSID", NULL);
2615 freq = g_key_file_get_integer(keyfile, services[i],
2618 entry = g_try_new(struct last_connected, 1);
2620 g_sequence_free(latest_list);
2621 g_key_file_free(keyfile);
2627 entry->modified = modified;
2630 g_sequence_insert_sorted(latest_list, entry,
2636 g_key_file_free(keyfile);
2639 g_strfreev(services);
2641 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2643 iter = g_sequence_get_begin_iter(latest_list);
2645 for (i = 0; i < num_ssids; i++) {
2646 entry = g_sequence_get(iter);
2648 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2649 entry->modified.tv_sec);
2651 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2652 max_ssids, entry->ssid);
2654 iter = g_sequence_iter_next(iter);
2657 g_sequence_free(latest_list);
2661 static void wifi_update_scanner_type(struct wifi_data *wifi,
2662 enum wifi_scanning_type new_type)
2666 if (!wifi || wifi->scanning_type == new_type)
2669 wifi->scanning_type = new_type;
2671 setup_autoscan(wifi);
2674 static int wifi_scan_simple(struct connman_device *device)
2676 struct wifi_data *wifi = connman_device_get_data(device);
2678 reset_autoscan(device);
2680 /* Distinguish between devices performing passive and active scanning */
2682 wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE);
2684 return throw_wifi_scan(device, scan_callback_hidden);
2687 static gboolean p2p_find_stop(gpointer data)
2689 struct connman_device *device = data;
2690 struct wifi_data *wifi = connman_device_get_data(device);
2695 wifi->p2p_find_timeout = 0;
2697 g_supplicant_interface_p2p_stop_find(wifi->interface);
2700 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2702 connman_device_unref(device);
2703 start_autoscan(device);
2708 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2711 struct connman_device *device = user_data;
2712 struct wifi_data *wifi = connman_device_get_data(device);
2714 DBG("result %d wifi %p", result, wifi);
2719 if (wifi->p2p_find_timeout) {
2720 g_source_remove(wifi->p2p_find_timeout);
2721 wifi->p2p_find_timeout = 0;
2727 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2728 p2p_find_stop, device);
2729 if (!wifi->p2p_find_timeout)
2734 p2p_find_stop(device);
2737 static int p2p_find(struct connman_device *device)
2739 struct wifi_data *wifi;
2744 if (!p2p_technology)
2747 wifi = connman_device_get_data(device);
2749 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2752 reset_autoscan(device);
2753 connman_device_ref(device);
2755 ret = g_supplicant_interface_p2p_find(wifi->interface,
2756 p2p_find_callback, device);
2758 connman_device_unref(device);
2759 start_autoscan(device);
2761 connman_device_set_scanning(device,
2762 CONNMAN_SERVICE_TYPE_P2P, true);
2768 #if defined TIZEN_EXT
2769 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2772 struct connman_device *device = user_data;
2773 struct wifi_data *wifi = connman_device_get_data(device);
2776 DBG("result %d wifi %p", result, wifi);
2778 if (wifi && wifi->scan_params) {
2779 g_supplicant_free_scan_params(wifi->scan_params);
2780 wifi->scan_params = NULL;
2783 scanning = connman_device_get_scanning(device,
2784 CONNMAN_SERVICE_TYPE_WIFI);
2786 connman_device_set_scanning(device,
2787 CONNMAN_SERVICE_TYPE_WIFI, false);
2788 connman_device_unref(device);
2792 static int wifi_specific_scan(enum connman_service_type type,
2793 struct connman_device *device, int scan_type,
2794 GSList *specific_scan_list, void *user_data)
2796 GSList *list = NULL;
2798 struct wifi_data *wifi = connman_device_get_data(device);
2799 GSupplicantScanParams *scan_params = NULL;
2800 struct scan_ssid *scan_ssid = NULL;
2809 if (wifi->p2p_device)
2812 if (type == CONNMAN_SERVICE_TYPE_P2P)
2813 return p2p_find(device);
2815 if (wifi->tethering)
2819 connman_device_get_scanning(device,
2820 CONNMAN_SERVICE_TYPE_WIFI);
2824 DBG("scan_type: %d", scan_type);
2825 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2826 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2828 DBG("Failed to allocate memory.");
2832 for (list = specific_scan_list; list; list = list->next) {
2833 ssid = (char *)list->data;
2834 int ssid_len = strlen(ssid);
2836 scan_ssid = g_try_new0(struct scan_ssid, 1);
2838 DBG("Failed to allocate memory.");
2839 g_supplicant_free_scan_params(scan_params);
2843 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2844 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2845 scan_ssid->ssid_len = ssid_len;
2846 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2849 scan_params->num_ssids = count;
2851 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2853 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2855 DBG("Failed to allocate memory.");
2859 guint num_freqs = g_slist_length(specific_scan_list);
2860 DBG("num_freqs: %d", num_freqs);
2862 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2863 if (!scan_params->freqs) {
2864 DBG("Failed to allocate memory.");
2865 g_free(scan_params);
2870 for (list = specific_scan_list; list; list = list->next) {
2871 freq = (int)list->data;
2873 scan_params->freqs[count] = freq;
2874 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2877 scan_params->num_freqs = count;
2879 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2880 int freq_count, ap_count;
2881 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2883 DBG("Failed to allocate memory.");
2887 guint size = g_slist_length(specific_scan_list);
2889 scan_params->freqs = g_try_new0(uint16_t, size/2);
2890 if (!scan_params->freqs) {
2891 DBG("Failed to allocate memory.");
2892 g_free(scan_params);
2896 ap_count = freq_count = 0;
2897 for (list = specific_scan_list; list; list = list->next) {
2898 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2899 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2900 int ssid_len = strlen(ssid);
2902 scan_ssid = g_try_new0(struct scan_ssid, 1);
2904 DBG("Failed to allocate memory.");
2905 g_supplicant_free_scan_params(scan_params);
2909 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2910 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2911 scan_ssid->ssid_len = ssid_len;
2912 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2916 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2917 scan_params->freqs[freq_count] = freq;
2918 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2922 scan_params->num_ssids = ap_count;
2923 scan_params->num_freqs = freq_count;
2925 DBG("Invalid scan");
2929 reset_autoscan(device);
2930 connman_device_ref(device);
2932 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2933 specific_scan_callback, device);
2936 connman_device_set_scanning(device,
2937 CONNMAN_SERVICE_TYPE_WIFI, true);
2939 g_supplicant_free_scan_params(scan_params);
2940 connman_device_unref(device);
2947 #if defined TIZEN_EXT_WIFI_MESH
2948 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2951 struct connman_device *device = user_data;
2952 struct wifi_data *wifi = connman_device_get_data(device);
2955 DBG("result %d wifi %p", result, wifi);
2957 scanning = connman_device_get_scanning(device,
2958 CONNMAN_SERVICE_TYPE_MESH);
2960 connman_device_set_scanning(device,
2961 CONNMAN_SERVICE_TYPE_MESH, false);
2964 connman_device_unref(device);
2967 static int mesh_scan(struct connman_device *device)
2969 struct wifi_data *wifi;
2970 struct wifi_mesh_info *mesh_info;
2975 wifi = connman_device_get_data(device);
2977 if (!wifi->mesh_interface)
2980 mesh_info = wifi->mesh_info;
2981 reset_autoscan(device);
2982 connman_device_ref(device);
2984 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2985 mesh_scan_callback, device);
2987 connman_device_unref(device);
2989 connman_device_set_scanning(device,
2990 CONNMAN_SERVICE_TYPE_MESH, true);
2995 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2998 struct connman_device *device = user_data;
2999 struct wifi_data *wifi = connman_device_get_data(device);
3001 DBG("result %d wifi %p", result, wifi);
3003 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
3006 static int mesh_abort_scan(enum connman_service_type type,
3007 struct connman_device *device)
3009 struct wifi_data *wifi = connman_device_get_data(device);
3010 struct wifi_mesh_info *mesh_info;
3014 if (!wifi || !wifi->mesh_interface)
3017 if (type != CONNMAN_SERVICE_TYPE_MESH)
3020 mesh_info = wifi->mesh_info;
3022 scanning = connman_device_get_scanning(device,
3023 CONNMAN_SERVICE_TYPE_MESH);
3027 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
3028 abort_scan_callback, device);
3033 static int mesh_specific_scan(enum connman_service_type type,
3034 struct connman_device *device, const char *ssid,
3035 unsigned int freq, void *user_data)
3037 struct wifi_data *wifi = connman_device_get_data(device);
3038 GSupplicantScanParams *scan_params = NULL;
3039 struct wifi_mesh_info *mesh_info;
3040 struct scan_ssid *scan_ssid;
3044 if (!wifi || !wifi->mesh_interface)
3047 if (type != CONNMAN_SERVICE_TYPE_MESH)
3050 if (wifi->p2p_device)
3053 mesh_info = wifi->mesh_info;
3055 scanning = connman_device_get_scanning(device,
3056 CONNMAN_SERVICE_TYPE_MESH);
3060 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3064 scan_ssid = g_try_new(struct scan_ssid, 1);
3066 g_free(scan_params);
3070 scan_ssid->ssid_len = strlen(ssid);
3071 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
3072 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3073 scan_params->num_ssids = 1;
3075 scan_params->freqs = g_try_new(uint16_t, 1);
3076 if (!scan_params->freqs) {
3077 g_slist_free_full(scan_params->ssids, g_free);
3078 g_free(scan_params);
3082 scan_params->freqs[0] = freq;
3083 scan_params->num_freqs = 1;
3085 reset_autoscan(device);
3086 connman_device_ref(device);
3088 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
3089 mesh_scan_callback, device);
3092 connman_device_set_scanning(device,
3093 CONNMAN_SERVICE_TYPE_MESH, true);
3095 g_supplicant_free_scan_params(scan_params);
3096 connman_device_unref(device);
3104 * Note that the hidden scan is only used when connecting to this specific
3105 * hidden AP first time. It is not used when system autoconnects to hidden AP.
3107 static int wifi_scan(struct connman_device *device,
3108 struct connman_device_scan_params *params)
3110 struct wifi_data *wifi = connman_device_get_data(device);
3111 GSupplicantScanParams *scan_params = NULL;
3112 struct scan_ssid *scan_ssid;
3113 struct hidden_params *hidden;
3115 int driver_max_ssids = 0;
3122 if (wifi->p2p_device)
3125 if (wifi->tethering)
3128 if (params->type == CONNMAN_SERVICE_TYPE_P2P)
3129 return p2p_find(device);
3131 #if defined TIZEN_EXT_WIFI_MESH
3132 if (params->type == CONNMAN_SERVICE_TYPE_MESH)
3133 return mesh_scan(device);
3136 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface,
3139 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
3141 if (!params->ssid || params->ssid_len == 0 || params->ssid_len > 32) {
3145 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
3147 DBG("max ssids %d", driver_max_ssids);
3148 if (driver_max_ssids == 0)
3149 return wifi_scan_simple(device);
3153 if (scanning && wifi->hidden && wifi->postpone_hidden)
3159 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3164 scan_ssid = g_try_new(struct scan_ssid, 1);
3166 g_free(scan_params);
3170 memcpy(scan_ssid->ssid, params->ssid, params->ssid_len);
3171 scan_ssid->ssid_len = params->ssid_len;
3172 scan_params->ssids = g_slist_prepend(scan_params->ssids,
3174 scan_params->num_ssids = 1;
3176 hidden = g_try_new0(struct hidden_params, 1);
3178 g_supplicant_free_scan_params(scan_params);
3183 hidden_free(wifi->hidden);
3184 wifi->hidden = NULL;
3187 memcpy(hidden->ssid, params->ssid, params->ssid_len);
3188 hidden->ssid_len = params->ssid_len;
3189 hidden->identity = g_strdup(params->identity);
3190 hidden->passphrase = g_strdup(params->passphrase);
3191 hidden->security = g_strdup(params->security);
3192 hidden->user_data = params->user_data;
3193 wifi->hidden = hidden;
3196 /* Let's keep this active scan for later,
3197 * when current scan will be over. */
3198 wifi->postpone_hidden = TRUE;
3199 hidden->scan_params = scan_params;
3203 } else if (wifi->connected) {
3204 g_supplicant_free_scan_params(scan_params);
3205 return wifi_scan_simple(device);
3206 } else if (!params->force_full_scan) {
3207 ret = get_latest_connections(driver_max_ssids, scan_params);
3209 g_supplicant_free_scan_params(scan_params);
3210 return wifi_scan_simple(device);
3214 /* Distinguish between devices performing passive and active scanning */
3215 wifi_update_scanner_type(wifi, WIFI_SCANNING_ACTIVE);
3217 connman_device_ref(device);
3219 reset_autoscan(device);
3221 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3222 scan_callback, device);
3224 connman_device_set_scanning(device,
3225 CONNMAN_SERVICE_TYPE_WIFI, true);
3226 #if defined TIZEN_EXT
3227 /*To allow the Full Scan after ssid based scan, set the flag here
3228 It is required because Tizen does not use the ConnMan specific
3229 backgroung Scan feature.Tizen has added the BG Scan feature in
3230 net-config. To sync with up ConnMan, we need to issue the Full Scan
3231 after SSID specific scan.*/
3232 wifi->allow_full_scan = TRUE;
3235 g_supplicant_free_scan_params(scan_params);
3236 connman_device_unref(device);
3239 hidden_free(wifi->hidden);
3240 wifi->hidden = NULL;
3247 static void wifi_stop_scan(enum connman_service_type type,
3248 struct connman_device *device)
3250 struct wifi_data *wifi = connman_device_get_data(device);
3252 DBG("device %p wifi %p", device, wifi);
3257 if (type == CONNMAN_SERVICE_TYPE_P2P) {
3258 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
3259 g_source_remove(wifi->p2p_find_timeout);
3260 p2p_find_stop(device);
3265 static void wifi_regdom_callback(int result,
3269 struct connman_device *device = user_data;
3271 connman_device_regdom_notify(device, result, alpha2);
3273 connman_device_unref(device);
3276 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3278 struct wifi_data *wifi = connman_device_get_data(device);
3284 connman_device_ref(device);
3286 ret = g_supplicant_interface_set_country(wifi->interface,
3287 wifi_regdom_callback,
3290 connman_device_unref(device);
3295 static struct connman_device_driver wifi_ng_driver = {
3297 .type = CONNMAN_DEVICE_TYPE_WIFI,
3298 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3299 .probe = wifi_probe,
3300 .remove = wifi_remove,
3301 .enable = wifi_enable,
3302 .disable = wifi_disable,
3304 .stop_scan = wifi_stop_scan,
3305 .set_regdom = wifi_set_regdom,
3306 #if defined TIZEN_EXT
3307 .specific_scan = wifi_specific_scan,
3309 #if defined TIZEN_EXT_WIFI_MESH
3310 .abort_scan = mesh_abort_scan,
3311 .mesh_specific_scan = mesh_specific_scan,
3315 static void system_ready(void)
3319 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3320 connman_error("Failed to register WiFi driver");
3323 static void system_killed(void)
3327 connman_device_driver_unregister(&wifi_ng_driver);
3330 static int network_probe(struct connman_network *network)
3332 DBG("network %p", network);
3337 static void network_remove(struct connman_network *network)
3339 struct connman_device *device = connman_network_get_device(network);
3340 struct wifi_data *wifi;
3342 DBG("network %p", network);
3344 wifi = connman_device_get_data(device);
3348 if (wifi->network != network)
3351 wifi->network = NULL;
3353 #if defined TIZEN_EXT
3354 wifi->disconnecting = false;
3356 if (wifi->pending_network == network)
3357 wifi->pending_network = NULL;
3359 if (wifi->scan_pending_network == network)
3360 wifi->scan_pending_network = NULL;
3364 static void connect_callback(int result, GSupplicantInterface *interface,
3367 #if defined TIZEN_EXT
3369 struct wifi_data *wifi;
3371 struct connman_network *network = user_data;
3373 DBG("network %p result %d", network, result);
3375 #if defined TIZEN_EXT
3376 set_connman_bssid(RESET_BSSID, NULL);
3378 for (list = iface_list; list; list = list->next) {
3381 if (wifi && wifi->network == network)
3385 /* wifi_data may be invalid because wifi is already disabled */
3390 if (result == -ENOKEY) {
3391 connman_network_set_error(network,
3392 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3393 } else if (result < 0) {
3394 connman_network_set_error(network,
3395 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3398 connman_network_unref(network);
3401 static GSupplicantSecurity network_security(const char *security)
3403 if (g_str_equal(security, "none"))
3404 return G_SUPPLICANT_SECURITY_NONE;
3405 else if (g_str_equal(security, "wep"))
3406 return G_SUPPLICANT_SECURITY_WEP;
3407 else if (g_str_equal(security, "psk"))
3408 return G_SUPPLICANT_SECURITY_PSK;
3409 else if (g_str_equal(security, "wpa"))
3410 return G_SUPPLICANT_SECURITY_PSK;
3411 else if (g_str_equal(security, "rsn"))
3412 return G_SUPPLICANT_SECURITY_PSK;
3413 else if (g_str_equal(security, "ieee8021x"))
3414 return G_SUPPLICANT_SECURITY_IEEE8021X;
3415 #if defined TIZEN_EXT
3416 else if (g_str_equal(security, "ft_psk") == TRUE)
3417 return G_SUPPLICANT_SECURITY_FT_PSK;
3418 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3419 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3420 else if (g_str_equal(security, "sae"))
3421 return G_SUPPLICANT_SECURITY_SAE;
3422 else if (g_str_equal(security, "owe"))
3423 return G_SUPPLICANT_SECURITY_OWE;
3424 else if (g_str_equal(security, "dpp"))
3425 return G_SUPPLICANT_SECURITY_DPP;
3428 return G_SUPPLICANT_SECURITY_UNKNOWN;
3431 #if defined TIZEN_EXT
3432 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3434 if (security == NULL)
3435 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3437 if (g_str_equal(security, "FT") == TRUE)
3438 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3439 else if (g_str_equal(security, "CCKM") == TRUE)
3440 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3442 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3446 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3448 const char *security;
3449 #if defined TIZEN_EXT
3450 const void *ssid_data;
3453 memset(ssid, 0, sizeof(*ssid));
3454 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3455 #if defined TIZEN_EXT
3456 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3458 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3463 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3465 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3468 ssid->scan_ssid = 1;
3469 security = connman_network_get_string(network, "WiFi.Security");
3470 ssid->security = network_security(security);
3471 #if defined TIZEN_EXT
3472 ssid->ieee80211w = 1;
3474 ssid->passphrase = connman_network_get_string(network,
3477 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3480 * If our private key password is unset,
3481 * we use the supplied passphrase. That is needed
3482 * for PEAP where 2 passphrases (identity and client
3483 * cert may have to be provided.
3485 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3486 connman_network_set_string(network,
3487 "WiFi.PrivateKeyPassphrase",
3489 /* We must have an identity for both PEAP and TLS */
3490 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3492 /* Use agent provided identity as a fallback */
3493 if (!ssid->identity || strlen(ssid->identity) == 0)
3494 ssid->identity = connman_network_get_string(network,
3495 "WiFi.AgentIdentity");
3497 ssid->anonymous_identity = connman_network_get_string(network,
3498 "WiFi.AnonymousIdentity");
3499 ssid->ca_cert_path = connman_network_get_string(network,
3501 ssid->subject_match = connman_network_get_string(network,
3502 "WiFi.SubjectMatch");
3503 ssid->altsubject_match = connman_network_get_string(network,
3504 "WiFi.AltSubjectMatch");
3505 ssid->domain_suffix_match = connman_network_get_string(network,
3506 "WiFi.DomainSuffixMatch");
3507 ssid->domain_match = connman_network_get_string(network,
3508 "WiFi.DomainMatch");
3509 ssid->client_cert_path = connman_network_get_string(network,
3510 "WiFi.ClientCertFile");
3511 ssid->private_key_path = connman_network_get_string(network,
3512 "WiFi.PrivateKeyFile");
3513 ssid->private_key_passphrase = connman_network_get_string(network,
3514 "WiFi.PrivateKeyPassphrase");
3515 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3517 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3518 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3519 #if defined TIZEN_EXT
3520 ssid->connector = connman_network_get_string(network,
3522 ssid->c_sign_key = connman_network_get_string(network,
3524 ssid->net_access_key = connman_network_get_string(network,
3525 "WiFi.NetAccessKey");
3528 #if defined TIZEN_EXT
3529 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3530 ssid->bssid_for_connect_len = 6;
3531 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3532 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3533 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3534 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3535 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3537 ssid->freq = connman_network_get_frequency(network);
3540 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3541 if (bssid_list && g_slist_length(bssid_list) > 1) {
3543 /* If there are more than one bssid,
3544 * the user-specified bssid is tried only once at the beginning.
3545 * After that, the bssids in the list are tried in order.
3547 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3548 set_connman_bssid(RESET_BSSID, NULL);
3553 char buff[MAC_ADDRESS_LENGTH];
3554 for (list = bssid_list; list; list = list->next) {
3555 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3557 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3558 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3559 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3560 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3562 gchar *curr_bssid = g_strdup((const gchar *)buff);
3564 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3565 DBG("bssid match, try next bssid");
3569 g_hash_table_add(failed_bssids, curr_bssid);
3571 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3572 ssid->bssid = buff_bssid;
3573 ssid->freq = (unsigned int)bssids->frequency;
3579 ssid->bssid = connman_network_get_bssid(network);
3580 g_hash_table_remove_all(failed_bssids);
3583 ssid->bssid = connman_network_get_bssid(network);
3586 ssid->eap_keymgmt = network_eap_keymgmt(
3587 connman_network_get_string(network, "WiFi.KeymgmtType"));
3588 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3590 if(g_strcmp0(ssid->eap, "fast") == 0)
3591 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3594 if (connman_setting_get_bool("BackgroundScanning"))
3595 ssid->bgscan = BGSCAN_DEFAULT;
3598 static int network_connect(struct connman_network *network)
3600 struct connman_device *device = connman_network_get_device(network);
3601 struct wifi_data *wifi;
3602 GSupplicantInterface *interface;
3603 GSupplicantSSID *ssid;
3605 DBG("network %p", network);
3610 wifi = connman_device_get_data(device);
3614 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3618 interface = wifi->interface;
3620 ssid_init(ssid, network);
3622 if (wifi->disconnecting) {
3623 wifi->pending_network = network;
3624 #if defined TIZEN_EXT
3629 wifi->network = connman_network_ref(network);
3631 #if defined TIZEN_EXT
3632 wifi->scan_pending_network = NULL;
3635 return g_supplicant_interface_connect(interface, ssid,
3636 connect_callback, network);
3639 return -EINPROGRESS;
3642 static void disconnect_callback(int result, GSupplicantInterface *interface,
3645 #if defined TIZEN_EXT
3647 struct wifi_data *wifi;
3648 struct connman_network *network = user_data;
3650 DBG("network %p result %d", network, result);
3652 for (list = iface_list; list; list = list->next) {
3655 if (wifi->network == NULL && wifi->disconnecting == true)
3656 wifi->disconnecting = false;
3658 if (wifi->network == network)
3662 /* wifi_data may be invalid because wifi is already disabled */
3667 struct wifi_data *wifi = user_data;
3670 DBG("result %d supplicant interface %p wifi %p",
3671 result, interface, wifi);
3673 if (result == -ECONNABORTED) {
3674 DBG("wifi interface no longer available");
3678 if (wifi->network != wifi->pending_network)
3679 connman_network_set_connected(wifi->network, false);
3680 wifi->network = NULL;
3682 wifi->disconnecting = false;
3683 wifi->connected = false;
3685 if (wifi->pending_network) {
3686 network_connect(wifi->pending_network);
3687 wifi->pending_network = NULL;
3690 start_autoscan(wifi->device);
3693 static int network_disconnect(struct connman_network *network)
3695 struct connman_device *device = connman_network_get_device(network);
3696 struct wifi_data *wifi;
3698 #if defined TIZEN_EXT
3699 struct connman_service *service;
3702 DBG("network %p", network);
3704 wifi = connman_device_get_data(device);
3705 if (!wifi || !wifi->interface)
3708 #if defined TIZEN_EXT
3709 if (connman_network_get_associating(network) == true) {
3710 connman_network_clear_associating(network);
3711 connman_network_set_bool(network, "WiFi.UseWPS", false);
3713 service = connman_service_lookup_from_network(network);
3715 if (service != NULL &&
3716 (__connman_service_is_connected_state(service,
3717 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3718 __connman_service_is_connected_state(service,
3719 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3720 (connman_service_get_favorite(service) == false))
3721 __connman_service_set_passphrase(service, NULL);
3724 if (wifi->pending_network == network)
3725 wifi->pending_network = NULL;
3727 if (wifi->scan_pending_network == network)
3728 wifi->scan_pending_network = NULL;
3731 connman_network_set_associating(network, false);
3733 if (wifi->disconnecting)
3736 wifi->disconnecting = true;
3738 #if defined TIZEN_EXT
3739 err = g_supplicant_interface_disconnect(wifi->interface,
3740 disconnect_callback, network);
3742 err = g_supplicant_interface_disconnect(wifi->interface,
3743 disconnect_callback, wifi);
3747 wifi->disconnecting = false;
3752 #if defined TIZEN_EXT
3753 static void set_connection_mode(struct connman_network *network,
3756 ieee80211_modes_e phy_mode;
3757 connection_mode_e conn_mode;
3759 phy_mode = connman_network_get_phy_mode(network);
3761 case IEEE80211_MODE_B:
3762 if (linkspeed > 0 && linkspeed <= 11)
3763 conn_mode = CONNECTION_MODE_IEEE80211B;
3765 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3768 case IEEE80211_MODE_BG:
3769 if (linkspeed > 0 && linkspeed <= 11)
3770 conn_mode = CONNECTION_MODE_IEEE80211B;
3771 else if (linkspeed > 11 && linkspeed <= 54)
3772 conn_mode = CONNECTION_MODE_IEEE80211G;
3774 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3777 case IEEE80211_MODE_BGN:
3778 if (linkspeed > 0 && linkspeed <= 11)
3779 conn_mode = CONNECTION_MODE_IEEE80211B;
3780 else if (linkspeed > 11 && linkspeed <= 54)
3781 conn_mode = CONNECTION_MODE_IEEE80211G;
3782 else if (linkspeed > 54 && linkspeed <= 450)
3783 conn_mode = CONNECTION_MODE_IEEE80211N;
3785 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3788 case IEEE80211_MODE_A:
3789 if (linkspeed > 0 && linkspeed <= 54)
3790 conn_mode = CONNECTION_MODE_IEEE80211A;
3792 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3795 case IEEE80211_MODE_AN:
3796 if (linkspeed > 0 && linkspeed <= 54)
3797 conn_mode = CONNECTION_MODE_IEEE80211A;
3798 else if (linkspeed > 54 && linkspeed <= 450)
3799 conn_mode = CONNECTION_MODE_IEEE80211N;
3801 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3804 case IEEE80211_MODE_ANAC:
3805 if (linkspeed > 0 && linkspeed <= 54)
3806 conn_mode = CONNECTION_MODE_IEEE80211A;
3807 else if (linkspeed > 54 && linkspeed <= 450)
3808 conn_mode = CONNECTION_MODE_IEEE80211N;
3809 else if (linkspeed > 450 && linkspeed <= 1300)
3810 conn_mode = CONNECTION_MODE_IEEE80211AC;
3812 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3816 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3820 DBG("connection mode(%d)", conn_mode);
3821 connman_network_set_connection_mode(network, conn_mode);
3824 static void signalpoll_callback(int result, int maxspeed, int strength,
3827 struct connman_network *network = user_data;
3830 DBG("Failed to get maxspeed from signalpoll !");
3838 DBG("maxspeed = %d, strength = %d", maxspeed, strength);
3840 connman_network_set_strength(network, (uint8_t)strength);
3841 connman_network_set_maxspeed(network, maxspeed);
3842 set_connection_mode(network, maxspeed);
3846 static int network_signalpoll(struct wifi_data *wifi)
3848 GSupplicantInterface *interface;
3849 struct connman_network *network;
3851 if (!wifi || !wifi->network)
3854 interface = wifi->interface;
3855 network = wifi->network;
3857 DBG("network %p", network);
3859 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3862 static gboolean autosignalpoll_timeout(gpointer data)
3864 struct wifi_data *wifi = data;
3866 if (!wifi || !wifi->automaxspeed_timeout) {
3867 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3871 int ret = network_signalpoll(wifi);
3873 DBG("Fail to get max speed !!");
3874 wifi->automaxspeed_timeout = 0;
3882 static struct connman_network_driver network_driver = {
3884 .type = CONNMAN_NETWORK_TYPE_WIFI,
3885 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3886 .probe = network_probe,
3887 .remove = network_remove,
3888 .connect = network_connect,
3889 .disconnect = network_disconnect,
3892 static void interface_added(GSupplicantInterface *interface)
3894 const char *ifname = g_supplicant_interface_get_ifname(interface);
3895 const char *driver = g_supplicant_interface_get_driver(interface);
3896 #if defined TIZEN_EXT
3897 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3900 struct wifi_data *wifi;
3902 wifi = g_supplicant_interface_get_data(interface);
3904 wifi = get_pending_wifi_data(ifname);
3908 wifi->interface = interface;
3909 g_supplicant_interface_set_data(interface, wifi);
3910 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3911 wifi->p2p_device = true;
3914 DBG("ifname %s driver %s wifi %p tethering %d",
3915 ifname, driver, wifi, wifi->tethering);
3917 if (!wifi->device) {
3918 connman_error("WiFi device not set");
3922 connman_device_set_powered(wifi->device, true);
3923 #if defined TIZEN_EXT
3924 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3925 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3926 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3927 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3931 static bool is_idle(struct wifi_data *wifi)
3933 DBG("state %d", wifi->state);
3935 switch (wifi->state) {
3936 case G_SUPPLICANT_STATE_UNKNOWN:
3937 case G_SUPPLICANT_STATE_DISABLED:
3938 case G_SUPPLICANT_STATE_DISCONNECTED:
3939 case G_SUPPLICANT_STATE_INACTIVE:
3940 case G_SUPPLICANT_STATE_SCANNING:
3943 case G_SUPPLICANT_STATE_AUTHENTICATING:
3944 case G_SUPPLICANT_STATE_ASSOCIATING:
3945 case G_SUPPLICANT_STATE_ASSOCIATED:
3946 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3947 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3948 case G_SUPPLICANT_STATE_COMPLETED:
3955 static bool is_idle_wps(GSupplicantInterface *interface,
3956 struct wifi_data *wifi)
3958 /* First, let's check if WPS processing did not went wrong */
3959 if (g_supplicant_interface_get_wps_state(interface) ==
3960 G_SUPPLICANT_WPS_STATE_FAIL)
3963 /* Unlike normal connection, being associated while processing wps
3964 * actually means that we are idling. */
3965 switch (wifi->state) {
3966 case G_SUPPLICANT_STATE_UNKNOWN:
3967 case G_SUPPLICANT_STATE_DISABLED:
3968 case G_SUPPLICANT_STATE_DISCONNECTED:
3969 case G_SUPPLICANT_STATE_INACTIVE:
3970 case G_SUPPLICANT_STATE_SCANNING:
3971 case G_SUPPLICANT_STATE_ASSOCIATED:
3973 case G_SUPPLICANT_STATE_AUTHENTICATING:
3974 case G_SUPPLICANT_STATE_ASSOCIATING:
3975 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3976 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3977 case G_SUPPLICANT_STATE_COMPLETED:
3984 static bool handle_wps_completion(GSupplicantInterface *interface,
3985 struct connman_network *network,
3986 struct connman_device *device,
3987 struct wifi_data *wifi)
3991 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3993 const unsigned char *ssid, *wps_ssid;
3994 unsigned int ssid_len, wps_ssid_len;
3995 const char *wps_key;
3997 /* Checking if we got associated with requested
3999 ssid = connman_network_get_blob(network, "WiFi.SSID",
4002 wps_ssid = g_supplicant_interface_get_wps_ssid(
4003 interface, &wps_ssid_len);
4005 if (!wps_ssid || wps_ssid_len != ssid_len ||
4006 memcmp(ssid, wps_ssid, ssid_len) != 0) {
4007 connman_network_set_associating(network, false);
4008 #if defined TIZEN_EXT
4009 g_supplicant_interface_disconnect(wifi->interface,
4010 disconnect_callback, wifi->network);
4012 connman_network_set_bool(network, "WiFi.UseWPS", false);
4013 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4015 g_supplicant_interface_disconnect(wifi->interface,
4016 disconnect_callback, wifi);
4021 wps_key = g_supplicant_interface_get_wps_key(interface);
4022 #if defined TIZEN_EXT
4023 /* Check the passphrase and encrypt it
4026 gchar *passphrase = g_strdup(wps_key);
4028 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4030 if (check_passphrase_ext(network, passphrase) < 0) {
4031 DBG("[WPS] Invalid passphrase");
4036 ret = send_encryption_request(passphrase, network);
4041 DBG("[WPS] Encryption request succeeded");
4043 DBG("[WPS] Encryption request failed %d", ret);
4046 connman_network_set_string(network, "WiFi.Passphrase",
4049 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4056 static bool handle_assoc_status_code(GSupplicantInterface *interface,
4057 struct wifi_data *wifi)
4059 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
4060 #if defined TIZEN_EXT
4061 wifi->assoc_code > 0 &&
4063 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
4065 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
4066 wifi->load_shaping_retries ++;
4069 wifi->load_shaping_retries = 0;
4073 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
4074 struct connman_network *network,
4075 struct wifi_data *wifi)
4077 #if defined TIZEN_EXT
4078 const char *security;
4079 struct connman_service *service;
4081 if (wifi->connected)
4084 security = connman_network_get_string(network, "WiFi.Security");
4086 if (security && g_str_equal(security, "ieee8021x") == true &&
4087 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4089 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4094 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4097 struct connman_service *service;
4099 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4102 if (wifi->connected)
4106 service = connman_service_lookup_from_network(network);
4112 if (connman_service_get_favorite(service)) {
4113 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
4118 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4123 #if defined TIZEN_EXT
4124 static bool handle_wifi_assoc_retry(struct connman_network *network,
4125 struct wifi_data *wifi)
4127 const char *security;
4129 if (!wifi->network || wifi->connected || wifi->disconnecting ||
4130 connman_network_get_connecting(network) != true) {
4131 wifi->assoc_retry_count = 0;
4135 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
4136 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
4137 wifi->assoc_retry_count = 0;
4141 security = connman_network_get_string(network, "WiFi.Security");
4142 if (security && g_str_equal(security, "ieee8021x") == true &&
4143 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4144 wifi->assoc_retry_count = 0;
4148 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
4149 wifi->assoc_retry_count = 0;
4151 /* Honestly it's not an invalid-key error,
4152 * however QA team recommends that the invalid-key error
4153 * might be better to display for user experience.
4155 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
4164 static void interface_state(GSupplicantInterface *interface)
4166 struct connman_network *network;
4167 struct connman_device *device;
4168 struct wifi_data *wifi;
4169 GSupplicantState state = g_supplicant_interface_get_state(interface);
4173 wifi = g_supplicant_interface_get_data(interface);
4175 DBG("wifi %p interface state %d", wifi, state);
4180 device = wifi->device;
4184 if (state == G_SUPPLICANT_STATE_COMPLETED) {
4185 if (wifi->tethering_param) {
4186 g_free(wifi->tethering_param->ssid);
4187 g_free(wifi->tethering_param);
4188 wifi->tethering_param = NULL;
4191 if (wifi->tethering)
4192 stop_autoscan(device);
4195 if (g_supplicant_interface_get_ready(interface) &&
4196 !wifi->interface_ready) {
4197 wifi->interface_ready = true;
4198 finalize_interface_creation(wifi);
4201 network = wifi->network;
4206 case G_SUPPLICANT_STATE_SCANNING:
4207 if (wifi->connected)
4208 connman_network_set_connected(network, false);
4212 case G_SUPPLICANT_STATE_AUTHENTICATING:
4213 case G_SUPPLICANT_STATE_ASSOCIATING:
4214 #if defined TIZEN_EXT
4215 reset_autoscan(device);
4217 stop_autoscan(device);
4220 if (!wifi->connected)
4221 connman_network_set_associating(network, true);
4225 case G_SUPPLICANT_STATE_COMPLETED:
4226 #if defined TIZEN_EXT
4227 /* though it should be already reset: */
4228 reset_autoscan(device);
4230 wifi->assoc_retry_count = 0;
4232 wifi->scan_pending_network = NULL;
4234 /* should be cleared scanning flag */
4235 bool scanning = connman_device_get_scanning(device,
4236 CONNMAN_SERVICE_TYPE_WIFI);
4238 connman_device_set_scanning(device,
4239 CONNMAN_SERVICE_TYPE_WIFI, false);
4240 connman_device_unref(device);
4243 if (!wifi->automaxspeed_timeout) {
4244 DBG("Going to start signalpoll timer!!");
4245 int ret = network_signalpoll(wifi);
4247 DBG("Fail to get max speed !!");
4249 wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
4252 g_hash_table_remove_all(failed_bssids);
4254 /* though it should be already stopped: */
4255 stop_autoscan(device);
4258 if (!handle_wps_completion(interface, network, device, wifi))
4261 connman_network_set_connected(network, true);
4263 wifi->disconnect_code = 0;
4264 wifi->assoc_code = 0;
4265 wifi->load_shaping_retries = 0;
4268 case G_SUPPLICANT_STATE_DISCONNECTED:
4269 #if defined TIZEN_EXT
4270 connman_network_set_strength(network, 0);
4271 connman_network_set_maxspeed(network, 0);
4273 if (wifi->automaxspeed_timeout != 0) {
4274 g_source_remove(wifi->automaxspeed_timeout);
4275 wifi->automaxspeed_timeout = 0;
4276 DBG("Remove signalpoll timer!!");
4280 * If we're in one of the idle modes, we have
4281 * not started association yet and thus setting
4282 * those ones to FALSE could cancel an association
4285 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4287 if (is_idle_wps(interface, wifi))
4293 #if defined TIZEN_EXT
4294 if (handle_assoc_status_code(interface, wifi)) {
4295 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4296 guint bssid_length = 0;
4299 bssid_length = g_slist_length(bssid_list);
4301 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4302 network_connect(network);
4306 wifi->load_shaping_retries = 0;
4309 g_hash_table_remove_all(failed_bssids);
4311 if (handle_assoc_status_code(interface, wifi))
4315 /* If previous state was 4way-handshake, then
4316 * it's either: psk was incorrect and thus we retry
4317 * or if we reach the maximum retries we declare the
4319 if (handle_4way_handshake_failure(interface,
4323 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4324 switch (wifi->disconnect_code) {
4325 case 1: /* Unspecified reason */
4326 /* Let's assume it's because we got blocked */
4328 case 6: /* Class 2 frame received from nonauthenticated STA */
4329 connman_network_set_error(network,
4330 CONNMAN_NETWORK_ERROR_BLOCKED);
4337 #if defined TIZEN_EXT
4338 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4339 * Retry association until its retry count is expired */
4340 if (handle_wifi_assoc_retry(network, wifi) == true) {
4341 throw_wifi_scan(wifi->device, scan_callback);
4342 wifi->scan_pending_network = wifi->network;
4346 if(wifi->disconnect_code > 0){
4347 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4348 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4352 if (network != wifi->pending_network) {
4353 connman_network_set_connected(network, false);
4354 connman_network_set_associating(network, false);
4356 wifi->disconnecting = false;
4358 start_autoscan(device);
4362 case G_SUPPLICANT_STATE_INACTIVE:
4363 #if defined TIZEN_EXT
4364 if (handle_wps_completion(interface, network, device, wifi) == false)
4367 connman_network_set_associating(network, false);
4368 start_autoscan(device);
4372 case G_SUPPLICANT_STATE_UNKNOWN:
4373 case G_SUPPLICANT_STATE_DISABLED:
4374 case G_SUPPLICANT_STATE_ASSOCIATED:
4375 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4376 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4380 old_connected = wifi->connected;
4381 wifi->state = state;
4383 /* Saving wpa_s state policy:
4384 * If connected and if the state changes are roaming related:
4385 * --> We stay connected
4387 * --> We are connected
4389 * --> We are not connected
4392 case G_SUPPLICANT_STATE_AUTHENTICATING:
4393 case G_SUPPLICANT_STATE_ASSOCIATING:
4394 case G_SUPPLICANT_STATE_ASSOCIATED:
4395 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4396 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4397 if (wifi->connected)
4398 connman_warn("Probably roaming right now!"
4399 " Staying connected...");
4401 case G_SUPPLICANT_STATE_SCANNING:
4402 wifi->connected = false;
4405 start_autoscan(device);
4407 case G_SUPPLICANT_STATE_COMPLETED:
4408 wifi->connected = true;
4411 wifi->connected = false;
4418 static void interface_removed(GSupplicantInterface *interface)
4420 const char *ifname = g_supplicant_interface_get_ifname(interface);
4421 struct wifi_data *wifi;
4423 DBG("ifname %s", ifname);
4425 wifi = g_supplicant_interface_get_data(interface);
4427 #if defined TIZEN_EXT_WIFI_MESH
4428 if (wifi && wifi->mesh_interface) {
4429 DBG("Notify mesh interface remove");
4430 connman_mesh_notify_interface_remove(true);
4431 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4432 g_free(mesh_info->parent_ifname);
4433 g_free(mesh_info->ifname);
4434 g_free(mesh_info->identifier);
4436 wifi->mesh_interface = false;
4437 wifi->mesh_info = NULL;
4443 wifi->interface = NULL;
4445 if (wifi && wifi->tethering)
4448 if (!wifi || !wifi->device) {
4449 DBG("wifi interface already removed");
4453 connman_device_set_powered(wifi->device, false);
4455 check_p2p_technology();
4456 #if defined TIZEN_EXT_WIFI_MESH
4457 check_mesh_technology();
4461 static void set_device_type(const char *type, char dev_type[17])
4463 const char *oui = "0050F204";
4464 const char *category = "0001";
4465 const char *sub_category = "0000";
4467 if (!g_strcmp0(type, "handset")) {
4469 sub_category = "0005";
4470 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4471 sub_category = "0001";
4472 else if (!g_strcmp0(type, "server"))
4473 sub_category = "0002";
4474 else if (!g_strcmp0(type, "laptop"))
4475 sub_category = "0005";
4476 else if (!g_strcmp0(type, "desktop"))
4477 sub_category = "0006";
4478 else if (!g_strcmp0(type, "tablet"))
4479 sub_category = "0009";
4480 else if (!g_strcmp0(type, "watch"))
4483 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4486 static void p2p_support(GSupplicantInterface *interface)
4488 char dev_type[17] = {};
4489 const char *hostname;
4496 if (!g_supplicant_interface_has_p2p(interface))
4499 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4500 DBG("Could not register P2P technology driver");
4504 hostname = connman_utsname_get_hostname();
4506 hostname = "ConnMan";
4508 set_device_type(connman_machine_get_type(), dev_type);
4509 g_supplicant_interface_set_p2p_device_config(interface,
4510 hostname, dev_type);
4511 connman_peer_driver_register(&peer_driver);
4514 static void scan_started(GSupplicantInterface *interface)
4519 static void scan_finished(GSupplicantInterface *interface)
4521 #if defined TIZEN_EXT
4522 struct wifi_data *wifi;
4523 bool is_associating = false;
4524 static bool is_scanning = true;
4529 #if defined TIZEN_EXT
4530 wifi = g_supplicant_interface_get_data(interface);
4531 if (wifi && wifi->scan_pending_network) {
4532 network_connect(wifi->scan_pending_network);
4533 wifi->scan_pending_network = NULL;
4536 //service state - associating
4537 if(!wifi || !wifi->network)
4540 is_associating = connman_network_get_associating(wifi->network);
4541 if(is_associating && is_scanning){
4542 is_scanning = false;
4543 DBG("send scan for connecting");
4544 throw_wifi_scan(wifi->device, scan_callback);
4555 static void ap_create_fail(GSupplicantInterface *interface)
4557 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4560 if ((wifi->tethering) && (wifi->tethering_param)) {
4561 DBG("%s create AP fail \n",
4562 g_supplicant_interface_get_ifname(wifi->interface));
4564 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4565 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4566 wifi->tethering = false;
4568 ret = tech_set_tethering(wifi->tethering_param->technology,
4569 wifi->tethering_param->ssid->ssid,
4570 wifi->tethering_param->ssid->passphrase,
4571 wifi->bridge, true);
4573 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4574 connman_technology_tethering_notify(wifi_technology,false);
4577 g_free(wifi->tethering_param->ssid);
4578 g_free(wifi->tethering_param);
4579 wifi->tethering_param = NULL;
4583 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4585 unsigned char strength;
4587 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4588 #if !defined TIZEN_EXT
4596 #if defined TIZEN_EXT_WIFI_MESH
4597 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4599 GSupplicantInterface *interface;
4600 struct wifi_data *wifi;
4601 const char *name, *security;
4602 struct connman_mesh *connman_mesh;
4603 struct wifi_mesh_info *mesh_info;
4604 const unsigned char *bssid;
4605 const char *identifier;
4610 interface = g_supplicant_network_get_interface(supplicant_network);
4611 wifi = g_supplicant_interface_get_data(interface);
4612 if (!wifi || !wifi->mesh_interface) {
4613 DBG("Virtual Mesh interface not created");
4617 bssid = g_supplicant_network_get_bssid(supplicant_network);
4618 address = g_malloc0(19);
4619 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4620 bssid[2], bssid[3], bssid[4], bssid[5]);
4622 identifier = g_supplicant_network_get_identifier(supplicant_network);
4623 name = g_supplicant_network_get_name(supplicant_network);
4624 security = g_supplicant_network_get_security(supplicant_network);
4625 frequency = g_supplicant_network_get_frequency(supplicant_network);
4627 mesh_info = wifi->mesh_info;
4628 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4632 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4634 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4635 connman_mesh_set_name(connman_mesh, name);
4636 connman_mesh_set_security(connman_mesh, security);
4637 connman_mesh_set_frequency(connman_mesh, frequency);
4638 connman_mesh_set_address(connman_mesh, address);
4639 connman_mesh_set_index(connman_mesh, mesh_info->index);
4640 connman_mesh_set_strength(connman_mesh,
4641 calculate_strength(supplicant_network));
4642 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4644 ret = connman_mesh_register(connman_mesh);
4645 if (ret == -EALREADY)
4646 DBG("Mesh Peer is already registered");
4652 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4654 GSupplicantInterface *interface;
4655 struct wifi_data *wifi;
4656 struct connman_mesh *connman_mesh;
4657 struct wifi_mesh_info *mesh_info;
4658 const char *identifier;
4660 interface = g_supplicant_network_get_interface(supplicant_network);
4661 wifi = g_supplicant_interface_get_data(interface);
4662 if (!wifi || !wifi->mesh_interface) {
4663 DBG("Virtual Mesh interface not created");
4667 identifier = g_supplicant_network_get_identifier(supplicant_network);
4669 DBG("Failed to get Mesh Peer identifier");
4673 mesh_info = wifi->mesh_info;
4674 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4676 /* Do not unregister connected mesh peer */
4677 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4678 DBG("Mesh Peer %s is connected", identifier);
4681 DBG("Mesh Peer identifier %s removed", identifier);
4682 connman_mesh_unregister(connman_mesh);
4687 static void network_added(GSupplicantNetwork *supplicant_network)
4689 struct connman_network *network;
4690 GSupplicantInterface *interface;
4691 struct wifi_data *wifi;
4692 const char *name, *identifier, *security, *group, *mode;
4693 const unsigned char *ssid;
4694 unsigned int ssid_len;
4698 bool wps_advertizing;
4700 #if defined TIZEN_EXT
4701 GSList *vsie_list = NULL;
4702 const unsigned char *country_code;
4703 ieee80211_modes_e phy_mode;
4706 mode = g_supplicant_network_get_mode(supplicant_network);
4707 identifier = g_supplicant_network_get_identifier(supplicant_network);
4709 DBG("%s", identifier);
4711 if (!g_strcmp0(mode, "adhoc"))
4714 #if defined TIZEN_EXT_WIFI_MESH
4715 if (!g_strcmp0(mode, "mesh")) {
4716 mesh_peer_added(supplicant_network);
4721 interface = g_supplicant_network_get_interface(supplicant_network);
4722 wifi = g_supplicant_interface_get_data(interface);
4723 name = g_supplicant_network_get_name(supplicant_network);
4724 security = g_supplicant_network_get_security(supplicant_network);
4725 group = g_supplicant_network_get_identifier(supplicant_network);
4726 wps = g_supplicant_network_get_wps(supplicant_network);
4727 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4728 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4729 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4730 supplicant_network);
4735 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4737 network = connman_device_get_network(wifi->device, identifier);
4740 network = connman_network_create(identifier,
4741 CONNMAN_NETWORK_TYPE_WIFI);
4745 connman_network_set_index(network, wifi->index);
4747 if (connman_device_add_network(wifi->device, network) < 0) {
4748 connman_network_unref(network);
4752 wifi->networks = g_slist_prepend(wifi->networks, network);
4755 if (name && name[0] != '\0')
4756 connman_network_set_name(network, name);
4758 connman_network_set_blob(network, "WiFi.SSID",
4760 #if defined TIZEN_EXT
4761 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4763 connman_network_set_vsie_list(network, vsie_list);
4765 DBG("vsie_list is NULL");
4766 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4767 connman_network_set_countrycode(network, country_code);
4768 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4769 connman_network_set_phy_mode(network, phy_mode);
4771 connman_network_set_string(network, "WiFi.Security", security);
4772 connman_network_set_strength(network,
4773 calculate_strength(supplicant_network));
4774 connman_network_set_bool(network, "WiFi.WPS", wps);
4775 connman_network_set_bool(network, "WiFi.WPSAdvertising",
4779 /* Is AP advertizing for WPS association?
4780 * If so, we decide to use WPS by default */
4781 if (wps_ready && wps_pbc &&
4783 #if !defined TIZEN_EXT
4784 connman_network_set_bool(network, "WiFi.UseWPS", true);
4786 DBG("wps is activating by ap but ignore it.");
4790 connman_network_set_frequency(network,
4791 g_supplicant_network_get_frequency(supplicant_network));
4793 #if defined TIZEN_EXT
4794 connman_network_set_bssid(network,
4795 g_supplicant_network_get_bssid(supplicant_network));
4796 connman_network_set_maxrate(network,
4797 g_supplicant_network_get_maxrate(supplicant_network));
4798 connman_network_set_enc_mode(network,
4799 g_supplicant_network_get_enc_mode(supplicant_network));
4800 connman_network_set_rsn_mode(network,
4801 g_supplicant_network_get_rsn_mode(supplicant_network));
4802 connman_network_set_keymgmt(network,
4803 g_supplicant_network_get_keymgmt(supplicant_network));
4804 connman_network_set_bool(network, "WiFi.HS20AP",
4805 g_supplicant_network_is_hs20AP(supplicant_network));
4806 connman_network_set_bssid_list(network,
4807 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4809 connman_network_set_available(network, true);
4810 connman_network_set_string(network, "WiFi.Mode", mode);
4812 #if defined TIZEN_EXT
4817 connman_network_set_group(network, group);
4819 #if defined TIZEN_EXT
4820 if (wifi_first_scan == true)
4821 found_with_first_scan = true;
4824 if (wifi->hidden && ssid) {
4825 #if defined TIZEN_EXT
4826 if (network_security(wifi->hidden->security) ==
4827 network_security(security) &&
4829 if (!g_strcmp0(wifi->hidden->security, security) &&
4831 wifi->hidden->ssid_len == ssid_len &&
4832 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4833 connman_network_connect_hidden(network,
4834 wifi->hidden->identity,
4835 wifi->hidden->passphrase,
4836 wifi->hidden->user_data);
4837 wifi->hidden->user_data = NULL;
4838 hidden_free(wifi->hidden);
4839 wifi->hidden = NULL;
4844 static void network_removed(GSupplicantNetwork *network)
4846 GSupplicantInterface *interface;
4847 struct wifi_data *wifi;
4848 const char *name, *identifier;
4849 struct connman_network *connman_network;
4851 #if defined TIZEN_EXT_WIFI_MESH
4853 mode = g_supplicant_network_get_mode(network);
4854 if (!g_strcmp0(mode, "mesh")) {
4855 mesh_peer_removed(network);
4860 interface = g_supplicant_network_get_interface(network);
4861 wifi = g_supplicant_interface_get_data(interface);
4862 identifier = g_supplicant_network_get_identifier(network);
4863 name = g_supplicant_network_get_name(network);
4865 DBG("name %s", name);
4870 connman_network = connman_device_get_network(wifi->device, identifier);
4871 if (!connman_network)
4874 #if defined TIZEN_EXT
4875 if (connman_network == wifi->scan_pending_network)
4876 wifi->scan_pending_network = NULL;
4878 if (connman_network == wifi->pending_network)
4879 wifi->pending_network = NULL;
4881 if(connman_network_get_connecting(connman_network) == true){
4882 connman_network_set_connected(connman_network, false);
4886 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4888 connman_device_remove_network(wifi->device, connman_network);
4889 connman_network_unref(connman_network);
4892 static void network_changed(GSupplicantNetwork *network, const char *property)
4894 GSupplicantInterface *interface;
4895 struct wifi_data *wifi;
4896 const char *name, *identifier;
4897 struct connman_network *connman_network;
4900 #if defined TIZEN_EXT
4901 const unsigned char *bssid;
4902 unsigned int maxrate;
4905 const unsigned char *country_code;
4906 ieee80211_modes_e phy_mode;
4910 interface = g_supplicant_network_get_interface(network);
4911 wifi = g_supplicant_interface_get_data(interface);
4912 identifier = g_supplicant_network_get_identifier(network);
4913 name = g_supplicant_network_get_name(network);
4915 DBG("name %s", name);
4920 connman_network = connman_device_get_network(wifi->device, identifier);
4921 if (!connman_network)
4924 if (g_str_equal(property, "WPSCapabilities")) {
4928 bool wps_advertizing;
4930 wps = g_supplicant_network_get_wps(network);
4931 wps_pbc = g_supplicant_network_is_wps_pbc(network);
4932 wps_ready = g_supplicant_network_is_wps_active(network);
4934 g_supplicant_network_is_wps_advertizing(network);
4936 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4937 connman_network_set_bool(connman_network,
4938 "WiFi.WPSAdvertising", wps_advertizing);
4942 * Is AP advertizing for WPS association?
4943 * If so, we decide to use WPS by default
4945 if (wps_ready && wps_pbc && wps_advertizing)
4946 connman_network_set_bool(connman_network,
4947 "WiFi.UseWPS", true);
4950 update_needed = true;
4951 } else if (g_str_equal(property, "Signal")) {
4952 connman_network_set_strength(connman_network,
4953 calculate_strength(network));
4954 update_needed = true;
4956 update_needed = false;
4959 connman_network_update(connman_network);
4961 #if defined TIZEN_EXT
4962 bssid = g_supplicant_network_get_bssid(network);
4963 maxrate = g_supplicant_network_get_maxrate(network);
4964 frequency = g_supplicant_network_get_frequency(network);
4965 wps = g_supplicant_network_get_wps(network);
4966 phy_mode = g_supplicant_network_get_phy_mode(network);
4968 connman_network_set_bssid(connman_network, bssid);
4969 connman_network_set_maxrate(connman_network, maxrate);
4970 connman_network_set_frequency(connman_network, frequency);
4971 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4972 country_code = g_supplicant_network_get_countrycode(network);
4973 connman_network_set_countrycode(connman_network, country_code);
4974 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4975 connman_network_set_bssid_list(connman_network, bssid_list);
4976 connman_network_set_phy_mode(connman_network, phy_mode);
4978 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4979 connman_network_get_associating(connman_network))
4980 network_connect(connman_network);
4984 static void network_associated(GSupplicantNetwork *network)
4986 GSupplicantInterface *interface;
4987 struct wifi_data *wifi;
4988 struct connman_network *connman_network;
4989 const char *identifier;
4993 interface = g_supplicant_network_get_interface(network);
4997 wifi = g_supplicant_interface_get_data(interface);
5001 /* P2P networks must not be treated as WiFi networks */
5002 if (wifi->p2p_connecting || wifi->p2p_device)
5005 identifier = g_supplicant_network_get_identifier(network);
5007 connman_network = connman_device_get_network(wifi->device, identifier);
5008 if (!connman_network)
5011 if (wifi->network) {
5012 if (wifi->network == connman_network)
5016 * This should never happen, we got associated with
5017 * a network different than the one we were expecting.
5019 DBG("Associated to %p while expecting %p",
5020 connman_network, wifi->network);
5022 connman_network_set_associating(wifi->network, false);
5025 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
5027 wifi->network = connman_network_ref(connman_network);
5031 * Interface state changes callback (interface_state) is always
5032 * called before network_associated callback thus we need to call
5033 * interface_state again in order to process the new state now that
5034 * we have the network properly set.
5036 interface_state(interface);
5039 static void sta_authorized(GSupplicantInterface *interface,
5042 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5044 DBG("wifi %p station %s authorized", wifi, addr);
5046 if (!wifi || !wifi->tethering)
5049 __connman_tethering_client_register(addr);
5052 static void sta_deauthorized(GSupplicantInterface *interface,
5055 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5057 DBG("wifi %p station %s deauthorized", wifi, addr);
5059 if (!wifi || !wifi->tethering)
5062 __connman_tethering_client_unregister(addr);
5065 static void apply_peer_services(GSupplicantPeer *peer,
5066 struct connman_peer *connman_peer)
5068 const unsigned char *data;
5073 connman_peer_reset_services(connman_peer);
5075 data = g_supplicant_peer_get_widi_ies(peer, &length);
5077 connman_peer_add_service(connman_peer,
5078 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
5082 static void peer_found(GSupplicantPeer *peer)
5084 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5085 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5086 struct connman_peer *connman_peer;
5087 const char *identifier, *name;
5090 #if defined TIZEN_EXT
5094 identifier = g_supplicant_peer_get_identifier(peer);
5095 name = g_supplicant_peer_get_name(peer);
5097 DBG("ident: %s", identifier);
5099 connman_peer = connman_peer_get(wifi->device, identifier);
5103 connman_peer = connman_peer_create(identifier);
5104 connman_peer_set_name(connman_peer, name);
5105 connman_peer_set_device(connman_peer, wifi->device);
5106 apply_peer_services(peer, connman_peer);
5108 ret = connman_peer_register(connman_peer);
5109 if (ret < 0 && ret != -EALREADY)
5110 connman_peer_unref(connman_peer);
5112 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
5115 static void peer_lost(GSupplicantPeer *peer)
5117 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5118 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5119 struct connman_peer *connman_peer;
5120 const char *identifier;
5125 identifier = g_supplicant_peer_get_identifier(peer);
5127 DBG("ident: %s", identifier);
5129 connman_peer = connman_peer_get(wifi->device, identifier);
5131 if (wifi->p2p_connecting &&
5132 wifi->pending_peer == connman_peer) {
5133 peer_connect_timeout(wifi);
5135 connman_peer_unregister(connman_peer);
5136 connman_peer_unref(connman_peer);
5139 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
5142 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
5144 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5145 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5146 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
5147 struct connman_peer *connman_peer;
5148 const char *identifier;
5150 identifier = g_supplicant_peer_get_identifier(peer);
5152 DBG("ident: %s", identifier);
5157 connman_peer = connman_peer_get(wifi->device, identifier);
5162 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
5163 apply_peer_services(peer, connman_peer);
5164 connman_peer_services_changed(connman_peer);
5166 case G_SUPPLICANT_PEER_GROUP_CHANGED:
5167 if (!g_supplicant_peer_is_in_a_group(peer))
5168 p_state = CONNMAN_PEER_STATE_IDLE;
5170 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
5172 case G_SUPPLICANT_PEER_GROUP_STARTED:
5174 case G_SUPPLICANT_PEER_GROUP_FINISHED:
5175 p_state = CONNMAN_PEER_STATE_IDLE;
5177 case G_SUPPLICANT_PEER_GROUP_JOINED:
5178 connman_peer_set_iface_address(connman_peer,
5179 g_supplicant_peer_get_iface_address(peer));
5181 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
5182 p_state = CONNMAN_PEER_STATE_IDLE;
5184 case G_SUPPLICANT_PEER_GROUP_FAILED:
5185 if (g_supplicant_peer_has_requested_connection(peer))
5186 p_state = CONNMAN_PEER_STATE_IDLE;
5188 p_state = CONNMAN_PEER_STATE_FAILURE;
5192 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
5193 p_state == CONNMAN_PEER_STATE_FAILURE) {
5194 if (wifi->p2p_connecting
5195 && connman_peer == wifi->pending_peer)
5196 peer_cancel_timeout(wifi);
5198 p_state = CONNMAN_PEER_STATE_UNKNOWN;
5201 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
5204 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
5205 GSupplicantInterface *g_iface;
5206 struct wifi_data *g_wifi;
5208 g_iface = g_supplicant_peer_get_group_interface(peer);
5212 g_wifi = g_supplicant_interface_get_data(g_iface);
5216 connman_peer_set_as_master(connman_peer,
5217 !g_supplicant_peer_is_client(peer));
5218 connman_peer_set_sub_device(connman_peer, g_wifi->device);
5221 * If wpa_supplicant didn't create a dedicated p2p-group
5222 * interface then mark this interface as p2p_device to avoid
5223 * scan and auto-scan are launched on it while P2P is connected.
5225 if (!g_list_find(p2p_iface_list, g_wifi))
5226 wifi->p2p_device = true;
5229 connman_peer_set_state(connman_peer, p_state);
5232 static void peer_request(GSupplicantPeer *peer)
5234 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5235 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5236 struct connman_peer *connman_peer;
5237 const char *identifier;
5239 #if defined TIZEN_EXT
5244 identifier = g_supplicant_peer_get_identifier(peer);
5246 DBG("ident: %s", identifier);
5248 connman_peer = connman_peer_get(wifi->device, identifier);
5252 connman_peer_request_connection(connman_peer);
5255 #if defined TIZEN_EXT
5256 static void system_power_off(void)
5259 struct wifi_data *wifi;
5260 struct connman_service *service;
5261 struct connman_ipconfig *ipconfig_ipv4;
5263 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
5264 for (list = iface_list; list; list = list->next) {
5267 if (wifi->network != NULL) {
5268 service = connman_service_lookup_from_network(wifi->network);
5269 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5270 __connman_dhcp_stop(ipconfig_ipv4);
5276 static void network_merged(GSupplicantNetwork *network)
5278 GSupplicantInterface *interface;
5279 GSupplicantState state;
5280 struct wifi_data *wifi;
5281 const char *identifier;
5282 struct connman_network *connman_network;
5286 interface = g_supplicant_network_get_interface(network);
5290 state = g_supplicant_interface_get_state(interface);
5291 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5294 wifi = g_supplicant_interface_get_data(interface);
5298 identifier = g_supplicant_network_get_identifier(network);
5300 connman_network = connman_device_get_network(wifi->device, identifier);
5301 if (!connman_network)
5304 DBG("merged identifier %s", identifier);
5306 if (wifi->connected == FALSE) {
5308 case G_SUPPLICANT_STATE_AUTHENTICATING:
5309 case G_SUPPLICANT_STATE_ASSOCIATING:
5310 case G_SUPPLICANT_STATE_ASSOCIATED:
5311 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5312 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5313 connman_network_set_associating(connman_network, TRUE);
5315 case G_SUPPLICANT_STATE_COMPLETED:
5316 connman_network_set_connected(connman_network, TRUE);
5319 DBG("Not handled the state : %d", state);
5324 ishs20AP = g_supplicant_network_is_hs20AP(network);
5327 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5328 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5329 connman_network_set_string(connman_network, "WiFi.EAP",
5331 connman_network_set_string(connman_network, "WiFi.Identity",
5332 g_supplicant_network_get_identity(network));
5333 connman_network_set_string(connman_network, "WiFi.Phase2",
5334 g_supplicant_network_get_phase2(network));
5339 wifi->network = connman_network;
5342 static void assoc_failed(void *user_data)
5344 struct connman_network *network = user_data;
5345 connman_network_set_associating(network, false);
5348 static void scan_done(GSupplicantInterface *interface)
5351 int scan_type = CONNMAN_SCAN_TYPE_WPA_SUPPLICANT;
5352 struct wifi_data *wifi;
5355 for (list = iface_list; list; list = list->next) {
5358 if (interface == wifi->interface) {
5359 scanning = connman_device_get_scanning(wifi->device,
5360 CONNMAN_SERVICE_TYPE_WIFI);
5362 __connman_technology_notify_scan_done(scan_type);
5369 static void debug(const char *str)
5371 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5372 connman_debug("%s", str);
5375 static void disconnect_reasoncode(GSupplicantInterface *interface,
5378 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5381 wifi->disconnect_code = reasoncode;
5385 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5387 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5390 wifi->assoc_code = status_code;
5394 static const GSupplicantCallbacks callbacks = {
5395 .system_ready = system_ready,
5396 .system_killed = system_killed,
5397 .interface_added = interface_added,
5398 .interface_state = interface_state,
5399 .interface_removed = interface_removed,
5400 .p2p_support = p2p_support,
5401 .scan_started = scan_started,
5402 .scan_finished = scan_finished,
5403 .ap_create_fail = ap_create_fail,
5404 .network_added = network_added,
5405 .network_removed = network_removed,
5406 .network_changed = network_changed,
5407 .network_associated = network_associated,
5408 .sta_authorized = sta_authorized,
5409 .sta_deauthorized = sta_deauthorized,
5410 .peer_found = peer_found,
5411 .peer_lost = peer_lost,
5412 .peer_changed = peer_changed,
5413 .peer_request = peer_request,
5414 #if defined TIZEN_EXT
5415 .system_power_off = system_power_off,
5416 .network_merged = network_merged,
5417 .assoc_failed = assoc_failed,
5418 .scan_done = scan_done,
5421 .disconnect_reasoncode = disconnect_reasoncode,
5422 .assoc_status_code = assoc_status_code,
5423 #if defined TIZEN_EXT_WIFI_MESH
5424 .mesh_support = mesh_support,
5425 .mesh_group_started = mesh_group_started,
5426 .mesh_group_removed = mesh_group_removed,
5427 .mesh_peer_connected = mesh_peer_connected,
5428 .mesh_peer_disconnected = mesh_peer_disconnected,
5433 static int tech_probe(struct connman_technology *technology)
5435 wifi_technology = technology;
5440 static void tech_remove(struct connman_technology *technology)
5442 wifi_technology = NULL;
5445 static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
5447 GSupplicantSSID *ap;
5449 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5453 ap->mode = G_SUPPLICANT_MODE_MASTER;
5454 #if defined TIZEN_EXT
5455 ap->ssid = (void *) ssid;
5459 ap->ssid_len = strlen(ssid);
5463 if (!passphrase || strlen(passphrase) == 0) {
5464 ap->security = G_SUPPLICANT_SECURITY_NONE;
5465 ap->passphrase = NULL;
5467 ap->security = G_SUPPLICANT_SECURITY_PSK;
5468 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5469 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5470 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5471 ap->passphrase = passphrase;
5477 static void ap_start_callback(int result, GSupplicantInterface *interface,
5480 struct wifi_tethering_info *info = user_data;
5482 DBG("result %d index %d bridge %s",
5483 result, info->wifi->index, info->wifi->bridge);
5485 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5486 connman_inet_remove_from_bridge(info->wifi->index,
5487 info->wifi->bridge);
5489 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5490 connman_technology_tethering_notify(info->technology, false);
5491 g_free(info->wifi->tethering_param->ssid);
5492 g_free(info->wifi->tethering_param);
5493 info->wifi->tethering_param = NULL;
5497 g_free(info->ifname);
5501 static void ap_create_callback(int result,
5502 GSupplicantInterface *interface,
5505 struct wifi_tethering_info *info = user_data;
5507 DBG("result %d ifname %s", result,
5508 g_supplicant_interface_get_ifname(interface));
5510 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5511 connman_inet_remove_from_bridge(info->wifi->index,
5512 info->wifi->bridge);
5514 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5515 connman_technology_tethering_notify(info->technology, false);
5516 g_free(info->wifi->tethering_param->ssid);
5517 g_free(info->wifi->tethering_param);
5518 info->wifi->tethering_param = NULL;
5522 g_free(info->ifname);
5528 info->wifi->interface = interface;
5529 g_supplicant_interface_set_data(interface, info->wifi);
5531 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5532 connman_error("Failed to set interface ap_scan property");
5534 g_supplicant_interface_connect(interface, info->ssid,
5535 ap_start_callback, info);
5538 static void sta_remove_callback(int result,
5539 GSupplicantInterface *interface,
5542 struct wifi_tethering_info *info = user_data;
5543 const char *driver = connman_option_get_string("wifi");
5545 DBG("ifname %s result %d ", info->ifname, result);
5547 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5548 info->wifi->tethering = false;
5549 connman_technology_tethering_notify(info->technology, false);
5551 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5552 g_free(info->wifi->tethering_param->ssid);
5553 g_free(info->wifi->tethering_param);
5554 info->wifi->tethering_param = NULL;
5557 g_free(info->ifname);
5563 info->wifi->interface = NULL;
5565 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5570 static int enable_wifi_tethering(struct connman_technology *technology,
5571 const char *bridge, const char *identifier,
5572 const char *passphrase, bool available)
5575 GSupplicantInterface *interface;
5576 struct wifi_data *wifi;
5577 struct wifi_tethering_info *info;
5582 for (list = iface_list; list; list = list->next) {
5585 DBG("wifi %p network %p pending_network %p", wifi,
5586 wifi->network, wifi->pending_network);
5588 interface = wifi->interface;
5593 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5597 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5598 DBG("%s does not support AP mode (detected)", ifname);
5602 mode = g_supplicant_interface_get_mode(interface);
5603 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5604 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5605 DBG("%s does not support AP mode (capability)", ifname);
5609 if (wifi->network && available)
5612 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5616 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5617 if (!wifi->tethering_param) {
5623 info->technology = technology;
5624 info->wifi->bridge = bridge;
5625 info->ssid = ssid_ap_init(identifier, passphrase);
5629 info->ifname = g_strdup(ifname);
5631 wifi->tethering_param->technology = technology;
5632 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5633 if (!wifi->tethering_param->ssid)
5636 info->wifi->tethering = true;
5637 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5639 berr = connman_technology_tethering_notify(technology, true);
5643 err = g_supplicant_interface_remove(interface,
5644 sta_remove_callback,
5647 DBG("tethering wifi %p ifname %s", wifi, ifname);
5652 g_free(info->ifname);
5655 g_free(wifi->tethering_param);
5656 wifi->tethering_param = NULL;
5659 * Remove bridge if it was correctly created but remove
5660 * operation failed. Instead, if bridge creation failed then
5661 * break out and do not try again on another interface,
5662 * bridge set-up does not depend on it.
5665 connman_technology_tethering_notify(technology, false);
5673 static int tech_set_tethering(struct connman_technology *technology,
5674 const char *identifier, const char *passphrase,
5675 const char *bridge, bool enabled)
5678 struct wifi_data *wifi;
5684 for (list = iface_list; list; list = list->next) {
5687 if (wifi->tethering) {
5688 wifi->tethering = false;
5690 connman_inet_remove_from_bridge(wifi->index,
5692 wifi->bridged = false;
5696 connman_technology_tethering_notify(technology, false);
5701 DBG("trying tethering for available devices");
5702 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5706 DBG("trying tethering for any device");
5707 err = enable_wifi_tethering(technology, bridge, identifier,
5714 static void regdom_callback(int result, const char *alpha2, void *user_data)
5718 if (!wifi_technology)
5724 connman_technology_regdom_notify(wifi_technology, alpha2);
5727 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5729 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5732 static struct connman_technology_driver tech_driver = {
5734 .type = CONNMAN_SERVICE_TYPE_WIFI,
5735 .probe = tech_probe,
5736 .remove = tech_remove,
5737 .set_tethering = tech_set_tethering,
5738 .set_regdom = tech_set_regdom,
5741 static int wifi_init(void)
5745 err = connman_network_driver_register(&network_driver);
5749 err = g_supplicant_register(&callbacks);
5751 connman_network_driver_unregister(&network_driver);
5755 err = connman_technology_driver_register(&tech_driver);
5757 g_supplicant_unregister(&callbacks);
5758 connman_network_driver_unregister(&network_driver);
5762 #if defined TIZEN_EXT
5763 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5768 static void wifi_exit(void)
5772 connman_technology_driver_unregister(&tech_driver);
5774 g_supplicant_unregister(&callbacks);
5776 connman_network_driver_unregister(&network_driver);
5778 #if defined TIZEN_EXT
5779 g_hash_table_unref(failed_bssids);
5783 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5784 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)