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);
2095 DBG("result %d wifi %p", result, wifi);
2098 if (wifi->hidden && !wifi->postpone_hidden) {
2099 connman_network_clear_hidden(wifi->hidden->user_data);
2100 hidden_free(wifi->hidden);
2101 wifi->hidden = NULL;
2104 if (wifi->scan_params) {
2105 g_supplicant_free_scan_params(wifi->scan_params);
2106 wifi->scan_params = NULL;
2109 #if defined TIZEN_EXT
2110 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2111 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2112 wifi->hidden_scan_params = NULL;
2118 connman_device_reset_scanning(device);
2120 /* User is connecting to a hidden AP, let's wait for finished event */
2121 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2122 GSupplicantScanParams *scan_params;
2125 wifi->postpone_hidden = false;
2126 scan_params = wifi->hidden->scan_params;
2127 wifi->hidden->scan_params = NULL;
2129 reset_autoscan(device);
2131 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2132 scan_callback, device);
2136 /* On error, let's recall scan_callback, which will cleanup */
2137 return scan_callback(ret, interface, user_data);
2140 #if defined TIZEN_EXT
2141 if (wifi && wifi->allow_full_scan) {
2143 DBG("Trigger Full Channel Scan");
2144 wifi->allow_full_scan = FALSE;
2146 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2147 scan_callback_hidden, device);
2151 /* On error, let's recall scan_callback, which will cleanup */
2152 return scan_callback(ret, interface, user_data);
2156 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
2159 connman_device_set_scanning(device,
2160 CONNMAN_SERVICE_TYPE_WIFI, false);
2163 if (result != -ENOLINK)
2164 #if defined TIZEN_EXT
2167 start_autoscan(device);
2170 * If we are here then we were scanning; however, if we are
2171 * also mid-flight disabling the interface, then wifi_disable
2172 * has already cleared the device scanning state and
2173 * unreferenced the device, obviating the need to do it here.
2177 connman_device_unref(device);
2179 #if defined TIZEN_EXT
2180 if (wifi && wifi->scan_pending_network && result != -EIO) {
2181 network_connect(wifi->scan_pending_network);
2182 wifi->scan_pending_network = NULL;
2183 connman_network_set_connecting(wifi->network);
2186 if (is_wifi_notifier_registered != true &&
2187 wifi_first_scan == true && found_with_first_scan == true) {
2188 wifi_first_scan = false;
2189 found_with_first_scan = false;
2191 connman_notifier_register(¬ifier);
2192 is_wifi_notifier_registered = true;
2197 static void scan_callback_hidden(int result,
2198 GSupplicantInterface *interface, void *user_data)
2200 struct connman_device *device = user_data;
2201 struct wifi_data *wifi = connman_device_get_data(device);
2202 GSupplicantScanParams *scan_params;
2205 DBG("result %d wifi %p", result, wifi);
2210 /* User is trying to connect to a hidden AP */
2211 if (wifi->hidden && wifi->postpone_hidden)
2214 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2218 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2219 ret = g_supplicant_interface_scan(wifi->interface,
2221 #if defined TIZEN_EXT
2224 scan_callback_hidden,
2231 g_supplicant_free_scan_params(scan_params);
2234 scan_callback(result, interface, user_data);
2237 static gboolean autoscan_timeout(gpointer data)
2239 struct connman_device *device = data;
2240 struct wifi_data *wifi = connman_device_get_data(device);
2241 struct autoscan_params *autoscan;
2247 autoscan = wifi->autoscan;
2249 if (autoscan->interval <= 0) {
2250 interval = autoscan->base;
2253 interval = autoscan->interval * autoscan->base;
2255 #if defined TIZEN_EXT
2256 if (autoscan->interval >= autoscan->limit)
2258 if (interval > autoscan->limit)
2260 interval = autoscan->limit;
2262 throw_wifi_scan(wifi->device, scan_callback_hidden);
2265 * In case BackgroundScanning is disabled, interval will reach the
2266 * limit exactly after the very first passive scanning. It allows
2267 * to ensure at most one passive scan is performed in such cases.
2269 if (!connman_setting_get_bool("BackgroundScanning") &&
2270 interval == autoscan->limit) {
2271 g_source_remove(autoscan->timeout);
2272 autoscan->timeout = 0;
2274 connman_device_unref(device);
2280 DBG("interval %d", interval);
2282 autoscan->interval = interval;
2284 autoscan->timeout = g_timeout_add_seconds(interval,
2285 autoscan_timeout, device);
2290 static void start_autoscan(struct connman_device *device)
2292 struct wifi_data *wifi = connman_device_get_data(device);
2293 struct autoscan_params *autoscan;
2300 if (wifi->p2p_device)
2303 if (wifi->connected)
2306 autoscan = wifi->autoscan;
2310 if (autoscan->timeout > 0 || autoscan->interval > 0)
2313 connman_device_ref(device);
2315 autoscan_timeout(device);
2318 static struct autoscan_params *parse_autoscan_params(const char *params)
2320 struct autoscan_params *autoscan;
2327 list_params = g_strsplit(params, ":", 0);
2328 if (list_params == 0)
2331 if (!g_strcmp0(list_params[0], "exponential") &&
2332 g_strv_length(list_params) == 3) {
2333 base = atoi(list_params[1]);
2334 limit = atoi(list_params[2]);
2335 } else if (!g_strcmp0(list_params[0], "single") &&
2336 g_strv_length(list_params) == 2)
2337 base = limit = atoi(list_params[1]);
2339 g_strfreev(list_params);
2343 DBG("Setup %s autoscanning", list_params[0]);
2345 g_strfreev(list_params);
2347 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2349 DBG("Could not allocate memory for autoscan");
2353 DBG("base %d - limit %d", base, limit);
2354 autoscan->base = base;
2355 autoscan->limit = limit;
2360 static void setup_autoscan(struct wifi_data *wifi)
2363 * If BackgroundScanning is enabled, setup exponential
2364 * autoscanning if it has not been previously done.
2366 if (connman_setting_get_bool("BackgroundScanning")) {
2367 wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
2372 * On the contrary, if BackgroundScanning is disabled, update autoscan
2373 * parameters based on the type of scanning that is being performed.
2375 if (wifi->autoscan) {
2376 g_free(wifi->autoscan);
2377 wifi->autoscan = NULL;
2380 switch (wifi->scanning_type) {
2381 case WIFI_SCANNING_PASSIVE:
2382 /* Do not setup autoscan. */
2384 case WIFI_SCANNING_ACTIVE:
2385 /* Setup one single passive scan after active. */
2386 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2388 case WIFI_SCANNING_UNKNOWN:
2389 /* Setup autoscan in this case but we should never fall here. */
2390 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2395 static void finalize_interface_creation(struct wifi_data *wifi)
2397 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2399 if (!wifi->device) {
2400 connman_error("WiFi device not set");
2404 connman_device_set_powered(wifi->device, true);
2406 if (wifi->p2p_device)
2409 if (!wifi->autoscan)
2410 setup_autoscan(wifi);
2412 start_autoscan(wifi->device);
2415 static void interface_create_callback(int result,
2416 GSupplicantInterface *interface,
2419 struct wifi_data *wifi = user_data;
2421 DBG("result %d ifname %s, wifi %p", result,
2422 g_supplicant_interface_get_ifname(interface),
2425 if (result < 0 || !wifi)
2428 wifi->interface = interface;
2429 g_supplicant_interface_set_data(interface, wifi);
2431 if (g_supplicant_interface_get_ready(interface)) {
2432 wifi->interface_ready = true;
2433 finalize_interface_creation(wifi);
2437 static int wifi_enable(struct connman_device *device)
2439 struct wifi_data *wifi = connman_device_get_data(device);
2442 const char *driver = connman_option_get_string("wifi");
2445 DBG("device %p %p", device, wifi);
2447 index = connman_device_get_index(device);
2448 if (!wifi || index < 0)
2451 if (is_p2p_connecting())
2452 return -EINPROGRESS;
2454 interface = connman_inet_ifname(index);
2455 ret = g_supplicant_interface_create(interface, driver, NULL,
2456 interface_create_callback,
2463 return -EINPROGRESS;
2466 static int wifi_disable(struct connman_device *device)
2468 struct wifi_data *wifi = connman_device_get_data(device);
2471 DBG("device %p wifi %p", device, wifi);
2476 wifi->connected = false;
2477 wifi->disconnecting = false;
2479 if (wifi->pending_network)
2480 wifi->pending_network = NULL;
2482 #if !defined TIZEN_EXT
2483 stop_autoscan(device);
2486 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
2487 g_source_remove(wifi->p2p_find_timeout);
2488 wifi->p2p_find_timeout = 0;
2489 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2490 connman_device_unref(wifi->device);
2493 #if defined TIZEN_EXT
2494 if (wifi->automaxspeed_timeout != 0) {
2495 g_source_remove(wifi->automaxspeed_timeout);
2496 wifi->automaxspeed_timeout = 0;
2500 /* In case of a user scan, device is still referenced */
2501 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) {
2502 connman_device_set_scanning(device,
2503 CONNMAN_SERVICE_TYPE_WIFI, false);
2504 connman_device_unref(wifi->device);
2507 #if defined TIZEN_EXT
2508 stop_autoscan(device);
2511 remove_networks(device, wifi);
2514 #if defined TIZEN_EXT
2515 wifi->scan_pending_network = NULL;
2517 if (is_wifi_notifier_registered == true) {
2518 connman_notifier_unregister(¬ifier);
2519 is_wifi_notifier_registered = false;
2523 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2527 return -EINPROGRESS;
2530 static int get_latest_connections(int max_ssids,
2531 GSupplicantScanParams *scan_data)
2533 GSequenceIter *iter;
2534 GSequence *latest_list;
2535 struct last_connected *entry;
2544 latest_list = g_sequence_new(free_entry);
2548 services = connman_storage_get_services();
2549 for (i = 0; services && services[i]; i++) {
2550 if (strncmp(services[i], "wifi_", 5) != 0)
2553 keyfile = connman_storage_load_service(services[i]);
2557 str = g_key_file_get_string(keyfile,
2558 services[i], "Favorite", NULL);
2559 if (!str || g_strcmp0(str, "true")) {
2561 g_key_file_free(keyfile);
2566 str = g_key_file_get_string(keyfile,
2567 services[i], "AutoConnect", NULL);
2568 if (!str || g_strcmp0(str, "true")) {
2570 g_key_file_free(keyfile);
2575 str = g_key_file_get_string(keyfile,
2576 services[i], "Modified", NULL);
2578 g_key_file_free(keyfile);
2581 g_time_val_from_iso8601(str, &modified);
2584 ssid = g_key_file_get_string(keyfile,
2585 services[i], "SSID", NULL);
2587 freq = g_key_file_get_integer(keyfile, services[i],
2590 entry = g_try_new(struct last_connected, 1);
2592 g_sequence_free(latest_list);
2593 g_key_file_free(keyfile);
2599 entry->modified = modified;
2602 g_sequence_insert_sorted(latest_list, entry,
2608 g_key_file_free(keyfile);
2611 g_strfreev(services);
2613 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2615 iter = g_sequence_get_begin_iter(latest_list);
2617 for (i = 0; i < num_ssids; i++) {
2618 entry = g_sequence_get(iter);
2620 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2621 entry->modified.tv_sec);
2623 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2624 max_ssids, entry->ssid);
2626 iter = g_sequence_iter_next(iter);
2629 g_sequence_free(latest_list);
2633 static void wifi_update_scanner_type(struct wifi_data *wifi,
2634 enum wifi_scanning_type new_type)
2638 if (!wifi || wifi->scanning_type == new_type)
2641 wifi->scanning_type = new_type;
2643 setup_autoscan(wifi);
2646 static int wifi_scan_simple(struct connman_device *device)
2648 struct wifi_data *wifi = connman_device_get_data(device);
2650 reset_autoscan(device);
2652 /* Distinguish between devices performing passive and active scanning */
2654 wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE);
2656 return throw_wifi_scan(device, scan_callback_hidden);
2659 static gboolean p2p_find_stop(gpointer data)
2661 struct connman_device *device = data;
2662 struct wifi_data *wifi = connman_device_get_data(device);
2667 wifi->p2p_find_timeout = 0;
2669 g_supplicant_interface_p2p_stop_find(wifi->interface);
2672 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2674 connman_device_unref(device);
2675 start_autoscan(device);
2680 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2683 struct connman_device *device = user_data;
2684 struct wifi_data *wifi = connman_device_get_data(device);
2686 DBG("result %d wifi %p", result, wifi);
2691 if (wifi->p2p_find_timeout) {
2692 g_source_remove(wifi->p2p_find_timeout);
2693 wifi->p2p_find_timeout = 0;
2699 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2700 p2p_find_stop, device);
2701 if (!wifi->p2p_find_timeout)
2706 p2p_find_stop(device);
2709 static int p2p_find(struct connman_device *device)
2711 struct wifi_data *wifi;
2716 if (!p2p_technology)
2719 wifi = connman_device_get_data(device);
2721 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2724 reset_autoscan(device);
2725 connman_device_ref(device);
2727 ret = g_supplicant_interface_p2p_find(wifi->interface,
2728 p2p_find_callback, device);
2730 connman_device_unref(device);
2731 start_autoscan(device);
2733 connman_device_set_scanning(device,
2734 CONNMAN_SERVICE_TYPE_P2P, true);
2740 #if defined TIZEN_EXT
2741 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2744 struct connman_device *device = user_data;
2745 struct wifi_data *wifi = connman_device_get_data(device);
2748 DBG("result %d wifi %p", result, wifi);
2750 if (wifi && wifi->scan_params) {
2751 g_supplicant_free_scan_params(wifi->scan_params);
2752 wifi->scan_params = NULL;
2755 scanning = connman_device_get_scanning(device,
2756 CONNMAN_SERVICE_TYPE_WIFI);
2758 connman_device_set_scanning(device,
2759 CONNMAN_SERVICE_TYPE_WIFI, false);
2760 connman_device_unref(device);
2764 static int wifi_specific_scan(enum connman_service_type type,
2765 struct connman_device *device, int scan_type,
2766 GSList *specific_scan_list, void *user_data)
2768 GSList *list = NULL;
2770 struct wifi_data *wifi = connman_device_get_data(device);
2771 GSupplicantScanParams *scan_params = NULL;
2772 struct scan_ssid *scan_ssid = NULL;
2781 if (wifi->p2p_device)
2784 if (type == CONNMAN_SERVICE_TYPE_P2P)
2785 return p2p_find(device);
2787 if (wifi->tethering)
2791 connman_device_get_scanning(device,
2792 CONNMAN_SERVICE_TYPE_WIFI);
2796 DBG("scan_type: %d", scan_type);
2797 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2798 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2800 DBG("Failed to allocate memory.");
2804 for (list = specific_scan_list; list; list = list->next) {
2805 ssid = (char *)list->data;
2806 int ssid_len = strlen(ssid);
2808 scan_ssid = g_try_new0(struct scan_ssid, 1);
2810 DBG("Failed to allocate memory.");
2811 g_supplicant_free_scan_params(scan_params);
2815 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2816 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2817 scan_ssid->ssid_len = ssid_len;
2818 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2821 scan_params->num_ssids = count;
2823 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2825 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2827 DBG("Failed to allocate memory.");
2831 guint num_freqs = g_slist_length(specific_scan_list);
2832 DBG("num_freqs: %d", num_freqs);
2834 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2835 if (!scan_params->freqs) {
2836 DBG("Failed to allocate memory.");
2837 g_free(scan_params);
2842 for (list = specific_scan_list; list; list = list->next) {
2843 freq = (int)list->data;
2845 scan_params->freqs[count] = freq;
2846 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2849 scan_params->num_freqs = count;
2851 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2852 int freq_count, ap_count;
2853 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2855 DBG("Failed to allocate memory.");
2859 guint size = g_slist_length(specific_scan_list);
2861 scan_params->freqs = g_try_new0(uint16_t, size/2);
2862 if (!scan_params->freqs) {
2863 DBG("Failed to allocate memory.");
2864 g_free(scan_params);
2868 ap_count = freq_count = 0;
2869 for (list = specific_scan_list; list; list = list->next) {
2870 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2871 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2872 int ssid_len = strlen(ssid);
2874 scan_ssid = g_try_new0(struct scan_ssid, 1);
2876 DBG("Failed to allocate memory.");
2877 g_supplicant_free_scan_params(scan_params);
2881 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2882 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2883 scan_ssid->ssid_len = ssid_len;
2884 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2888 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2889 scan_params->freqs[freq_count] = freq;
2890 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2894 scan_params->num_ssids = ap_count;
2895 scan_params->num_freqs = freq_count;
2897 DBG("Invalid scan");
2901 reset_autoscan(device);
2902 connman_device_ref(device);
2904 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2905 specific_scan_callback, device);
2908 connman_device_set_scanning(device,
2909 CONNMAN_SERVICE_TYPE_WIFI, true);
2911 g_supplicant_free_scan_params(scan_params);
2912 connman_device_unref(device);
2919 #if defined TIZEN_EXT_WIFI_MESH
2920 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2923 struct connman_device *device = user_data;
2924 struct wifi_data *wifi = connman_device_get_data(device);
2927 DBG("result %d wifi %p", result, wifi);
2929 scanning = connman_device_get_scanning(device,
2930 CONNMAN_SERVICE_TYPE_MESH);
2932 connman_device_set_scanning(device,
2933 CONNMAN_SERVICE_TYPE_MESH, false);
2936 connman_device_unref(device);
2939 static int mesh_scan(struct connman_device *device)
2941 struct wifi_data *wifi;
2942 struct wifi_mesh_info *mesh_info;
2947 wifi = connman_device_get_data(device);
2949 if (!wifi->mesh_interface)
2952 mesh_info = wifi->mesh_info;
2953 reset_autoscan(device);
2954 connman_device_ref(device);
2956 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2957 mesh_scan_callback, device);
2959 connman_device_unref(device);
2961 connman_device_set_scanning(device,
2962 CONNMAN_SERVICE_TYPE_MESH, true);
2967 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2970 struct connman_device *device = user_data;
2971 struct wifi_data *wifi = connman_device_get_data(device);
2973 DBG("result %d wifi %p", result, wifi);
2975 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2978 static int mesh_abort_scan(enum connman_service_type type,
2979 struct connman_device *device)
2981 struct wifi_data *wifi = connman_device_get_data(device);
2982 struct wifi_mesh_info *mesh_info;
2986 if (!wifi || !wifi->mesh_interface)
2989 if (type != CONNMAN_SERVICE_TYPE_MESH)
2992 mesh_info = wifi->mesh_info;
2994 scanning = connman_device_get_scanning(device,
2995 CONNMAN_SERVICE_TYPE_MESH);
2999 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
3000 abort_scan_callback, device);
3005 static int mesh_specific_scan(enum connman_service_type type,
3006 struct connman_device *device, const char *ssid,
3007 unsigned int freq, void *user_data)
3009 struct wifi_data *wifi = connman_device_get_data(device);
3010 GSupplicantScanParams *scan_params = NULL;
3011 struct wifi_mesh_info *mesh_info;
3012 struct scan_ssid *scan_ssid;
3016 if (!wifi || !wifi->mesh_interface)
3019 if (type != CONNMAN_SERVICE_TYPE_MESH)
3022 if (wifi->p2p_device)
3025 mesh_info = wifi->mesh_info;
3027 scanning = connman_device_get_scanning(device,
3028 CONNMAN_SERVICE_TYPE_MESH);
3032 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3036 scan_ssid = g_try_new(struct scan_ssid, 1);
3038 g_free(scan_params);
3042 scan_ssid->ssid_len = strlen(ssid);
3043 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
3044 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3045 scan_params->num_ssids = 1;
3047 scan_params->freqs = g_try_new(uint16_t, 1);
3048 if (!scan_params->freqs) {
3049 g_slist_free_full(scan_params->ssids, g_free);
3050 g_free(scan_params);
3054 scan_params->freqs[0] = freq;
3055 scan_params->num_freqs = 1;
3057 reset_autoscan(device);
3058 connman_device_ref(device);
3060 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
3061 mesh_scan_callback, device);
3064 connman_device_set_scanning(device,
3065 CONNMAN_SERVICE_TYPE_MESH, true);
3067 g_supplicant_free_scan_params(scan_params);
3068 connman_device_unref(device);
3076 * Note that the hidden scan is only used when connecting to this specific
3077 * hidden AP first time. It is not used when system autoconnects to hidden AP.
3079 static int wifi_scan(struct connman_device *device,
3080 struct connman_device_scan_params *params)
3082 struct wifi_data *wifi = connman_device_get_data(device);
3083 GSupplicantScanParams *scan_params = NULL;
3084 struct scan_ssid *scan_ssid;
3085 struct hidden_params *hidden;
3087 int driver_max_ssids = 0;
3094 if (wifi->p2p_device)
3097 if (wifi->tethering)
3100 if (params->type == CONNMAN_SERVICE_TYPE_P2P)
3101 return p2p_find(device);
3103 #if defined TIZEN_EXT_WIFI_MESH
3104 if (params->type == CONNMAN_SERVICE_TYPE_MESH)
3105 return mesh_scan(device);
3108 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface,
3111 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
3113 if (!params->ssid || params->ssid_len == 0 || params->ssid_len > 32) {
3117 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
3119 DBG("max ssids %d", driver_max_ssids);
3120 if (driver_max_ssids == 0)
3121 return wifi_scan_simple(device);
3125 if (scanning && wifi->hidden && wifi->postpone_hidden)
3131 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3136 scan_ssid = g_try_new(struct scan_ssid, 1);
3138 g_free(scan_params);
3142 memcpy(scan_ssid->ssid, params->ssid, params->ssid_len);
3143 scan_ssid->ssid_len = params->ssid_len;
3144 scan_params->ssids = g_slist_prepend(scan_params->ssids,
3146 scan_params->num_ssids = 1;
3148 hidden = g_try_new0(struct hidden_params, 1);
3150 g_supplicant_free_scan_params(scan_params);
3155 hidden_free(wifi->hidden);
3156 wifi->hidden = NULL;
3159 memcpy(hidden->ssid, params->ssid, params->ssid_len);
3160 hidden->ssid_len = params->ssid_len;
3161 hidden->identity = g_strdup(params->identity);
3162 hidden->passphrase = g_strdup(params->passphrase);
3163 hidden->security = g_strdup(params->security);
3164 hidden->user_data = params->user_data;
3165 wifi->hidden = hidden;
3168 /* Let's keep this active scan for later,
3169 * when current scan will be over. */
3170 wifi->postpone_hidden = TRUE;
3171 hidden->scan_params = scan_params;
3175 } else if (wifi->connected) {
3176 g_supplicant_free_scan_params(scan_params);
3177 return wifi_scan_simple(device);
3178 } else if (!params->force_full_scan) {
3179 ret = get_latest_connections(driver_max_ssids, scan_params);
3181 g_supplicant_free_scan_params(scan_params);
3182 return wifi_scan_simple(device);
3186 /* Distinguish between devices performing passive and active scanning */
3187 wifi_update_scanner_type(wifi, WIFI_SCANNING_ACTIVE);
3189 connman_device_ref(device);
3191 reset_autoscan(device);
3193 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3194 scan_callback, device);
3196 connman_device_set_scanning(device,
3197 CONNMAN_SERVICE_TYPE_WIFI, true);
3198 #if defined TIZEN_EXT
3199 /*To allow the Full Scan after ssid based scan, set the flag here
3200 It is required because Tizen does not use the ConnMan specific
3201 backgroung Scan feature.Tizen has added the BG Scan feature in
3202 net-config. To sync with up ConnMan, we need to issue the Full Scan
3203 after SSID specific scan.*/
3204 wifi->allow_full_scan = TRUE;
3207 g_supplicant_free_scan_params(scan_params);
3208 connman_device_unref(device);
3211 hidden_free(wifi->hidden);
3212 wifi->hidden = NULL;
3219 static void wifi_stop_scan(enum connman_service_type type,
3220 struct connman_device *device)
3222 struct wifi_data *wifi = connman_device_get_data(device);
3224 DBG("device %p wifi %p", device, wifi);
3229 if (type == CONNMAN_SERVICE_TYPE_P2P) {
3230 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
3231 g_source_remove(wifi->p2p_find_timeout);
3232 p2p_find_stop(device);
3237 static void wifi_regdom_callback(int result,
3241 struct connman_device *device = user_data;
3243 connman_device_regdom_notify(device, result, alpha2);
3245 connman_device_unref(device);
3248 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3250 struct wifi_data *wifi = connman_device_get_data(device);
3256 connman_device_ref(device);
3258 ret = g_supplicant_interface_set_country(wifi->interface,
3259 wifi_regdom_callback,
3262 connman_device_unref(device);
3267 static struct connman_device_driver wifi_ng_driver = {
3269 .type = CONNMAN_DEVICE_TYPE_WIFI,
3270 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3271 .probe = wifi_probe,
3272 .remove = wifi_remove,
3273 .enable = wifi_enable,
3274 .disable = wifi_disable,
3276 .stop_scan = wifi_stop_scan,
3277 .set_regdom = wifi_set_regdom,
3278 #if defined TIZEN_EXT
3279 .specific_scan = wifi_specific_scan,
3281 #if defined TIZEN_EXT_WIFI_MESH
3282 .abort_scan = mesh_abort_scan,
3283 .mesh_specific_scan = mesh_specific_scan,
3287 static void system_ready(void)
3291 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3292 connman_error("Failed to register WiFi driver");
3295 static void system_killed(void)
3299 connman_device_driver_unregister(&wifi_ng_driver);
3302 static int network_probe(struct connman_network *network)
3304 DBG("network %p", network);
3309 static void network_remove(struct connman_network *network)
3311 struct connman_device *device = connman_network_get_device(network);
3312 struct wifi_data *wifi;
3314 DBG("network %p", network);
3316 wifi = connman_device_get_data(device);
3320 if (wifi->network != network)
3323 wifi->network = NULL;
3325 #if defined TIZEN_EXT
3326 wifi->disconnecting = false;
3328 if (wifi->pending_network == network)
3329 wifi->pending_network = NULL;
3331 if (wifi->scan_pending_network == network)
3332 wifi->scan_pending_network = NULL;
3336 static void connect_callback(int result, GSupplicantInterface *interface,
3339 #if defined TIZEN_EXT
3341 struct wifi_data *wifi;
3343 struct connman_network *network = user_data;
3345 DBG("network %p result %d", network, result);
3347 #if defined TIZEN_EXT
3348 set_connman_bssid(RESET_BSSID, NULL);
3350 for (list = iface_list; list; list = list->next) {
3353 if (wifi && wifi->network == network)
3357 /* wifi_data may be invalid because wifi is already disabled */
3362 if (result == -ENOKEY) {
3363 connman_network_set_error(network,
3364 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3365 } else if (result < 0) {
3366 connman_network_set_error(network,
3367 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3370 connman_network_unref(network);
3373 static GSupplicantSecurity network_security(const char *security)
3375 if (g_str_equal(security, "none"))
3376 return G_SUPPLICANT_SECURITY_NONE;
3377 else if (g_str_equal(security, "wep"))
3378 return G_SUPPLICANT_SECURITY_WEP;
3379 else if (g_str_equal(security, "psk"))
3380 return G_SUPPLICANT_SECURITY_PSK;
3381 else if (g_str_equal(security, "wpa"))
3382 return G_SUPPLICANT_SECURITY_PSK;
3383 else if (g_str_equal(security, "rsn"))
3384 return G_SUPPLICANT_SECURITY_PSK;
3385 else if (g_str_equal(security, "ieee8021x"))
3386 return G_SUPPLICANT_SECURITY_IEEE8021X;
3387 #if defined TIZEN_EXT
3388 else if (g_str_equal(security, "ft_psk") == TRUE)
3389 return G_SUPPLICANT_SECURITY_FT_PSK;
3390 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3391 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3392 else if (g_str_equal(security, "sae"))
3393 return G_SUPPLICANT_SECURITY_SAE;
3394 else if (g_str_equal(security, "owe"))
3395 return G_SUPPLICANT_SECURITY_OWE;
3396 else if (g_str_equal(security, "dpp"))
3397 return G_SUPPLICANT_SECURITY_DPP;
3400 return G_SUPPLICANT_SECURITY_UNKNOWN;
3403 #if defined TIZEN_EXT
3404 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3406 if (security == NULL)
3407 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3409 if (g_str_equal(security, "FT") == TRUE)
3410 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3411 else if (g_str_equal(security, "CCKM") == TRUE)
3412 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3414 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3418 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3420 const char *security;
3421 #if defined TIZEN_EXT
3422 const void *ssid_data;
3425 memset(ssid, 0, sizeof(*ssid));
3426 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3427 #if defined TIZEN_EXT
3428 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3430 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3435 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3437 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3440 ssid->scan_ssid = 1;
3441 security = connman_network_get_string(network, "WiFi.Security");
3442 ssid->security = network_security(security);
3443 #if defined TIZEN_EXT
3444 ssid->ieee80211w = 1;
3446 ssid->passphrase = connman_network_get_string(network,
3449 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3452 * If our private key password is unset,
3453 * we use the supplied passphrase. That is needed
3454 * for PEAP where 2 passphrases (identity and client
3455 * cert may have to be provided.
3457 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3458 connman_network_set_string(network,
3459 "WiFi.PrivateKeyPassphrase",
3461 /* We must have an identity for both PEAP and TLS */
3462 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3464 /* Use agent provided identity as a fallback */
3465 if (!ssid->identity || strlen(ssid->identity) == 0)
3466 ssid->identity = connman_network_get_string(network,
3467 "WiFi.AgentIdentity");
3469 ssid->anonymous_identity = connman_network_get_string(network,
3470 "WiFi.AnonymousIdentity");
3471 ssid->ca_cert_path = connman_network_get_string(network,
3473 ssid->subject_match = connman_network_get_string(network,
3474 "WiFi.SubjectMatch");
3475 ssid->altsubject_match = connman_network_get_string(network,
3476 "WiFi.AltSubjectMatch");
3477 ssid->domain_suffix_match = connman_network_get_string(network,
3478 "WiFi.DomainSuffixMatch");
3479 ssid->domain_match = connman_network_get_string(network,
3480 "WiFi.DomainMatch");
3481 ssid->client_cert_path = connman_network_get_string(network,
3482 "WiFi.ClientCertFile");
3483 ssid->private_key_path = connman_network_get_string(network,
3484 "WiFi.PrivateKeyFile");
3485 ssid->private_key_passphrase = connman_network_get_string(network,
3486 "WiFi.PrivateKeyPassphrase");
3487 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3489 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3490 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3491 #if defined TIZEN_EXT
3492 ssid->connector = connman_network_get_string(network,
3494 ssid->c_sign_key = connman_network_get_string(network,
3496 ssid->net_access_key = connman_network_get_string(network,
3497 "WiFi.NetAccessKey");
3500 #if defined TIZEN_EXT
3501 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3502 ssid->bssid_for_connect_len = 6;
3503 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3504 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3505 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3506 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3507 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3509 ssid->freq = connman_network_get_frequency(network);
3512 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3513 if (bssid_list && g_slist_length(bssid_list) > 1) {
3515 /* If there are more than one bssid,
3516 * the user-specified bssid is tried only once at the beginning.
3517 * After that, the bssids in the list are tried in order.
3519 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3520 set_connman_bssid(RESET_BSSID, NULL);
3525 char buff[MAC_ADDRESS_LENGTH];
3526 for (list = bssid_list; list; list = list->next) {
3527 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3529 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3530 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3531 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3532 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3534 gchar *curr_bssid = g_strdup((const gchar *)buff);
3536 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3537 DBG("bssid match, try next bssid");
3541 g_hash_table_add(failed_bssids, curr_bssid);
3543 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3544 ssid->bssid = buff_bssid;
3545 ssid->freq = (unsigned int)bssids->frequency;
3551 ssid->bssid = connman_network_get_bssid(network);
3552 g_hash_table_remove_all(failed_bssids);
3555 ssid->bssid = connman_network_get_bssid(network);
3558 ssid->eap_keymgmt = network_eap_keymgmt(
3559 connman_network_get_string(network, "WiFi.KeymgmtType"));
3560 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3562 if(g_strcmp0(ssid->eap, "fast") == 0)
3563 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3566 if (connman_setting_get_bool("BackgroundScanning"))
3567 ssid->bgscan = BGSCAN_DEFAULT;
3570 static int network_connect(struct connman_network *network)
3572 struct connman_device *device = connman_network_get_device(network);
3573 struct wifi_data *wifi;
3574 GSupplicantInterface *interface;
3575 GSupplicantSSID *ssid;
3577 DBG("network %p", network);
3582 wifi = connman_device_get_data(device);
3586 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3590 interface = wifi->interface;
3592 ssid_init(ssid, network);
3594 if (wifi->disconnecting) {
3595 wifi->pending_network = network;
3596 #if defined TIZEN_EXT
3601 wifi->network = connman_network_ref(network);
3603 #if defined TIZEN_EXT
3604 wifi->scan_pending_network = NULL;
3607 return g_supplicant_interface_connect(interface, ssid,
3608 connect_callback, network);
3611 return -EINPROGRESS;
3614 static void disconnect_callback(int result, GSupplicantInterface *interface,
3617 #if defined TIZEN_EXT
3619 struct wifi_data *wifi;
3620 struct connman_network *network = user_data;
3622 DBG("network %p result %d", network, result);
3624 for (list = iface_list; list; list = list->next) {
3627 if (wifi->network == NULL && wifi->disconnecting == true)
3628 wifi->disconnecting = false;
3630 if (wifi->network == network)
3634 /* wifi_data may be invalid because wifi is already disabled */
3639 struct wifi_data *wifi = user_data;
3642 DBG("result %d supplicant interface %p wifi %p",
3643 result, interface, wifi);
3645 if (result == -ECONNABORTED) {
3646 DBG("wifi interface no longer available");
3650 if (wifi->network != wifi->pending_network)
3651 connman_network_set_connected(wifi->network, false);
3652 wifi->network = NULL;
3654 wifi->disconnecting = false;
3655 wifi->connected = false;
3657 if (wifi->pending_network) {
3658 network_connect(wifi->pending_network);
3659 wifi->pending_network = NULL;
3662 start_autoscan(wifi->device);
3665 static int network_disconnect(struct connman_network *network)
3667 struct connman_device *device = connman_network_get_device(network);
3668 struct wifi_data *wifi;
3670 #if defined TIZEN_EXT
3671 struct connman_service *service;
3674 DBG("network %p", network);
3676 wifi = connman_device_get_data(device);
3677 if (!wifi || !wifi->interface)
3680 #if defined TIZEN_EXT
3681 if (connman_network_get_associating(network) == true) {
3682 connman_network_clear_associating(network);
3683 connman_network_set_bool(network, "WiFi.UseWPS", false);
3685 service = connman_service_lookup_from_network(network);
3687 if (service != NULL &&
3688 (__connman_service_is_connected_state(service,
3689 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3690 __connman_service_is_connected_state(service,
3691 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3692 (connman_service_get_favorite(service) == false))
3693 __connman_service_set_passphrase(service, NULL);
3696 if (wifi->pending_network == network)
3697 wifi->pending_network = NULL;
3699 if (wifi->scan_pending_network == network)
3700 wifi->scan_pending_network = NULL;
3703 connman_network_set_associating(network, false);
3705 if (wifi->disconnecting)
3708 wifi->disconnecting = true;
3710 #if defined TIZEN_EXT
3711 err = g_supplicant_interface_disconnect(wifi->interface,
3712 disconnect_callback, network);
3714 err = g_supplicant_interface_disconnect(wifi->interface,
3715 disconnect_callback, wifi);
3719 wifi->disconnecting = false;
3724 #if defined TIZEN_EXT
3725 static void set_connection_mode(struct connman_network *network,
3728 ieee80211_modes_e phy_mode;
3729 connection_mode_e conn_mode;
3731 phy_mode = connman_network_get_phy_mode(network);
3733 case IEEE80211_MODE_B:
3734 if (linkspeed > 0 && linkspeed <= 11)
3735 conn_mode = CONNECTION_MODE_IEEE80211B;
3737 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3740 case IEEE80211_MODE_BG:
3741 if (linkspeed > 0 && linkspeed <= 11)
3742 conn_mode = CONNECTION_MODE_IEEE80211B;
3743 else if (linkspeed > 11 && linkspeed <= 54)
3744 conn_mode = CONNECTION_MODE_IEEE80211G;
3746 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3749 case IEEE80211_MODE_BGN:
3750 if (linkspeed > 0 && linkspeed <= 11)
3751 conn_mode = CONNECTION_MODE_IEEE80211B;
3752 else if (linkspeed > 11 && linkspeed <= 54)
3753 conn_mode = CONNECTION_MODE_IEEE80211G;
3754 else if (linkspeed > 54 && linkspeed <= 450)
3755 conn_mode = CONNECTION_MODE_IEEE80211N;
3757 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3760 case IEEE80211_MODE_A:
3761 if (linkspeed > 0 && linkspeed <= 54)
3762 conn_mode = CONNECTION_MODE_IEEE80211A;
3764 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3767 case IEEE80211_MODE_AN:
3768 if (linkspeed > 0 && linkspeed <= 54)
3769 conn_mode = CONNECTION_MODE_IEEE80211A;
3770 else if (linkspeed > 54 && linkspeed <= 450)
3771 conn_mode = CONNECTION_MODE_IEEE80211N;
3773 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3776 case IEEE80211_MODE_ANAC:
3777 if (linkspeed > 0 && linkspeed <= 54)
3778 conn_mode = CONNECTION_MODE_IEEE80211A;
3779 else if (linkspeed > 54 && linkspeed <= 450)
3780 conn_mode = CONNECTION_MODE_IEEE80211N;
3781 else if (linkspeed > 450 && linkspeed <= 1300)
3782 conn_mode = CONNECTION_MODE_IEEE80211AC;
3784 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3788 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3792 DBG("connection mode(%d)", conn_mode);
3793 connman_network_set_connection_mode(network, conn_mode);
3796 static void signalpoll_callback(int result, int maxspeed, uint8_t strength,
3799 struct connman_network *network = user_data;
3802 DBG("Failed to get maxspeed from signalpoll !");
3810 DBG("maxspeed = %d, strength = %d", maxspeed, strength);
3812 connman_network_set_strength(network, strength);
3813 connman_network_set_maxspeed(network, maxspeed);
3814 set_connection_mode(network, maxspeed);
3818 static int network_signalpoll(struct wifi_data *wifi)
3820 GSupplicantInterface *interface;
3821 struct connman_network *network;
3823 if (!wifi || !wifi->network)
3826 interface = wifi->interface;
3827 network = wifi->network;
3829 DBG("network %p", network);
3831 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3834 static gboolean autosignalpoll_timeout(gpointer data)
3836 struct wifi_data *wifi = data;
3838 if (!wifi || !wifi->automaxspeed_timeout) {
3839 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3843 int ret = network_signalpoll(wifi);
3845 DBG("Fail to get max speed !!");
3846 wifi->automaxspeed_timeout = 0;
3854 static struct connman_network_driver network_driver = {
3856 .type = CONNMAN_NETWORK_TYPE_WIFI,
3857 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3858 .probe = network_probe,
3859 .remove = network_remove,
3860 .connect = network_connect,
3861 .disconnect = network_disconnect,
3864 static void interface_added(GSupplicantInterface *interface)
3866 const char *ifname = g_supplicant_interface_get_ifname(interface);
3867 const char *driver = g_supplicant_interface_get_driver(interface);
3868 #if defined TIZEN_EXT
3869 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3872 struct wifi_data *wifi;
3874 wifi = g_supplicant_interface_get_data(interface);
3876 wifi = get_pending_wifi_data(ifname);
3880 wifi->interface = interface;
3881 g_supplicant_interface_set_data(interface, wifi);
3882 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3883 wifi->p2p_device = true;
3886 DBG("ifname %s driver %s wifi %p tethering %d",
3887 ifname, driver, wifi, wifi->tethering);
3889 if (!wifi->device) {
3890 connman_error("WiFi device not set");
3894 connman_device_set_powered(wifi->device, true);
3895 #if defined TIZEN_EXT
3896 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3897 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3898 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3899 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3903 static bool is_idle(struct wifi_data *wifi)
3905 DBG("state %d", wifi->state);
3907 switch (wifi->state) {
3908 case G_SUPPLICANT_STATE_UNKNOWN:
3909 case G_SUPPLICANT_STATE_DISABLED:
3910 case G_SUPPLICANT_STATE_DISCONNECTED:
3911 case G_SUPPLICANT_STATE_INACTIVE:
3912 case G_SUPPLICANT_STATE_SCANNING:
3915 case G_SUPPLICANT_STATE_AUTHENTICATING:
3916 case G_SUPPLICANT_STATE_ASSOCIATING:
3917 case G_SUPPLICANT_STATE_ASSOCIATED:
3918 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3919 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3920 case G_SUPPLICANT_STATE_COMPLETED:
3927 static bool is_idle_wps(GSupplicantInterface *interface,
3928 struct wifi_data *wifi)
3930 /* First, let's check if WPS processing did not went wrong */
3931 if (g_supplicant_interface_get_wps_state(interface) ==
3932 G_SUPPLICANT_WPS_STATE_FAIL)
3935 /* Unlike normal connection, being associated while processing wps
3936 * actually means that we are idling. */
3937 switch (wifi->state) {
3938 case G_SUPPLICANT_STATE_UNKNOWN:
3939 case G_SUPPLICANT_STATE_DISABLED:
3940 case G_SUPPLICANT_STATE_DISCONNECTED:
3941 case G_SUPPLICANT_STATE_INACTIVE:
3942 case G_SUPPLICANT_STATE_SCANNING:
3943 case G_SUPPLICANT_STATE_ASSOCIATED:
3945 case G_SUPPLICANT_STATE_AUTHENTICATING:
3946 case G_SUPPLICANT_STATE_ASSOCIATING:
3947 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3948 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3949 case G_SUPPLICANT_STATE_COMPLETED:
3956 static bool handle_wps_completion(GSupplicantInterface *interface,
3957 struct connman_network *network,
3958 struct connman_device *device,
3959 struct wifi_data *wifi)
3963 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3965 const unsigned char *ssid, *wps_ssid;
3966 unsigned int ssid_len, wps_ssid_len;
3967 const char *wps_key;
3969 /* Checking if we got associated with requested
3971 ssid = connman_network_get_blob(network, "WiFi.SSID",
3974 wps_ssid = g_supplicant_interface_get_wps_ssid(
3975 interface, &wps_ssid_len);
3977 if (!wps_ssid || wps_ssid_len != ssid_len ||
3978 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3979 connman_network_set_associating(network, false);
3980 #if defined TIZEN_EXT
3981 g_supplicant_interface_disconnect(wifi->interface,
3982 disconnect_callback, wifi->network);
3984 connman_network_set_bool(network, "WiFi.UseWPS", false);
3985 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3987 g_supplicant_interface_disconnect(wifi->interface,
3988 disconnect_callback, wifi);
3993 wps_key = g_supplicant_interface_get_wps_key(interface);
3994 #if defined TIZEN_EXT
3995 /* Check the passphrase and encrypt it
3998 gchar *passphrase = g_strdup(wps_key);
4000 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4002 if (check_passphrase_ext(network, passphrase) < 0) {
4003 DBG("[WPS] Invalid passphrase");
4008 ret = send_encryption_request(passphrase, network);
4013 DBG("[WPS] Encryption request succeeded");
4015 DBG("[WPS] Encryption request failed %d", ret);
4018 connman_network_set_string(network, "WiFi.Passphrase",
4021 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4028 static bool handle_assoc_status_code(GSupplicantInterface *interface,
4029 struct wifi_data *wifi)
4031 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
4032 #if defined TIZEN_EXT
4033 wifi->assoc_code > 0 &&
4035 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
4037 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
4038 wifi->load_shaping_retries ++;
4041 wifi->load_shaping_retries = 0;
4045 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
4046 struct connman_network *network,
4047 struct wifi_data *wifi)
4049 #if defined TIZEN_EXT
4050 const char *security;
4051 struct connman_service *service;
4053 if (wifi->connected)
4056 security = connman_network_get_string(network, "WiFi.Security");
4058 if (security && g_str_equal(security, "ieee8021x") == true &&
4059 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4061 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4066 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4069 struct connman_service *service;
4071 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4074 if (wifi->connected)
4078 service = connman_service_lookup_from_network(network);
4084 if (connman_service_get_favorite(service)) {
4085 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
4090 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4095 #if defined TIZEN_EXT
4096 static bool handle_wifi_assoc_retry(struct connman_network *network,
4097 struct wifi_data *wifi)
4099 const char *security;
4101 if (!wifi->network || wifi->connected || wifi->disconnecting ||
4102 connman_network_get_connecting(network) != true) {
4103 wifi->assoc_retry_count = 0;
4107 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
4108 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
4109 wifi->assoc_retry_count = 0;
4113 security = connman_network_get_string(network, "WiFi.Security");
4114 if (security && g_str_equal(security, "ieee8021x") == true &&
4115 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4116 wifi->assoc_retry_count = 0;
4120 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
4121 wifi->assoc_retry_count = 0;
4123 /* Honestly it's not an invalid-key error,
4124 * however QA team recommends that the invalid-key error
4125 * might be better to display for user experience.
4127 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
4136 static void interface_state(GSupplicantInterface *interface)
4138 struct connman_network *network;
4139 struct connman_device *device;
4140 struct wifi_data *wifi;
4141 GSupplicantState state = g_supplicant_interface_get_state(interface);
4145 wifi = g_supplicant_interface_get_data(interface);
4147 DBG("wifi %p interface state %d", wifi, state);
4152 device = wifi->device;
4156 if (state == G_SUPPLICANT_STATE_COMPLETED) {
4157 if (wifi->tethering_param) {
4158 g_free(wifi->tethering_param->ssid);
4159 g_free(wifi->tethering_param);
4160 wifi->tethering_param = NULL;
4163 if (wifi->tethering)
4164 stop_autoscan(device);
4167 if (g_supplicant_interface_get_ready(interface) &&
4168 !wifi->interface_ready) {
4169 wifi->interface_ready = true;
4170 finalize_interface_creation(wifi);
4173 network = wifi->network;
4178 case G_SUPPLICANT_STATE_SCANNING:
4179 if (wifi->connected)
4180 connman_network_set_connected(network, false);
4184 case G_SUPPLICANT_STATE_AUTHENTICATING:
4185 case G_SUPPLICANT_STATE_ASSOCIATING:
4186 #if defined TIZEN_EXT
4187 reset_autoscan(device);
4189 stop_autoscan(device);
4192 if (!wifi->connected)
4193 connman_network_set_associating(network, true);
4197 case G_SUPPLICANT_STATE_COMPLETED:
4198 #if defined TIZEN_EXT
4199 /* though it should be already reset: */
4200 reset_autoscan(device);
4202 wifi->assoc_retry_count = 0;
4204 wifi->scan_pending_network = NULL;
4206 /* should be cleared scanning flag */
4207 bool scanning = connman_device_get_scanning(device,
4208 CONNMAN_SERVICE_TYPE_WIFI);
4210 connman_device_set_scanning(device,
4211 CONNMAN_SERVICE_TYPE_WIFI, false);
4212 connman_device_unref(device);
4215 if (!wifi->automaxspeed_timeout) {
4216 DBG("Going to start signalpoll timer!!");
4217 int ret = network_signalpoll(wifi);
4219 DBG("Fail to get max speed !!");
4221 wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
4224 g_hash_table_remove_all(failed_bssids);
4226 /* though it should be already stopped: */
4227 stop_autoscan(device);
4230 if (!handle_wps_completion(interface, network, device, wifi))
4233 connman_network_set_connected(network, true);
4235 wifi->disconnect_code = 0;
4236 wifi->assoc_code = 0;
4237 wifi->load_shaping_retries = 0;
4240 case G_SUPPLICANT_STATE_DISCONNECTED:
4241 #if defined TIZEN_EXT
4242 connman_network_set_strength(network, 0);
4243 connman_network_set_maxspeed(network, 0);
4245 if (wifi->automaxspeed_timeout != 0) {
4246 g_source_remove(wifi->automaxspeed_timeout);
4247 wifi->automaxspeed_timeout = 0;
4248 DBG("Remove signalpoll timer!!");
4252 * If we're in one of the idle modes, we have
4253 * not started association yet and thus setting
4254 * those ones to FALSE could cancel an association
4257 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4259 if (is_idle_wps(interface, wifi))
4265 #if defined TIZEN_EXT
4266 if (handle_assoc_status_code(interface, wifi)) {
4267 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4268 guint bssid_length = 0;
4271 bssid_length = g_slist_length(bssid_list);
4273 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4274 network_connect(network);
4278 wifi->load_shaping_retries = 0;
4281 g_hash_table_remove_all(failed_bssids);
4283 if (handle_assoc_status_code(interface, wifi))
4287 /* If previous state was 4way-handshake, then
4288 * it's either: psk was incorrect and thus we retry
4289 * or if we reach the maximum retries we declare the
4291 if (handle_4way_handshake_failure(interface,
4295 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4296 switch (wifi->disconnect_code) {
4297 case 1: /* Unspecified reason */
4298 /* Let's assume it's because we got blocked */
4300 case 6: /* Class 2 frame received from nonauthenticated STA */
4301 connman_network_set_error(network,
4302 CONNMAN_NETWORK_ERROR_BLOCKED);
4309 #if defined TIZEN_EXT
4310 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4311 * Retry association until its retry count is expired */
4312 if (handle_wifi_assoc_retry(network, wifi) == true) {
4313 throw_wifi_scan(wifi->device, scan_callback);
4314 wifi->scan_pending_network = wifi->network;
4318 if(wifi->disconnect_code > 0){
4319 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4320 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4324 if (network != wifi->pending_network) {
4325 connman_network_set_connected(network, false);
4326 connman_network_set_associating(network, false);
4328 wifi->disconnecting = false;
4330 start_autoscan(device);
4334 case G_SUPPLICANT_STATE_INACTIVE:
4335 #if defined TIZEN_EXT
4336 if (handle_wps_completion(interface, network, device, wifi) == false)
4339 connman_network_set_associating(network, false);
4340 start_autoscan(device);
4344 case G_SUPPLICANT_STATE_UNKNOWN:
4345 case G_SUPPLICANT_STATE_DISABLED:
4346 case G_SUPPLICANT_STATE_ASSOCIATED:
4347 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4348 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4352 old_connected = wifi->connected;
4353 wifi->state = state;
4355 /* Saving wpa_s state policy:
4356 * If connected and if the state changes are roaming related:
4357 * --> We stay connected
4359 * --> We are connected
4361 * --> We are not connected
4364 case G_SUPPLICANT_STATE_AUTHENTICATING:
4365 case G_SUPPLICANT_STATE_ASSOCIATING:
4366 case G_SUPPLICANT_STATE_ASSOCIATED:
4367 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4368 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4369 if (wifi->connected)
4370 connman_warn("Probably roaming right now!"
4371 " Staying connected...");
4373 case G_SUPPLICANT_STATE_SCANNING:
4374 wifi->connected = false;
4377 start_autoscan(device);
4379 case G_SUPPLICANT_STATE_COMPLETED:
4380 wifi->connected = true;
4383 wifi->connected = false;
4390 static void interface_removed(GSupplicantInterface *interface)
4392 const char *ifname = g_supplicant_interface_get_ifname(interface);
4393 struct wifi_data *wifi;
4395 DBG("ifname %s", ifname);
4397 wifi = g_supplicant_interface_get_data(interface);
4399 #if defined TIZEN_EXT_WIFI_MESH
4400 if (wifi && wifi->mesh_interface) {
4401 DBG("Notify mesh interface remove");
4402 connman_mesh_notify_interface_remove(true);
4403 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4404 g_free(mesh_info->parent_ifname);
4405 g_free(mesh_info->ifname);
4406 g_free(mesh_info->identifier);
4408 wifi->mesh_interface = false;
4409 wifi->mesh_info = NULL;
4415 wifi->interface = NULL;
4417 if (wifi && wifi->tethering)
4420 if (!wifi || !wifi->device) {
4421 DBG("wifi interface already removed");
4425 connman_device_set_powered(wifi->device, false);
4427 check_p2p_technology();
4428 #if defined TIZEN_EXT_WIFI_MESH
4429 check_mesh_technology();
4433 static void set_device_type(const char *type, char dev_type[17])
4435 const char *oui = "0050F204";
4436 const char *category = "0001";
4437 const char *sub_category = "0000";
4439 if (!g_strcmp0(type, "handset")) {
4441 sub_category = "0005";
4442 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4443 sub_category = "0001";
4444 else if (!g_strcmp0(type, "server"))
4445 sub_category = "0002";
4446 else if (!g_strcmp0(type, "laptop"))
4447 sub_category = "0005";
4448 else if (!g_strcmp0(type, "desktop"))
4449 sub_category = "0006";
4450 else if (!g_strcmp0(type, "tablet"))
4451 sub_category = "0009";
4452 else if (!g_strcmp0(type, "watch"))
4455 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4458 static void p2p_support(GSupplicantInterface *interface)
4460 char dev_type[17] = {};
4461 const char *hostname;
4468 if (!g_supplicant_interface_has_p2p(interface))
4471 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4472 DBG("Could not register P2P technology driver");
4476 hostname = connman_utsname_get_hostname();
4478 hostname = "ConnMan";
4480 set_device_type(connman_machine_get_type(), dev_type);
4481 g_supplicant_interface_set_p2p_device_config(interface,
4482 hostname, dev_type);
4483 connman_peer_driver_register(&peer_driver);
4486 static void scan_started(GSupplicantInterface *interface)
4491 static void scan_finished(GSupplicantInterface *interface)
4493 #if defined TIZEN_EXT
4494 struct wifi_data *wifi;
4495 bool is_associating = false;
4496 static bool is_scanning = true;
4501 #if defined TIZEN_EXT
4502 wifi = g_supplicant_interface_get_data(interface);
4503 if (wifi && wifi->scan_pending_network) {
4504 network_connect(wifi->scan_pending_network);
4505 wifi->scan_pending_network = NULL;
4508 //service state - associating
4509 if(!wifi || !wifi->network)
4512 is_associating = connman_network_get_associating(wifi->network);
4513 if(is_associating && is_scanning){
4514 is_scanning = false;
4515 DBG("send scan for connecting");
4516 throw_wifi_scan(wifi->device, scan_callback);
4527 static void ap_create_fail(GSupplicantInterface *interface)
4529 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4532 if ((wifi->tethering) && (wifi->tethering_param)) {
4533 DBG("%s create AP fail \n",
4534 g_supplicant_interface_get_ifname(wifi->interface));
4536 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4537 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4538 wifi->tethering = false;
4540 ret = tech_set_tethering(wifi->tethering_param->technology,
4541 wifi->tethering_param->ssid->ssid,
4542 wifi->tethering_param->ssid->passphrase,
4543 wifi->bridge, true);
4545 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4546 connman_technology_tethering_notify(wifi_technology,false);
4549 g_free(wifi->tethering_param->ssid);
4550 g_free(wifi->tethering_param);
4551 wifi->tethering_param = NULL;
4555 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4557 unsigned char strength;
4559 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4560 #if !defined TIZEN_EXT
4568 #if defined TIZEN_EXT_WIFI_MESH
4569 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4571 GSupplicantInterface *interface;
4572 struct wifi_data *wifi;
4573 const char *name, *security;
4574 struct connman_mesh *connman_mesh;
4575 struct wifi_mesh_info *mesh_info;
4576 const unsigned char *bssid;
4577 const char *identifier;
4582 interface = g_supplicant_network_get_interface(supplicant_network);
4583 wifi = g_supplicant_interface_get_data(interface);
4584 if (!wifi || !wifi->mesh_interface) {
4585 DBG("Virtual Mesh interface not created");
4589 bssid = g_supplicant_network_get_bssid(supplicant_network);
4590 address = g_malloc0(19);
4591 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4592 bssid[2], bssid[3], bssid[4], bssid[5]);
4594 identifier = g_supplicant_network_get_identifier(supplicant_network);
4595 name = g_supplicant_network_get_name(supplicant_network);
4596 security = g_supplicant_network_get_security(supplicant_network);
4597 frequency = g_supplicant_network_get_frequency(supplicant_network);
4599 mesh_info = wifi->mesh_info;
4600 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4604 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4606 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4607 connman_mesh_set_name(connman_mesh, name);
4608 connman_mesh_set_security(connman_mesh, security);
4609 connman_mesh_set_frequency(connman_mesh, frequency);
4610 connman_mesh_set_address(connman_mesh, address);
4611 connman_mesh_set_index(connman_mesh, mesh_info->index);
4612 connman_mesh_set_strength(connman_mesh,
4613 calculate_strength(supplicant_network));
4614 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4616 ret = connman_mesh_register(connman_mesh);
4617 if (ret == -EALREADY)
4618 DBG("Mesh Peer is already registered");
4624 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4626 GSupplicantInterface *interface;
4627 struct wifi_data *wifi;
4628 struct connman_mesh *connman_mesh;
4629 struct wifi_mesh_info *mesh_info;
4630 const char *identifier;
4632 interface = g_supplicant_network_get_interface(supplicant_network);
4633 wifi = g_supplicant_interface_get_data(interface);
4634 if (!wifi || !wifi->mesh_interface) {
4635 DBG("Virtual Mesh interface not created");
4639 identifier = g_supplicant_network_get_identifier(supplicant_network);
4641 DBG("Failed to get Mesh Peer identifier");
4645 mesh_info = wifi->mesh_info;
4646 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4648 /* Do not unregister connected mesh peer */
4649 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4650 DBG("Mesh Peer %s is connected", identifier);
4653 DBG("Mesh Peer identifier %s removed", identifier);
4654 connman_mesh_unregister(connman_mesh);
4659 static void network_added(GSupplicantNetwork *supplicant_network)
4661 struct connman_network *network;
4662 GSupplicantInterface *interface;
4663 struct wifi_data *wifi;
4664 const char *name, *identifier, *security, *group, *mode;
4665 const unsigned char *ssid;
4666 unsigned int ssid_len;
4670 bool wps_advertizing;
4672 #if defined TIZEN_EXT
4673 GSList *vsie_list = NULL;
4674 const unsigned char *country_code;
4675 ieee80211_modes_e phy_mode;
4678 mode = g_supplicant_network_get_mode(supplicant_network);
4679 identifier = g_supplicant_network_get_identifier(supplicant_network);
4681 DBG("%s", identifier);
4683 if (!g_strcmp0(mode, "adhoc"))
4686 #if defined TIZEN_EXT_WIFI_MESH
4687 if (!g_strcmp0(mode, "mesh")) {
4688 mesh_peer_added(supplicant_network);
4693 interface = g_supplicant_network_get_interface(supplicant_network);
4694 wifi = g_supplicant_interface_get_data(interface);
4695 name = g_supplicant_network_get_name(supplicant_network);
4696 security = g_supplicant_network_get_security(supplicant_network);
4697 group = g_supplicant_network_get_identifier(supplicant_network);
4698 wps = g_supplicant_network_get_wps(supplicant_network);
4699 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4700 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4701 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4702 supplicant_network);
4707 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4709 network = connman_device_get_network(wifi->device, identifier);
4712 network = connman_network_create(identifier,
4713 CONNMAN_NETWORK_TYPE_WIFI);
4717 connman_network_set_index(network, wifi->index);
4719 if (connman_device_add_network(wifi->device, network) < 0) {
4720 connman_network_unref(network);
4724 wifi->networks = g_slist_prepend(wifi->networks, network);
4727 if (name && name[0] != '\0')
4728 connman_network_set_name(network, name);
4730 connman_network_set_blob(network, "WiFi.SSID",
4732 #if defined TIZEN_EXT
4733 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4735 connman_network_set_vsie_list(network, vsie_list);
4737 DBG("vsie_list is NULL");
4738 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4739 connman_network_set_countrycode(network, country_code);
4740 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4741 connman_network_set_phy_mode(network, phy_mode);
4743 connman_network_set_string(network, "WiFi.Security", security);
4744 connman_network_set_strength(network,
4745 calculate_strength(supplicant_network));
4746 connman_network_set_bool(network, "WiFi.WPS", wps);
4747 connman_network_set_bool(network, "WiFi.WPSAdvertising",
4751 /* Is AP advertizing for WPS association?
4752 * If so, we decide to use WPS by default */
4753 if (wps_ready && wps_pbc &&
4755 #if !defined TIZEN_EXT
4756 connman_network_set_bool(network, "WiFi.UseWPS", true);
4758 DBG("wps is activating by ap but ignore it.");
4762 connman_network_set_frequency(network,
4763 g_supplicant_network_get_frequency(supplicant_network));
4765 #if defined TIZEN_EXT
4766 connman_network_set_bssid(network,
4767 g_supplicant_network_get_bssid(supplicant_network));
4768 connman_network_set_maxrate(network,
4769 g_supplicant_network_get_maxrate(supplicant_network));
4770 connman_network_set_enc_mode(network,
4771 g_supplicant_network_get_enc_mode(supplicant_network));
4772 connman_network_set_rsn_mode(network,
4773 g_supplicant_network_get_rsn_mode(supplicant_network));
4774 connman_network_set_keymgmt(network,
4775 g_supplicant_network_get_keymgmt(supplicant_network));
4776 connman_network_set_bool(network, "WiFi.HS20AP",
4777 g_supplicant_network_is_hs20AP(supplicant_network));
4778 connman_network_set_bssid_list(network,
4779 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4781 connman_network_set_available(network, true);
4782 connman_network_set_string(network, "WiFi.Mode", mode);
4784 #if defined TIZEN_EXT
4789 connman_network_set_group(network, group);
4791 #if defined TIZEN_EXT
4792 if (wifi_first_scan == true)
4793 found_with_first_scan = true;
4796 if (wifi->hidden && ssid) {
4797 #if defined TIZEN_EXT
4798 if (network_security(wifi->hidden->security) ==
4799 network_security(security) &&
4801 if (!g_strcmp0(wifi->hidden->security, security) &&
4803 wifi->hidden->ssid_len == ssid_len &&
4804 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4805 connman_network_connect_hidden(network,
4806 wifi->hidden->identity,
4807 wifi->hidden->passphrase,
4808 wifi->hidden->user_data);
4809 wifi->hidden->user_data = NULL;
4810 hidden_free(wifi->hidden);
4811 wifi->hidden = NULL;
4816 static void network_removed(GSupplicantNetwork *network)
4818 GSupplicantInterface *interface;
4819 struct wifi_data *wifi;
4820 const char *name, *identifier;
4821 struct connman_network *connman_network;
4823 #if defined TIZEN_EXT_WIFI_MESH
4825 mode = g_supplicant_network_get_mode(network);
4826 if (!g_strcmp0(mode, "mesh")) {
4827 mesh_peer_removed(network);
4832 interface = g_supplicant_network_get_interface(network);
4833 wifi = g_supplicant_interface_get_data(interface);
4834 identifier = g_supplicant_network_get_identifier(network);
4835 name = g_supplicant_network_get_name(network);
4837 DBG("name %s", name);
4842 connman_network = connman_device_get_network(wifi->device, identifier);
4843 if (!connman_network)
4846 #if defined TIZEN_EXT
4847 if (connman_network == wifi->scan_pending_network)
4848 wifi->scan_pending_network = NULL;
4850 if (connman_network == wifi->pending_network)
4851 wifi->pending_network = NULL;
4853 if(connman_network_get_connecting(connman_network) == true){
4854 connman_network_set_connected(connman_network, false);
4858 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4860 connman_device_remove_network(wifi->device, connman_network);
4861 connman_network_unref(connman_network);
4864 static void network_changed(GSupplicantNetwork *network, const char *property)
4866 GSupplicantInterface *interface;
4867 struct wifi_data *wifi;
4868 const char *name, *identifier;
4869 struct connman_network *connman_network;
4872 #if defined TIZEN_EXT
4873 const unsigned char *bssid;
4874 unsigned int maxrate;
4877 const unsigned char *country_code;
4878 ieee80211_modes_e phy_mode;
4882 interface = g_supplicant_network_get_interface(network);
4883 wifi = g_supplicant_interface_get_data(interface);
4884 identifier = g_supplicant_network_get_identifier(network);
4885 name = g_supplicant_network_get_name(network);
4887 DBG("name %s", name);
4892 connman_network = connman_device_get_network(wifi->device, identifier);
4893 if (!connman_network)
4896 if (g_str_equal(property, "WPSCapabilities")) {
4900 bool wps_advertizing;
4902 wps = g_supplicant_network_get_wps(network);
4903 wps_pbc = g_supplicant_network_is_wps_pbc(network);
4904 wps_ready = g_supplicant_network_is_wps_active(network);
4906 g_supplicant_network_is_wps_advertizing(network);
4908 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4909 connman_network_set_bool(connman_network,
4910 "WiFi.WPSAdvertising", wps_advertizing);
4914 * Is AP advertizing for WPS association?
4915 * If so, we decide to use WPS by default
4917 if (wps_ready && wps_pbc && wps_advertizing)
4918 connman_network_set_bool(connman_network,
4919 "WiFi.UseWPS", true);
4922 update_needed = true;
4923 } else if (g_str_equal(property, "Signal")) {
4924 connman_network_set_strength(connman_network,
4925 calculate_strength(network));
4926 update_needed = true;
4928 update_needed = false;
4931 connman_network_update(connman_network);
4933 #if defined TIZEN_EXT
4934 bssid = g_supplicant_network_get_bssid(network);
4935 maxrate = g_supplicant_network_get_maxrate(network);
4936 frequency = g_supplicant_network_get_frequency(network);
4937 wps = g_supplicant_network_get_wps(network);
4938 phy_mode = g_supplicant_network_get_phy_mode(network);
4940 connman_network_set_bssid(connman_network, bssid);
4941 connman_network_set_maxrate(connman_network, maxrate);
4942 connman_network_set_frequency(connman_network, frequency);
4943 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4944 country_code = g_supplicant_network_get_countrycode(network);
4945 connman_network_set_countrycode(connman_network, country_code);
4946 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4947 connman_network_set_bssid_list(connman_network, bssid_list);
4948 connman_network_set_phy_mode(connman_network, phy_mode);
4950 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4951 connman_network_get_associating(connman_network))
4952 network_connect(connman_network);
4956 static void network_associated(GSupplicantNetwork *network)
4958 GSupplicantInterface *interface;
4959 struct wifi_data *wifi;
4960 struct connman_network *connman_network;
4961 const char *identifier;
4965 interface = g_supplicant_network_get_interface(network);
4969 wifi = g_supplicant_interface_get_data(interface);
4973 /* P2P networks must not be treated as WiFi networks */
4974 if (wifi->p2p_connecting || wifi->p2p_device)
4977 identifier = g_supplicant_network_get_identifier(network);
4979 connman_network = connman_device_get_network(wifi->device, identifier);
4980 if (!connman_network)
4983 if (wifi->network) {
4984 if (wifi->network == connman_network)
4988 * This should never happen, we got associated with
4989 * a network different than the one we were expecting.
4991 DBG("Associated to %p while expecting %p",
4992 connman_network, wifi->network);
4994 connman_network_set_associating(wifi->network, false);
4997 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4999 wifi->network = connman_network_ref(connman_network);
5003 * Interface state changes callback (interface_state) is always
5004 * called before network_associated callback thus we need to call
5005 * interface_state again in order to process the new state now that
5006 * we have the network properly set.
5008 interface_state(interface);
5011 static void sta_authorized(GSupplicantInterface *interface,
5014 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5016 DBG("wifi %p station %s authorized", wifi, addr);
5018 if (!wifi || !wifi->tethering)
5021 __connman_tethering_client_register(addr);
5024 static void sta_deauthorized(GSupplicantInterface *interface,
5027 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5029 DBG("wifi %p station %s deauthorized", wifi, addr);
5031 if (!wifi || !wifi->tethering)
5034 __connman_tethering_client_unregister(addr);
5037 static void apply_peer_services(GSupplicantPeer *peer,
5038 struct connman_peer *connman_peer)
5040 const unsigned char *data;
5045 connman_peer_reset_services(connman_peer);
5047 data = g_supplicant_peer_get_widi_ies(peer, &length);
5049 connman_peer_add_service(connman_peer,
5050 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
5054 static void peer_found(GSupplicantPeer *peer)
5056 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5057 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5058 struct connman_peer *connman_peer;
5059 const char *identifier, *name;
5062 #if defined TIZEN_EXT
5066 identifier = g_supplicant_peer_get_identifier(peer);
5067 name = g_supplicant_peer_get_name(peer);
5069 DBG("ident: %s", identifier);
5071 connman_peer = connman_peer_get(wifi->device, identifier);
5075 connman_peer = connman_peer_create(identifier);
5076 connman_peer_set_name(connman_peer, name);
5077 connman_peer_set_device(connman_peer, wifi->device);
5078 apply_peer_services(peer, connman_peer);
5080 ret = connman_peer_register(connman_peer);
5081 if (ret < 0 && ret != -EALREADY)
5082 connman_peer_unref(connman_peer);
5084 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
5087 static void peer_lost(GSupplicantPeer *peer)
5089 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5090 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5091 struct connman_peer *connman_peer;
5092 const char *identifier;
5097 identifier = g_supplicant_peer_get_identifier(peer);
5099 DBG("ident: %s", identifier);
5101 connman_peer = connman_peer_get(wifi->device, identifier);
5103 if (wifi->p2p_connecting &&
5104 wifi->pending_peer == connman_peer) {
5105 peer_connect_timeout(wifi);
5107 connman_peer_unregister(connman_peer);
5108 connman_peer_unref(connman_peer);
5111 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
5114 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
5116 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5117 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5118 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
5119 struct connman_peer *connman_peer;
5120 const char *identifier;
5122 identifier = g_supplicant_peer_get_identifier(peer);
5124 DBG("ident: %s", identifier);
5129 connman_peer = connman_peer_get(wifi->device, identifier);
5134 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
5135 apply_peer_services(peer, connman_peer);
5136 connman_peer_services_changed(connman_peer);
5138 case G_SUPPLICANT_PEER_GROUP_CHANGED:
5139 if (!g_supplicant_peer_is_in_a_group(peer))
5140 p_state = CONNMAN_PEER_STATE_IDLE;
5142 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
5144 case G_SUPPLICANT_PEER_GROUP_STARTED:
5146 case G_SUPPLICANT_PEER_GROUP_FINISHED:
5147 p_state = CONNMAN_PEER_STATE_IDLE;
5149 case G_SUPPLICANT_PEER_GROUP_JOINED:
5150 connman_peer_set_iface_address(connman_peer,
5151 g_supplicant_peer_get_iface_address(peer));
5153 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
5154 p_state = CONNMAN_PEER_STATE_IDLE;
5156 case G_SUPPLICANT_PEER_GROUP_FAILED:
5157 if (g_supplicant_peer_has_requested_connection(peer))
5158 p_state = CONNMAN_PEER_STATE_IDLE;
5160 p_state = CONNMAN_PEER_STATE_FAILURE;
5164 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
5165 p_state == CONNMAN_PEER_STATE_FAILURE) {
5166 if (wifi->p2p_connecting
5167 && connman_peer == wifi->pending_peer)
5168 peer_cancel_timeout(wifi);
5170 p_state = CONNMAN_PEER_STATE_UNKNOWN;
5173 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
5176 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
5177 GSupplicantInterface *g_iface;
5178 struct wifi_data *g_wifi;
5180 g_iface = g_supplicant_peer_get_group_interface(peer);
5184 g_wifi = g_supplicant_interface_get_data(g_iface);
5188 connman_peer_set_as_master(connman_peer,
5189 !g_supplicant_peer_is_client(peer));
5190 connman_peer_set_sub_device(connman_peer, g_wifi->device);
5193 * If wpa_supplicant didn't create a dedicated p2p-group
5194 * interface then mark this interface as p2p_device to avoid
5195 * scan and auto-scan are launched on it while P2P is connected.
5197 if (!g_list_find(p2p_iface_list, g_wifi))
5198 wifi->p2p_device = true;
5201 connman_peer_set_state(connman_peer, p_state);
5204 static void peer_request(GSupplicantPeer *peer)
5206 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5207 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5208 struct connman_peer *connman_peer;
5209 const char *identifier;
5211 #if defined TIZEN_EXT
5216 identifier = g_supplicant_peer_get_identifier(peer);
5218 DBG("ident: %s", identifier);
5220 connman_peer = connman_peer_get(wifi->device, identifier);
5224 connman_peer_request_connection(connman_peer);
5227 #if defined TIZEN_EXT
5228 static void system_power_off(void)
5231 struct wifi_data *wifi;
5232 struct connman_service *service;
5233 struct connman_ipconfig *ipconfig_ipv4;
5235 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
5236 for (list = iface_list; list; list = list->next) {
5239 if (wifi->network != NULL) {
5240 service = connman_service_lookup_from_network(wifi->network);
5241 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5242 __connman_dhcp_stop(ipconfig_ipv4);
5248 static void network_merged(GSupplicantNetwork *network)
5250 GSupplicantInterface *interface;
5251 GSupplicantState state;
5252 struct wifi_data *wifi;
5253 const char *identifier;
5254 struct connman_network *connman_network;
5258 interface = g_supplicant_network_get_interface(network);
5262 state = g_supplicant_interface_get_state(interface);
5263 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5266 wifi = g_supplicant_interface_get_data(interface);
5270 identifier = g_supplicant_network_get_identifier(network);
5272 connman_network = connman_device_get_network(wifi->device, identifier);
5273 if (!connman_network)
5276 DBG("merged identifier %s", identifier);
5278 if (wifi->connected == FALSE) {
5280 case G_SUPPLICANT_STATE_AUTHENTICATING:
5281 case G_SUPPLICANT_STATE_ASSOCIATING:
5282 case G_SUPPLICANT_STATE_ASSOCIATED:
5283 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5284 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5285 connman_network_set_associating(connman_network, TRUE);
5287 case G_SUPPLICANT_STATE_COMPLETED:
5288 connman_network_set_connected(connman_network, TRUE);
5291 DBG("Not handled the state : %d", state);
5296 ishs20AP = g_supplicant_network_is_hs20AP(network);
5299 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5300 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5301 connman_network_set_string(connman_network, "WiFi.EAP",
5303 connman_network_set_string(connman_network, "WiFi.Identity",
5304 g_supplicant_network_get_identity(network));
5305 connman_network_set_string(connman_network, "WiFi.Phase2",
5306 g_supplicant_network_get_phase2(network));
5311 wifi->network = connman_network;
5314 static void assoc_failed(void *user_data)
5316 struct connman_network *network = user_data;
5317 connman_network_set_associating(network, false);
5321 static void debug(const char *str)
5323 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5324 connman_debug("%s", str);
5327 static void disconnect_reasoncode(GSupplicantInterface *interface,
5330 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5333 wifi->disconnect_code = reasoncode;
5337 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5339 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5342 wifi->assoc_code = status_code;
5346 static const GSupplicantCallbacks callbacks = {
5347 .system_ready = system_ready,
5348 .system_killed = system_killed,
5349 .interface_added = interface_added,
5350 .interface_state = interface_state,
5351 .interface_removed = interface_removed,
5352 .p2p_support = p2p_support,
5353 .scan_started = scan_started,
5354 .scan_finished = scan_finished,
5355 .ap_create_fail = ap_create_fail,
5356 .network_added = network_added,
5357 .network_removed = network_removed,
5358 .network_changed = network_changed,
5359 .network_associated = network_associated,
5360 .sta_authorized = sta_authorized,
5361 .sta_deauthorized = sta_deauthorized,
5362 .peer_found = peer_found,
5363 .peer_lost = peer_lost,
5364 .peer_changed = peer_changed,
5365 .peer_request = peer_request,
5366 #if defined TIZEN_EXT
5367 .system_power_off = system_power_off,
5368 .network_merged = network_merged,
5369 .assoc_failed = assoc_failed,
5372 .disconnect_reasoncode = disconnect_reasoncode,
5373 .assoc_status_code = assoc_status_code,
5374 #if defined TIZEN_EXT_WIFI_MESH
5375 .mesh_support = mesh_support,
5376 .mesh_group_started = mesh_group_started,
5377 .mesh_group_removed = mesh_group_removed,
5378 .mesh_peer_connected = mesh_peer_connected,
5379 .mesh_peer_disconnected = mesh_peer_disconnected,
5384 static int tech_probe(struct connman_technology *technology)
5386 wifi_technology = technology;
5391 static void tech_remove(struct connman_technology *technology)
5393 wifi_technology = NULL;
5396 static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
5398 GSupplicantSSID *ap;
5400 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5404 ap->mode = G_SUPPLICANT_MODE_MASTER;
5405 #if defined TIZEN_EXT
5406 ap->ssid = (void *) ssid;
5410 ap->ssid_len = strlen(ssid);
5414 if (!passphrase || strlen(passphrase) == 0) {
5415 ap->security = G_SUPPLICANT_SECURITY_NONE;
5416 ap->passphrase = NULL;
5418 ap->security = G_SUPPLICANT_SECURITY_PSK;
5419 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5420 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5421 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5422 ap->passphrase = passphrase;
5428 static void ap_start_callback(int result, GSupplicantInterface *interface,
5431 struct wifi_tethering_info *info = user_data;
5433 DBG("result %d index %d bridge %s",
5434 result, info->wifi->index, info->wifi->bridge);
5436 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5437 connman_inet_remove_from_bridge(info->wifi->index,
5438 info->wifi->bridge);
5440 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5441 connman_technology_tethering_notify(info->technology, false);
5442 g_free(info->wifi->tethering_param->ssid);
5443 g_free(info->wifi->tethering_param);
5444 info->wifi->tethering_param = NULL;
5448 g_free(info->ifname);
5452 static void ap_create_callback(int result,
5453 GSupplicantInterface *interface,
5456 struct wifi_tethering_info *info = user_data;
5458 DBG("result %d ifname %s", result,
5459 g_supplicant_interface_get_ifname(interface));
5461 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5462 connman_inet_remove_from_bridge(info->wifi->index,
5463 info->wifi->bridge);
5465 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5466 connman_technology_tethering_notify(info->technology, false);
5467 g_free(info->wifi->tethering_param->ssid);
5468 g_free(info->wifi->tethering_param);
5469 info->wifi->tethering_param = NULL;
5473 g_free(info->ifname);
5479 info->wifi->interface = interface;
5480 g_supplicant_interface_set_data(interface, info->wifi);
5482 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5483 connman_error("Failed to set interface ap_scan property");
5485 g_supplicant_interface_connect(interface, info->ssid,
5486 ap_start_callback, info);
5489 static void sta_remove_callback(int result,
5490 GSupplicantInterface *interface,
5493 struct wifi_tethering_info *info = user_data;
5494 const char *driver = connman_option_get_string("wifi");
5496 DBG("ifname %s result %d ", info->ifname, result);
5498 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5499 info->wifi->tethering = false;
5500 connman_technology_tethering_notify(info->technology, false);
5501 #if !defined TIZEN_EXT
5503 g_free(info->ifname);
5506 #endif /* !defined TIZEN_EXT */
5508 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5509 g_free(info->wifi->tethering_param->ssid);
5510 g_free(info->wifi->tethering_param);
5511 info->wifi->tethering_param = NULL;
5513 #if defined TIZEN_EXT
5515 g_free(info->ifname);
5518 #endif /* defined TIZEN_EXT */
5522 info->wifi->interface = NULL;
5524 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5529 static int enable_wifi_tethering(struct connman_technology *technology,
5530 const char *bridge, const char *identifier,
5531 const char *passphrase, bool available)
5534 GSupplicantInterface *interface;
5535 struct wifi_data *wifi;
5536 struct wifi_tethering_info *info;
5541 for (list = iface_list; list; list = list->next) {
5544 DBG("wifi %p network %p pending_network %p", wifi,
5545 wifi->network, wifi->pending_network);
5547 interface = wifi->interface;
5552 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5556 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5557 DBG("%s does not support AP mode (detected)", ifname);
5561 mode = g_supplicant_interface_get_mode(interface);
5562 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5563 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5564 DBG("%s does not support AP mode (capability)", ifname);
5568 if (wifi->network && available)
5571 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5575 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5576 if (!wifi->tethering_param) {
5582 info->technology = technology;
5583 info->wifi->bridge = bridge;
5584 info->ssid = ssid_ap_init(identifier, passphrase);
5588 info->ifname = g_strdup(ifname);
5590 wifi->tethering_param->technology = technology;
5591 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5592 if (!wifi->tethering_param->ssid)
5595 info->wifi->tethering = true;
5596 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5598 berr = connman_technology_tethering_notify(technology, true);
5602 err = g_supplicant_interface_remove(interface,
5603 sta_remove_callback,
5606 DBG("tethering wifi %p ifname %s", wifi, ifname);
5611 g_free(info->ifname);
5614 g_free(wifi->tethering_param);
5615 wifi->tethering_param = NULL;
5618 * Remove bridge if it was correctly created but remove
5619 * operation failed. Instead, if bridge creation failed then
5620 * break out and do not try again on another interface,
5621 * bridge set-up does not depend on it.
5624 connman_technology_tethering_notify(technology, false);
5632 static int tech_set_tethering(struct connman_technology *technology,
5633 const char *identifier, const char *passphrase,
5634 const char *bridge, bool enabled)
5637 struct wifi_data *wifi;
5643 for (list = iface_list; list; list = list->next) {
5646 if (wifi->tethering) {
5647 wifi->tethering = false;
5649 connman_inet_remove_from_bridge(wifi->index,
5651 wifi->bridged = false;
5655 connman_technology_tethering_notify(technology, false);
5660 DBG("trying tethering for available devices");
5661 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5665 DBG("trying tethering for any device");
5666 err = enable_wifi_tethering(technology, bridge, identifier,
5673 static void regdom_callback(int result, const char *alpha2, void *user_data)
5677 if (!wifi_technology)
5683 connman_technology_regdom_notify(wifi_technology, alpha2);
5686 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5688 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5691 static struct connman_technology_driver tech_driver = {
5693 .type = CONNMAN_SERVICE_TYPE_WIFI,
5694 .probe = tech_probe,
5695 .remove = tech_remove,
5696 .set_tethering = tech_set_tethering,
5697 .set_regdom = tech_set_regdom,
5700 static int wifi_init(void)
5704 err = connman_network_driver_register(&network_driver);
5708 err = g_supplicant_register(&callbacks);
5710 connman_network_driver_unregister(&network_driver);
5714 err = connman_technology_driver_register(&tech_driver);
5716 g_supplicant_unregister(&callbacks);
5717 connman_network_driver_unregister(&network_driver);
5721 #if defined TIZEN_EXT
5722 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5727 static void wifi_exit(void)
5731 connman_technology_driver_unregister(&tech_driver);
5733 g_supplicant_unregister(&callbacks);
5735 connman_network_driver_unregister(&network_driver);
5737 #if defined TIZEN_EXT
5738 g_hash_table_unref(failed_bssids);
5742 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5743 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)