5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <net/ethernet.h>
34 #include <linux/wireless.h>
37 #define IFF_LOWER_UP 0x10000
40 #include <dbus/dbus.h>
43 #define CONNMAN_API_SUBJECT_TO_CHANGE
44 #include <connman/plugin.h>
45 #include <connman/inet.h>
46 #include <connman/device.h>
47 #include <connman/rtnl.h>
48 #include <connman/technology.h>
49 #include <connman/service.h>
50 #include <connman/peer.h>
51 #include <connman/log.h>
52 #include <connman/option.h>
53 #include <connman/storage.h>
54 #include <include/setting.h>
55 #include <connman/provision.h>
56 #include <connman/utsname.h>
57 #include <connman/machine.h>
58 #include <connman/tethering.h>
60 #include <gsupplicant/gsupplicant.h>
62 #define CLEANUP_TIMEOUT 8 /* in seconds */
63 #define INACTIVE_TIMEOUT 12 /* in seconds */
64 #define FAVORITE_MAXIMUM_RETRIES 2
66 #define BGSCAN_DEFAULT "simple:30:-45:300"
67 #define AUTOSCAN_EXPONENTIAL "exponential:3:300"
68 #define AUTOSCAN_SINGLE "single:3"
70 #define P2P_FIND_TIMEOUT 30
71 #define P2P_CONNECTION_TIMEOUT 100
72 #define P2P_LISTEN_PERIOD 500
73 #define P2P_LISTEN_INTERVAL 2000
75 #define ASSOC_STATUS_NO_CLIENT 17
77 #define LOAD_SHAPING_MAX_RETRIES 7
79 #define LOAD_SHAPING_MAX_RETRIES 3
83 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
86 static struct connman_technology *wifi_technology = NULL;
87 static struct connman_technology *p2p_technology = NULL;
89 enum wifi_ap_capability{
91 WIFI_AP_SUPPORTED = 1,
92 WIFI_AP_NOT_SUPPORTED = 2,
95 enum wifi_scanning_type {
96 WIFI_SCANNING_UNKNOWN = 0,
97 WIFI_SCANNING_PASSIVE = 1,
98 WIFI_SCANNING_ACTIVE = 2,
101 struct hidden_params {
103 unsigned int ssid_len;
105 char *anonymous_identity;
107 char *altsubject_match;
108 char *domain_suffix_match;
112 GSupplicantScanParams *scan_params;
117 * Used for autoscan "emulation".
118 * Should be removed when wpa_s autoscan support will be by default.
120 struct autoscan_params {
124 unsigned int timeout;
127 struct wifi_tethering_info {
128 struct wifi_data *wifi;
129 struct connman_technology *technology;
131 GSupplicantSSID *ssid;
136 struct connman_device *device;
137 struct connman_network *network;
138 struct connman_network *pending_network;
140 GSupplicantInterface *interface;
141 GSupplicantState state;
145 enum wifi_ap_capability ap_supported;
147 bool interface_ready;
153 int load_shaping_retries;
154 struct hidden_params *hidden;
155 bool postpone_hidden;
156 struct wifi_tethering_info *tethering_param;
158 * autoscan "emulation".
160 struct autoscan_params *autoscan;
161 enum wifi_scanning_type scanning_type;
162 GSupplicantScanParams *scan_params;
163 unsigned int p2p_find_timeout;
164 unsigned int p2p_connection_timeout;
165 struct connman_peer *pending_peer;
170 #if defined TIZEN_EXT
171 int assoc_retry_count;
172 struct connman_network *scan_pending_network;
173 bool allow_full_scan;
174 unsigned int automaxspeed_timeout;
175 GSupplicantScanParams *hidden_scan_params;
179 #if defined TIZEN_EXT_WIFI_MESH
181 struct wifi_mesh_info *mesh_info;
185 #if defined TIZEN_EXT
189 #define TIZEN_ASSOC_RETRY_COUNT 4
191 static gboolean wifi_first_scan = false;
192 static gboolean found_with_first_scan = false;
193 static gboolean is_wifi_notifier_registered = false;
194 static GHashTable *failed_bssids = NULL;
195 static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
199 static GList *iface_list = NULL;
201 static GList *pending_wifi_device = NULL;
202 static GList *p2p_iface_list = NULL;
203 static bool wfd_service_registered = false;
205 static void start_autoscan(struct connman_device *device);
206 static int tech_set_tethering(struct connman_technology *technology,
207 const char *identifier, const char *passphrase,
208 const char *bridge, bool enabled);
210 #if defined TIZEN_EXT
211 #define NETCONFIG_SERVICE "net.netconfig"
212 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
213 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
215 struct enc_method_call_data {
216 DBusConnection *connection;
217 struct connman_network *network;
220 static struct enc_method_call_data encrypt_request_data;
222 static void encryption_request_reply(DBusPendingCall *call,
227 DBusMessageIter args;
229 struct connman_service *service;
230 gchar* encrypted_value = NULL;
231 struct connman_network *network = encrypt_request_data.network;
235 reply = dbus_pending_call_steal_reply(call);
237 dbus_error_init(&error);
238 if (dbus_set_error_from_message(&error, reply)) {
239 DBG("send_encryption_request() %s %s", error.name, error.message);
240 dbus_error_free(&error);
244 if (dbus_message_iter_init(reply, &args) == FALSE)
247 dbus_message_iter_get_basic(&args, &out_data);
249 encrypted_value = g_strdup((const gchar *)out_data);
250 service = connman_service_lookup_from_network(network);
253 DBG("encryption result: no service");
257 if (connman_service_get_favorite(service)) {
258 __connman_service_set_passphrase(service, encrypted_value);
259 __connman_service_save(service);
261 connman_network_set_string(network, "WiFi.Passphrase",
264 DBG("encryption result: succeeded");
267 dbus_message_unref(reply);
268 dbus_pending_call_unref(call);
269 dbus_connection_unref(encrypt_request_data.connection);
270 g_free(encrypted_value);
272 encrypt_request_data.connection = NULL;
273 encrypt_request_data.network = NULL;
276 static int send_encryption_request(const char *passphrase,
277 struct connman_network *network)
279 DBusConnection *connection = NULL;
280 DBusMessage *msg = NULL;
281 DBusPendingCall *call;
284 DBG("Invalid parameter");
288 connection = connman_dbus_get_connection();
290 DBG("dbus connection does not exist");
294 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
295 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
297 dbus_connection_unref(connection);
301 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
304 if (!dbus_connection_send_with_reply(connection, msg,
305 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
306 dbus_message_unref(msg);
307 dbus_connection_unref(connection);
312 dbus_message_unref(msg);
313 dbus_connection_unref(connection);
317 encrypt_request_data.connection = connection;
318 encrypt_request_data.network = network;
320 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
321 dbus_message_unref(msg);
327 static int p2p_tech_probe(struct connman_technology *technology)
329 p2p_technology = technology;
334 static void p2p_tech_remove(struct connman_technology *technology)
336 p2p_technology = NULL;
339 static struct connman_technology_driver p2p_tech_driver = {
341 .type = CONNMAN_SERVICE_TYPE_P2P,
342 .probe = p2p_tech_probe,
343 .remove = p2p_tech_remove,
346 static bool is_p2p_connecting(void)
350 for (list = iface_list; list; list = list->next) {
351 struct wifi_data *wifi = list->data;
353 if (wifi->p2p_connecting)
360 static void add_pending_wifi_device(struct wifi_data *wifi)
362 if (g_list_find(pending_wifi_device, wifi))
365 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
368 #if defined TIZEN_EXT_WIFI_MESH
369 struct wifi_mesh_info {
370 struct wifi_data *wifi;
371 GSupplicantInterface *interface;
372 struct connman_mesh *mesh;
379 struct mesh_change_peer_status_info {
381 enum connman_mesh_peer_status peer_status;
382 mesh_change_peer_status_cb_t callback;
386 static struct connman_technology_driver mesh_tech_driver = {
388 .type = CONNMAN_SERVICE_TYPE_MESH,
391 static void mesh_interface_create_callback(int result,
392 GSupplicantInterface *interface,
395 struct wifi_mesh_info *mesh_info = user_data;
396 struct wifi_data *wifi;
397 bool success = false;
399 DBG("result %d ifname %s, mesh_info %p", result,
400 g_supplicant_interface_get_ifname(interface),
403 if (result < 0 || !mesh_info)
406 wifi = mesh_info->wifi;
408 mesh_info->interface = interface;
409 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
410 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
411 DBG("Mesh Interface identifier %s", mesh_info->identifier);
412 wifi->mesh_interface = true;
413 wifi->mesh_info = mesh_info;
414 g_supplicant_interface_set_data(interface, wifi);
418 connman_mesh_notify_interface_create(success);
421 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
424 struct wifi_data *wifi;
425 struct wifi_mesh_info *mesh_info;
426 const char *wifi_ifname;
427 bool parent_found = false;
428 const char *driver = "nl80211";
430 for (list = iface_list; list; list = list->next) {
433 if (!g_supplicant_interface_has_mesh(wifi->interface))
436 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
440 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
447 DBG("Parent interface %s doesn't exist", parent_ifname);
451 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
455 mesh_info->wifi = wifi;
456 mesh_info->ifname = g_strdup(ifname);
457 mesh_info->parent_ifname = g_strdup(parent_ifname);
459 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
460 mesh_interface_create_callback, mesh_info);
464 static void mesh_interface_remove_callback(int result,
465 GSupplicantInterface *interface,
468 struct wifi_data *wifi = user_data;
469 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
470 bool success = false;
472 DBG("result %d mesh_info %p", result, mesh_info);
474 if (result < 0 || !mesh_info)
477 mesh_info->interface = NULL;
478 g_free(mesh_info->parent_ifname);
479 g_free(mesh_info->ifname);
480 g_free(mesh_info->identifier);
482 wifi->mesh_interface = false;
483 wifi->mesh_info = NULL;
487 connman_mesh_notify_interface_remove(success);
490 static int remove_mesh_interface(const char *ifname)
493 struct wifi_data *wifi;
494 struct wifi_mesh_info *mesh_info;
495 bool mesh_if_found = false;
498 for (list = iface_list; list; list = list->next) {
501 if (wifi->mesh_interface) {
502 mesh_if_found = true;
507 if (!mesh_if_found) {
508 DBG("Mesh interface %s doesn't exist", ifname);
512 mesh_info = wifi->mesh_info;
513 ret = g_supplicant_interface_remove(mesh_info->interface,
514 mesh_interface_remove_callback, wifi);
521 static void mesh_disconnect_callback(int result,
522 GSupplicantInterface *interface, void *user_data)
524 struct connman_mesh *mesh = user_data;
526 DBG("result %d interface %p mesh %p", result, interface, mesh);
529 static int mesh_peer_disconnect(struct connman_mesh *mesh)
532 struct wifi_data *wifi;
533 struct wifi_mesh_info *mesh_info;
534 bool mesh_if_found = false;
535 GSupplicantInterface *interface;
537 for (list = iface_list; list; list = list->next) {
540 if (wifi->mesh_interface) {
541 mesh_if_found = true;
546 if (!mesh_if_found) {
547 DBG("Mesh interface is not created");
551 mesh_info = wifi->mesh_info;
553 interface = mesh_info->interface;
554 return g_supplicant_interface_disconnect(interface,
555 mesh_disconnect_callback, mesh);
558 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
561 struct connman_mesh *mesh = user_data;
562 DBG("mesh %p result %d", mesh, result);
565 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
567 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
570 static GSupplicantSecurity mesh_network_security(const char *security)
572 if (g_str_equal(security, "none"))
573 return G_SUPPLICANT_SECURITY_NONE;
574 else if (g_str_equal(security, "sae"))
575 return G_SUPPLICANT_SECURITY_SAE;
577 return G_SUPPLICANT_SECURITY_UNKNOWN;
580 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
583 const char *security;
588 memset(ssid, 0, sizeof(*ssid));
589 ssid->mode = G_SUPPLICANT_MODE_MESH;
591 security = connman_mesh_get_security(mesh);
592 ssid->security = mesh_network_security(security);
594 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
595 ssid->passphrase = connman_mesh_get_passphrase(mesh);
597 ssid->freq = connman_mesh_get_frequency(mesh);
598 name = connman_mesh_get_name(mesh);
600 ssid->ssid_len = strlen(name);
601 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
602 memcpy(ssid->ssid, name, ssid->ssid_len);
607 static int mesh_peer_connect(struct connman_mesh *mesh)
610 struct wifi_data *wifi;
611 struct wifi_mesh_info *mesh_info;
612 bool mesh_if_found = false;
613 GSupplicantInterface *interface;
614 GSupplicantSSID *ssid;
616 for (list = iface_list; list; list = list->next) {
619 if (wifi->mesh_interface) {
620 mesh_if_found = true;
625 if (!mesh_if_found) {
626 DBG("Mesh interface is not created");
630 mesh_info = wifi->mesh_info;
632 interface = mesh_info->interface;
634 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
638 mesh_info->mesh = mesh;
640 mesh_ssid_init(ssid, mesh);
641 return g_supplicant_interface_connect(interface, ssid,
642 mesh_connect_callback, mesh);
645 static void mesh_peer_change_status_callback(int result,
646 GSupplicantInterface *interface,
649 struct mesh_change_peer_status_info *data = user_data;
651 DBG("result %d Peer Status %d", result, data->peer_status);
653 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
654 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
655 connman_mesh_remove_connected_peer(data->peer_address, 52);
659 data->callback(result, data->user_data);
661 g_free(data->peer_address);
666 static int mesh_change_peer_status(const char *peer_address,
667 enum connman_mesh_peer_status status,
668 mesh_change_peer_status_cb_t callback, void *user_data)
671 struct wifi_data *wifi;
672 struct wifi_mesh_info *mesh_info;
673 bool mesh_if_found = false;
674 GSupplicantInterface *interface;
675 struct mesh_change_peer_status_info *data;
678 for (list = iface_list; list; list = list->next) {
681 if (wifi->mesh_interface) {
682 mesh_if_found = true;
687 if (!mesh_if_found) {
688 DBG("Mesh interface is not created");
692 mesh_info = wifi->mesh_info;
694 interface = mesh_info->interface;
697 case CONNMAN_MESH_PEER_ADD:
698 method = "MeshPeerAdd";
700 case CONNMAN_MESH_PEER_REMOVE:
701 method = "MeshPeerRemove";
704 DBG("Invalid method");
708 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
710 DBG("Memory allocation failed");
714 data->peer_address = g_strdup(peer_address);
715 data->peer_status = status;
716 data->callback = callback;
717 data->user_data = user_data;
719 return g_supplicant_interface_mesh_peer_change_status(interface,
720 mesh_peer_change_status_callback, peer_address, method,
724 static struct connman_mesh_driver mesh_driver = {
725 .add_interface = add_mesh_interface,
726 .remove_interface = remove_mesh_interface,
727 .connect = mesh_peer_connect,
728 .disconnect = mesh_peer_disconnect,
729 .change_peer_status = mesh_change_peer_status,
732 static void mesh_support(GSupplicantInterface *interface)
736 if (!g_supplicant_interface_has_mesh(interface))
739 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
740 DBG("Could not register Mesh technology driver");
744 connman_mesh_driver_register(&mesh_driver);
747 static void check_mesh_technology(void)
749 bool mesh_exists = false;
752 for (list = iface_list; list; list = list->next) {
753 struct wifi_data *w = list->data;
756 g_supplicant_interface_has_mesh(w->interface))
761 connman_technology_driver_unregister(&mesh_tech_driver);
762 connman_mesh_driver_unregister(&mesh_driver);
766 static void mesh_group_started(GSupplicantInterface *interface)
768 struct wifi_data *wifi;
769 struct wifi_mesh_info *mesh_info;
770 struct connman_mesh *mesh;
771 const unsigned char *ssid;
772 unsigned int ssid_len;
775 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
776 memcpy(name, ssid, ssid_len);
777 name[ssid_len] = '\0';
778 DBG("name %s", name);
779 wifi = g_supplicant_interface_get_data(interface);
780 DBG("wifi %p", wifi);
785 mesh_info = wifi->mesh_info;
789 mesh = mesh_info->mesh;
793 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
796 static void mesh_group_removed(GSupplicantInterface *interface)
798 struct wifi_data *wifi;
799 struct wifi_mesh_info *mesh_info;
800 struct connman_mesh *mesh;
801 const unsigned char *ssid;
802 unsigned int ssid_len;
803 int disconnect_reason;
806 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
807 memcpy(name, ssid, ssid_len);
808 name[ssid_len] = '\0';
809 DBG("name %s", name);
811 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
812 DBG("Disconnect Reason %d", disconnect_reason);
814 wifi = g_supplicant_interface_get_data(interface);
815 DBG("wifi %p", wifi);
820 mesh_info = wifi->mesh_info;
824 mesh = connman_get_connected_mesh_from_name(name);
826 DBG("%s is not connected", name);
827 mesh = connman_get_connecting_mesh_from_name(name);
829 DBG("%s is not connecting", name);
834 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
835 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
838 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
840 const char *peer_address;
842 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
847 DBG("Peer %s connected", peer_address);
848 connman_mesh_add_connected_peer(peer_address);
851 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
853 const char *peer_address;
856 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
861 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
863 DBG("Peer %s disconnected with reason %d", peer_address, reason);
864 connman_mesh_remove_connected_peer(peer_address, reason);
868 static struct wifi_data *get_pending_wifi_data(const char *ifname)
872 for (list = pending_wifi_device; list; list = list->next) {
873 struct wifi_data *wifi;
874 const char *dev_name;
877 if (!wifi || !wifi->device)
880 dev_name = connman_device_get_string(wifi->device, "Interface");
881 if (!g_strcmp0(ifname, dev_name)) {
882 pending_wifi_device = g_list_delete_link(
883 pending_wifi_device, list);
891 static void remove_pending_wifi_device(struct wifi_data *wifi)
895 link = g_list_find(pending_wifi_device, wifi);
900 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
903 static void peer_cancel_timeout(struct wifi_data *wifi)
905 if (wifi->p2p_connection_timeout > 0)
906 g_source_remove(wifi->p2p_connection_timeout);
908 wifi->p2p_connection_timeout = 0;
909 wifi->p2p_connecting = false;
911 if (wifi->pending_peer) {
912 connman_peer_unref(wifi->pending_peer);
913 wifi->pending_peer = NULL;
917 static gboolean peer_connect_timeout(gpointer data)
919 struct wifi_data *wifi = data;
923 if (wifi->p2p_connecting) {
924 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
925 GSupplicantPeer *gs_peer =
926 g_supplicant_interface_peer_lookup(wifi->interface,
927 connman_peer_get_identifier(wifi->pending_peer));
929 if (g_supplicant_peer_has_requested_connection(gs_peer))
930 state = CONNMAN_PEER_STATE_IDLE;
932 connman_peer_set_state(wifi->pending_peer, state);
935 peer_cancel_timeout(wifi);
940 static void peer_connect_callback(int result, GSupplicantInterface *interface,
943 struct wifi_data *wifi = user_data;
944 struct connman_peer *peer = wifi->pending_peer;
946 DBG("peer %p - %d", peer, result);
952 peer_connect_timeout(wifi);
956 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
958 wifi->p2p_connection_timeout = g_timeout_add_seconds(
959 P2P_CONNECTION_TIMEOUT,
960 peer_connect_timeout, wifi);
963 static int peer_connect(struct connman_peer *peer,
964 enum connman_peer_wps_method wps_method,
967 struct connman_device *device = connman_peer_get_device(peer);
968 GSupplicantPeerParams *peer_params;
969 GSupplicantPeer *gs_peer;
970 struct wifi_data *wifi;
974 DBG("peer %p", peer);
979 wifi = connman_device_get_data(device);
980 if (!wifi || !wifi->interface)
983 if (wifi->p2p_connecting)
986 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
987 connman_peer_get_identifier(peer));
991 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
992 pin = g_supplicant_peer_is_wps_pin(gs_peer);
994 switch (wps_method) {
995 case CONNMAN_PEER_WPS_UNKNOWN:
996 if ((pbc && pin) || pin)
999 case CONNMAN_PEER_WPS_PBC:
1004 case CONNMAN_PEER_WPS_PIN:
1005 if (!pin || !wps_pin)
1010 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1014 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1016 peer_params->wps_pin = g_strdup(wps_pin);
1018 peer_params->master = connman_peer_service_is_master();
1020 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1021 peer_connect_callback, wifi);
1022 if (ret == -EINPROGRESS) {
1023 wifi->pending_peer = connman_peer_ref(peer);
1024 wifi->p2p_connecting = true;
1025 } else if (ret < 0) {
1026 g_free(peer_params->path);
1027 g_free(peer_params->wps_pin);
1028 g_free(peer_params);
1034 static int peer_disconnect(struct connman_peer *peer)
1036 struct connman_device *device = connman_peer_get_device(peer);
1037 GSupplicantPeerParams peer_params = {};
1038 GSupplicantPeer *gs_peer;
1039 struct wifi_data *wifi;
1042 DBG("peer %p", peer);
1047 wifi = connman_device_get_data(device);
1051 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1052 connman_peer_get_identifier(peer));
1056 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1058 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1060 g_free(peer_params.path);
1062 if (ret == -EINPROGRESS) {
1063 peer_cancel_timeout(wifi);
1064 wifi->p2p_device = false;
1070 struct peer_service_registration {
1071 peer_service_registration_cb_t callback;
1075 static bool is_service_wfd(const unsigned char *specs, int length)
1077 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1083 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1085 struct wifi_data *wifi = data;
1087 if (!wifi->interface ||
1088 !g_supplicant_interface_has_p2p(wifi->interface))
1091 if (!wifi->servicing) {
1092 g_supplicant_interface_p2p_listen(wifi->interface,
1093 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1099 static void register_wfd_service_cb(int result,
1100 GSupplicantInterface *iface, void *user_data)
1102 struct peer_service_registration *reg_data = user_data;
1107 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1109 if (reg_data && reg_data->callback) {
1110 reg_data->callback(result, reg_data->user_data);
1115 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1116 const unsigned char *spec,
1117 int spec_length, const unsigned char *query,
1118 int query_length, int version)
1120 GSupplicantP2PServiceParams *params;
1122 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1127 params->version = version;
1128 params->service = g_memdup(spec, spec_length);
1129 } else if (query_length > 0 && spec_length > 0) {
1130 params->query = g_memdup(query, query_length);
1131 params->query_length = query_length;
1133 params->response = g_memdup(spec, spec_length);
1134 params->response_length = spec_length;
1136 params->wfd_ies = g_memdup(spec, spec_length);
1137 params->wfd_ies_length = spec_length;
1143 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1148 g_free(params->service);
1149 g_free(params->query);
1150 g_free(params->response);
1151 g_free(params->wfd_ies);
1156 static int peer_register_wfd_service(const unsigned char *specification,
1157 int specification_length,
1158 peer_service_registration_cb_t callback,
1161 struct peer_service_registration *reg_data = NULL;
1162 static GSupplicantP2PServiceParams *params;
1167 if (wfd_service_registered)
1170 params = fill_in_peer_service_params(specification,
1171 specification_length, NULL, 0, 0);
1175 reg_data = g_try_malloc0(sizeof(*reg_data));
1181 reg_data->callback = callback;
1182 reg_data->user_data = user_data;
1184 ret = g_supplicant_set_widi_ies(params,
1185 register_wfd_service_cb, reg_data);
1186 if (ret < 0 && ret != -EINPROGRESS)
1189 wfd_service_registered = true;
1193 free_peer_service_params(params);
1199 static void register_peer_service_cb(int result,
1200 GSupplicantInterface *iface, void *user_data)
1202 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1203 struct peer_service_registration *reg_data = user_data;
1205 #if defined TIZEN_EXT
1213 apply_p2p_listen_on_iface(wifi, NULL);
1215 if (reg_data->callback)
1216 reg_data->callback(result, reg_data->user_data);
1221 static int peer_register_service(const unsigned char *specification,
1222 int specification_length,
1223 const unsigned char *query,
1224 int query_length, int version,
1225 peer_service_registration_cb_t callback,
1228 struct peer_service_registration *reg_data;
1229 GSupplicantP2PServiceParams *params;
1236 if (specification && !version && !query &&
1237 is_service_wfd(specification, specification_length)) {
1238 return peer_register_wfd_service(specification,
1239 specification_length, callback, user_data);
1242 reg_data = g_try_malloc0(sizeof(*reg_data));
1246 reg_data->callback = callback;
1247 reg_data->user_data = user_data;
1249 ret_f = -EOPNOTSUPP;
1251 for (list = iface_list; list; list = list->next) {
1252 struct wifi_data *wifi = list->data;
1253 GSupplicantInterface *iface = wifi->interface;
1255 if (!g_supplicant_interface_has_p2p(iface))
1258 params = fill_in_peer_service_params(specification,
1259 specification_length, query,
1260 query_length, version);
1265 ret_f = g_supplicant_interface_p2p_add_service(iface,
1266 register_peer_service_cb, params, reg_data);
1267 if (ret_f == 0 || ret_f == -EINPROGRESS)
1271 ret = g_supplicant_interface_p2p_add_service(iface,
1272 register_peer_service_cb, params, NULL);
1273 if (ret != 0 && ret != -EINPROGRESS)
1274 free_peer_service_params(params);
1277 if (ret_f != 0 && ret_f != -EINPROGRESS)
1283 static int peer_unregister_wfd_service(void)
1285 GSupplicantP2PServiceParams *params;
1288 if (!wfd_service_registered)
1291 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1295 wfd_service_registered = false;
1297 g_supplicant_set_widi_ies(params, NULL, NULL);
1299 for (list = iface_list; list; list = list->next) {
1300 struct wifi_data *wifi = list->data;
1302 if (!g_supplicant_interface_has_p2p(wifi->interface))
1306 if (!wifi->servicing || wifi->servicing < 0) {
1307 g_supplicant_interface_p2p_listen(wifi->interface,
1309 wifi->servicing = 0;
1316 static int peer_unregister_service(const unsigned char *specification,
1317 int specification_length,
1318 const unsigned char *query,
1319 int query_length, int version)
1321 GSupplicantP2PServiceParams *params;
1326 if (specification && !version && !query &&
1327 is_service_wfd(specification, specification_length)) {
1328 ret = peer_unregister_wfd_service();
1329 if (ret != 0 && ret != -EINPROGRESS)
1334 for (list = iface_list; list; list = list->next) {
1335 struct wifi_data *wifi = list->data;
1336 GSupplicantInterface *iface = wifi->interface;
1339 goto stop_listening;
1341 if (!g_supplicant_interface_has_p2p(iface))
1344 params = fill_in_peer_service_params(specification,
1345 specification_length, query,
1346 query_length, version);
1350 ret = g_supplicant_interface_p2p_del_service(iface, params);
1351 if (ret != 0 && ret != -EINPROGRESS)
1352 free_peer_service_params(params);
1355 if (!wifi->servicing || wifi->servicing < 0) {
1356 g_supplicant_interface_p2p_listen(iface, 0, 0);
1357 wifi->servicing = 0;
1364 static struct connman_peer_driver peer_driver = {
1365 .connect = peer_connect,
1366 .disconnect = peer_disconnect,
1367 .register_service = peer_register_service,
1368 .unregister_service = peer_unregister_service,
1371 static void handle_tethering(struct wifi_data *wifi)
1373 if (!wifi->tethering)
1382 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1384 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1387 wifi->bridged = true;
1390 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1392 struct connman_device *device = user_data;
1393 struct wifi_data *wifi = connman_device_get_data(device);
1398 DBG("index %d flags %d change %d", wifi->index, flags, change);
1400 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1402 DBG("interface up");
1404 DBG("interface down");
1407 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1408 if (flags & IFF_LOWER_UP) {
1411 handle_tethering(wifi);
1416 wifi->flags = flags;
1419 static int wifi_probe(struct connman_device *device)
1421 struct wifi_data *wifi;
1423 DBG("device %p", device);
1425 wifi = g_try_new0(struct wifi_data, 1);
1429 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1430 wifi->ap_supported = WIFI_AP_UNKNOWN;
1431 wifi->tethering_param = NULL;
1433 connman_device_set_data(device, wifi);
1434 wifi->device = connman_device_ref(device);
1436 wifi->index = connman_device_get_index(device);
1439 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1440 wifi_newlink, device);
1441 if (is_p2p_connecting())
1442 add_pending_wifi_device(wifi);
1444 iface_list = g_list_append(iface_list, wifi);
1449 static void remove_networks(struct connman_device *device,
1450 struct wifi_data *wifi)
1454 for (list = wifi->networks; list; list = list->next) {
1455 struct connman_network *network = list->data;
1457 connman_device_remove_network(device, network);
1458 connman_network_unref(network);
1461 g_slist_free(wifi->networks);
1462 wifi->networks = NULL;
1465 static void remove_peers(struct wifi_data *wifi)
1469 for (list = wifi->peers; list; list = list->next) {
1470 struct connman_peer *peer = list->data;
1472 connman_peer_unregister(peer);
1473 connman_peer_unref(peer);
1476 g_slist_free(wifi->peers);
1480 static void reset_autoscan(struct connman_device *device)
1482 struct wifi_data *wifi = connman_device_get_data(device);
1483 struct autoscan_params *autoscan;
1487 if (!wifi || !wifi->autoscan)
1490 autoscan = wifi->autoscan;
1492 autoscan->interval = 0;
1494 if (autoscan->timeout == 0)
1497 g_source_remove(autoscan->timeout);
1498 autoscan->timeout = 0;
1500 connman_device_unref(device);
1503 static void stop_autoscan(struct connman_device *device)
1505 const struct wifi_data *wifi = connman_device_get_data(device);
1507 if (!wifi || !wifi->autoscan)
1510 reset_autoscan(device);
1512 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1515 static void check_p2p_technology(void)
1517 bool p2p_exists = false;
1520 for (list = iface_list; list; list = list->next) {
1521 struct wifi_data *w = list->data;
1524 g_supplicant_interface_has_p2p(w->interface))
1529 connman_technology_driver_unregister(&p2p_tech_driver);
1530 connman_peer_driver_unregister(&peer_driver);
1534 struct last_connected {
1540 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1542 GTimeVal *aval = (GTimeVal *)a;
1543 GTimeVal *bval = (GTimeVal *)b;
1545 /* Note that the sort order is descending */
1546 if (aval->tv_sec < bval->tv_sec)
1549 if (aval->tv_sec > bval->tv_sec)
1555 static void free_entry(gpointer data)
1557 struct last_connected *entry = data;
1559 g_free(entry->ssid);
1563 static void wifi_remove(struct connman_device *device)
1565 struct wifi_data *wifi = connman_device_get_data(device);
1567 DBG("device %p wifi %p", device, wifi);
1572 stop_autoscan(device);
1574 if (wifi->p2p_device)
1575 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1577 iface_list = g_list_remove(iface_list, wifi);
1579 check_p2p_technology();
1580 #if defined TIZEN_EXT_WIFI_MESH
1581 check_mesh_technology();
1584 remove_pending_wifi_device(wifi);
1586 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
1587 g_source_remove(wifi->p2p_find_timeout);
1588 connman_device_unref(wifi->device);
1591 if (wifi->p2p_connection_timeout)
1592 g_source_remove(wifi->p2p_connection_timeout);
1594 #if defined TIZEN_EXT
1595 if (wifi->automaxspeed_timeout != 0) {
1596 g_source_remove(wifi->automaxspeed_timeout);
1597 wifi->automaxspeed_timeout = 0;
1601 remove_networks(device, wifi);
1604 connman_device_set_powered(device, false);
1605 connman_device_set_data(device, NULL);
1606 connman_device_unref(wifi->device);
1607 connman_rtnl_remove_watch(wifi->watch);
1609 g_supplicant_interface_set_data(wifi->interface, NULL);
1611 g_supplicant_interface_cancel(wifi->interface);
1613 if (wifi->scan_params)
1614 g_supplicant_free_scan_params(wifi->scan_params);
1615 #if defined TIZEN_EXT
1616 if (wifi->hidden_scan_params) {
1617 while (wifi->hidden_scan_params->ssids) {
1618 struct scan_ssid *ssid;
1619 ssid = wifi->hidden_scan_params->ssids->data;
1620 wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
1622 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1626 g_free(wifi->autoscan);
1627 g_free(wifi->identifier);
1631 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1635 for (iter = list; iter; iter = g_slist_next(iter)) {
1636 struct scan_ssid *scan_ssid = iter->data;
1638 if (ssid_len == scan_ssid->ssid_len &&
1639 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1646 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1647 int freq, GSupplicantScanParams *scan_data,
1648 int driver_max_scan_ssids, char *ssid_name)
1651 struct scan_ssid *scan_ssid;
1653 if ((driver_max_scan_ssids == 0 ||
1654 driver_max_scan_ssids > scan_data->num_ssids) &&
1655 (hex_ssid || raw_ssid)) {
1657 unsigned int j = 0, hex;
1660 size_t hex_ssid_len = strlen(hex_ssid);
1662 ssid = g_try_malloc0(hex_ssid_len / 2);
1666 for (i = 0; i < hex_ssid_len; i += 2) {
1667 sscanf(hex_ssid + i, "%02x", &hex);
1676 * If we have already added hidden AP to the list,
1677 * then do not do it again. This might happen if you have
1678 * used or are using multiple wifi cards, so in that case
1679 * you might have multiple service files for same AP.
1681 if (is_duplicate(scan_data->ssids, ssid, j)) {
1687 scan_ssid = g_try_new(struct scan_ssid, 1);
1694 memcpy(scan_ssid->ssid, ssid, j);
1695 scan_ssid->ssid_len = j;
1696 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1699 scan_data->num_ssids++;
1701 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1702 scan_data->num_ssids);
1709 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1711 if (!scan_data->freqs) {
1712 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1713 if (!scan_data->freqs) {
1714 g_slist_free_full(scan_data->ssids, g_free);
1718 scan_data->num_freqs = 1;
1719 scan_data->freqs[0] = freq;
1721 bool duplicate = false;
1723 /* Don't add duplicate entries */
1724 for (i = 0; i < scan_data->num_freqs; i++) {
1725 if (scan_data->freqs[i] == freq) {
1732 scan_data->num_freqs++;
1733 scan_data->freqs = g_try_realloc(scan_data->freqs,
1734 sizeof(uint16_t) * scan_data->num_freqs);
1735 if (!scan_data->freqs) {
1736 g_slist_free_full(scan_data->ssids, g_free);
1739 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1746 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1748 struct connman_config_entry **entries;
1750 #if defined TIZEN_EXT
1751 gchar **services = NULL;
1754 #endif /* defined TIZEN_EXT */
1758 int num_ssids = 0, add_param_failed = 0;
1759 #if defined TIZEN_EXT
1760 GSequenceIter *iter;
1761 GSequence *latest_list;
1762 struct last_connected *entry;
1765 latest_list = g_sequence_new(free_entry);
1769 services = connman_storage_get_services();
1770 for (i = 0; services && services[i]; i++) {
1771 if (strncmp(services[i], "wifi_", 5) != 0)
1774 keyfile = connman_storage_load_service(services[i]);
1778 value = g_key_file_get_boolean(keyfile,
1779 services[i], "Hidden", NULL);
1781 g_key_file_free(keyfile);
1785 value = g_key_file_get_boolean(keyfile,
1786 services[i], "Favorite", NULL);
1788 g_key_file_free(keyfile);
1792 #if defined TIZEN_EXT
1793 value = g_key_file_get_boolean(keyfile,
1794 services[i], "AutoConnect", NULL);
1796 g_key_file_free(keyfile);
1800 gchar *str = g_key_file_get_string(keyfile,
1801 services[i], "Modified", NULL);
1803 g_key_file_free(keyfile);
1806 g_time_val_from_iso8601(str, &modified);
1810 ssid = g_key_file_get_string(keyfile,
1811 services[i], "SSID", NULL);
1813 name = g_key_file_get_string(keyfile, services[i], "Name",
1816 #if defined TIZEN_EXT
1817 entry = g_try_new(struct last_connected, 1);
1819 g_sequence_free(latest_list);
1822 g_key_file_free(keyfile);
1826 entry->modified = modified;
1829 g_sequence_insert_sorted(latest_list, entry,
1832 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1841 g_key_file_free(keyfile);
1844 #if defined TIZEN_EXT
1845 gint length = g_sequence_get_length(latest_list);
1846 iter = g_sequence_get_begin_iter(latest_list);
1848 for (i = 0; i < length; i++) {
1849 entry = g_sequence_get(iter);
1851 ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid);
1857 iter = g_sequence_iter_next(iter);
1860 g_sequence_free(latest_list);
1864 * Check if there are any hidden AP that needs to be provisioned.
1866 entries = connman_config_get_entries("wifi");
1867 for (i = 0; entries && entries[i]; i++) {
1870 if (!entries[i]->hidden)
1873 if (!entries[i]->ssid) {
1874 ssid = entries[i]->name;
1877 ssid = entries[i]->ssid;
1878 len = entries[i]->ssid_len;
1884 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1891 connman_config_free_entries(entries);
1893 if (add_param_failed > 0)
1894 DBG("Unable to scan %d out of %d SSIDs",
1895 add_param_failed, num_ssids);
1897 g_strfreev(services);
1902 static int get_hidden_connections_params(struct wifi_data *wifi,
1903 GSupplicantScanParams *scan_params)
1905 int driver_max_ssids, i;
1906 GSupplicantScanParams *orig_params;
1909 * Scan hidden networks so that we can autoconnect to them.
1910 * We will assume 1 as a default number of ssid to scan.
1912 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1914 if (driver_max_ssids == 0)
1915 driver_max_ssids = 1;
1917 DBG("max ssids %d", driver_max_ssids);
1919 #if defined TIZEN_EXT
1920 if (!wifi->hidden_scan_params) {
1921 wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1922 if (!wifi->hidden_scan_params)
1925 if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
1926 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1927 wifi->hidden_scan_params = NULL;
1933 orig_params = wifi->hidden_scan_params;
1935 if (!wifi->scan_params) {
1936 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1937 if (!wifi->scan_params)
1940 if (get_hidden_connections(wifi->scan_params) == 0) {
1941 g_supplicant_free_scan_params(wifi->scan_params);
1942 wifi->scan_params = NULL;
1948 orig_params = wifi->scan_params;
1951 /* Let's transfer driver_max_ssids params */
1952 for (i = 0; i < driver_max_ssids; i++) {
1953 struct scan_ssid *ssid;
1955 #if defined TIZEN_EXT
1956 if (!wifi->hidden_scan_params->ssids)
1958 if (!wifi->scan_params->ssids)
1962 ssid = orig_params->ssids->data;
1963 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1964 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1968 scan_params->num_ssids = i;
1969 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1971 scan_params->freqs = g_memdup(orig_params->freqs,
1972 sizeof(uint16_t) * orig_params->num_freqs);
1973 if (!scan_params->freqs)
1976 scan_params->num_freqs = orig_params->num_freqs;
1981 orig_params->num_ssids -= scan_params->num_ssids;
1983 return scan_params->num_ssids;
1986 g_slist_free_full(scan_params->ssids, g_free);
1987 #if defined TIZEN_EXT
1988 g_supplicant_free_scan_params(wifi->hidden_scan_params);
1989 wifi->hidden_scan_params = NULL;
1991 g_supplicant_free_scan_params(wifi->scan_params);
1992 wifi->scan_params = NULL;
1998 static int throw_wifi_scan(struct connman_device *device,
1999 GSupplicantInterfaceCallback callback)
2001 struct wifi_data *wifi = connman_device_get_data(device);
2007 DBG("device %p %p", device, wifi->interface);
2009 if (wifi->tethering)
2012 #if defined TIZEN_EXT
2013 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)
2014 && !wifi->allow_full_scan)
2016 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
2020 connman_device_ref(device);
2022 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2025 connman_device_set_scanning(device,
2026 CONNMAN_SERVICE_TYPE_WIFI, true);
2028 connman_device_unref(device);
2033 static void hidden_free(struct hidden_params *hidden)
2038 if (hidden->scan_params)
2039 g_supplicant_free_scan_params(hidden->scan_params);
2040 g_free(hidden->identity);
2041 g_free(hidden->passphrase);
2042 g_free(hidden->security);
2046 #if defined TIZEN_EXT
2047 static void service_state_changed(struct connman_service *service,
2048 enum connman_service_state state);
2050 static int network_connect(struct connman_network *network);
2052 static struct connman_notifier notifier = {
2054 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
2055 .service_state_changed = service_state_changed,
2058 static void service_state_changed(struct connman_service *service,
2059 enum connman_service_state state)
2061 enum connman_service_type type;
2063 type = connman_service_get_type(service);
2064 if (type != CONNMAN_SERVICE_TYPE_WIFI)
2067 DBG("service %p state %d", service, state);
2070 case CONNMAN_SERVICE_STATE_READY:
2071 case CONNMAN_SERVICE_STATE_ONLINE:
2072 case CONNMAN_SERVICE_STATE_FAILURE:
2073 connman_notifier_unregister(¬ifier);
2074 is_wifi_notifier_registered = FALSE;
2076 __connman_device_request_scan(type);
2084 static void scan_callback_hidden(int result,
2085 GSupplicantInterface *interface, void *user_data);
2088 static void scan_callback(int result, GSupplicantInterface *interface,
2091 struct connman_device *device = user_data;
2092 struct wifi_data *wifi = connman_device_get_data(device);
2094 #if defined TIZEN_EXT
2095 GSList *list = NULL;
2096 bool favorite_exists = false;
2097 struct connman_network *network = NULL;
2098 struct connman_service *service = NULL;
2101 DBG("result %d wifi %p", result, wifi);
2104 if (wifi->hidden && !wifi->postpone_hidden) {
2105 connman_network_clear_hidden(wifi->hidden->user_data);
2106 hidden_free(wifi->hidden);
2107 wifi->hidden = NULL;
2110 if (wifi->scan_params) {
2111 g_supplicant_free_scan_params(wifi->scan_params);
2112 wifi->scan_params = NULL;
2115 #if defined TIZEN_EXT
2116 if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
2117 g_supplicant_free_scan_params(wifi->hidden_scan_params);
2118 wifi->hidden_scan_params = NULL;
2124 connman_device_reset_scanning(device);
2126 /* User is connecting to a hidden AP, let's wait for finished event */
2127 if (wifi && wifi->hidden && wifi->postpone_hidden) {
2128 GSupplicantScanParams *scan_params;
2131 wifi->postpone_hidden = false;
2132 scan_params = wifi->hidden->scan_params;
2133 wifi->hidden->scan_params = NULL;
2135 reset_autoscan(device);
2137 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2138 scan_callback, device);
2142 /* On error, let's recall scan_callback, which will cleanup */
2143 return scan_callback(ret, interface, user_data);
2146 #if defined TIZEN_EXT
2148 for (list = wifi->networks; list; list = list->next) {
2149 network = list->data;
2150 service = connman_service_lookup_from_network(network);
2152 if (service != NULL &&
2153 (connman_service_get_favorite(service) == true) &&
2154 (connman_service_get_autoconnect(service) == true)) {
2155 DBG("Favorite service exists [%s]", connman_network_get_string(network, "Name"));
2156 favorite_exists = true;
2162 if (favorite_exists == false) {
2163 if (wifi && wifi->allow_full_scan) {
2165 DBG("Trigger full channel scan");
2166 wifi->allow_full_scan = false;
2168 ret = g_supplicant_interface_scan(wifi->interface, NULL,
2169 scan_callback_hidden, device);
2173 /* On error, let's recall scan_callback, which will cleanup */
2174 return scan_callback(ret, interface, user_data);
2179 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
2182 connman_device_set_scanning(device,
2183 CONNMAN_SERVICE_TYPE_WIFI, false);
2186 if (result != -ENOLINK)
2187 #if defined TIZEN_EXT
2190 start_autoscan(device);
2193 * If we are here then we were scanning; however, if we are
2194 * also mid-flight disabling the interface, then wifi_disable
2195 * has already cleared the device scanning state and
2196 * unreferenced the device, obviating the need to do it here.
2200 connman_device_unref(device);
2202 #if defined TIZEN_EXT
2203 if (wifi && wifi->scan_pending_network && result != -EIO) {
2204 network_connect(wifi->scan_pending_network);
2205 wifi->scan_pending_network = NULL;
2206 connman_network_set_connecting(wifi->network);
2209 if (is_wifi_notifier_registered != true &&
2210 wifi_first_scan == true && found_with_first_scan == true) {
2211 wifi_first_scan = false;
2212 found_with_first_scan = false;
2214 connman_notifier_register(¬ifier);
2215 is_wifi_notifier_registered = true;
2220 static void scan_callback_hidden(int result,
2221 GSupplicantInterface *interface, void *user_data)
2223 struct connman_device *device = user_data;
2224 struct wifi_data *wifi = connman_device_get_data(device);
2225 GSupplicantScanParams *scan_params;
2228 DBG("result %d wifi %p", result, wifi);
2233 /* User is trying to connect to a hidden AP */
2234 if (wifi->hidden && wifi->postpone_hidden)
2237 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2241 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2242 ret = g_supplicant_interface_scan(wifi->interface,
2244 #if defined TIZEN_EXT
2247 scan_callback_hidden,
2254 g_supplicant_free_scan_params(scan_params);
2257 scan_callback(result, interface, user_data);
2260 static gboolean autoscan_timeout(gpointer data)
2262 struct connman_device *device = data;
2263 struct wifi_data *wifi = connman_device_get_data(device);
2264 struct autoscan_params *autoscan;
2270 autoscan = wifi->autoscan;
2272 if (autoscan->interval <= 0) {
2273 interval = autoscan->base;
2276 interval = autoscan->interval * autoscan->base;
2278 #if defined TIZEN_EXT
2279 if (autoscan->interval >= autoscan->limit)
2281 if (interval > autoscan->limit)
2283 interval = autoscan->limit;
2285 throw_wifi_scan(wifi->device, scan_callback_hidden);
2288 * In case BackgroundScanning is disabled, interval will reach the
2289 * limit exactly after the very first passive scanning. It allows
2290 * to ensure at most one passive scan is performed in such cases.
2292 if (!connman_setting_get_bool("BackgroundScanning") &&
2293 interval == autoscan->limit) {
2294 g_source_remove(autoscan->timeout);
2295 autoscan->timeout = 0;
2297 connman_device_unref(device);
2303 DBG("interval %d", interval);
2305 autoscan->interval = interval;
2307 autoscan->timeout = g_timeout_add_seconds(interval,
2308 autoscan_timeout, device);
2313 static void start_autoscan(struct connman_device *device)
2315 struct wifi_data *wifi = connman_device_get_data(device);
2316 struct autoscan_params *autoscan;
2323 if (wifi->p2p_device)
2326 if (wifi->connected)
2329 autoscan = wifi->autoscan;
2333 if (autoscan->timeout > 0 || autoscan->interval > 0)
2336 connman_device_ref(device);
2338 autoscan_timeout(device);
2341 static struct autoscan_params *parse_autoscan_params(const char *params)
2343 struct autoscan_params *autoscan;
2350 list_params = g_strsplit(params, ":", 0);
2351 if (list_params == 0)
2354 if (!g_strcmp0(list_params[0], "exponential") &&
2355 g_strv_length(list_params) == 3) {
2356 base = atoi(list_params[1]);
2357 limit = atoi(list_params[2]);
2358 } else if (!g_strcmp0(list_params[0], "single") &&
2359 g_strv_length(list_params) == 2)
2360 base = limit = atoi(list_params[1]);
2362 g_strfreev(list_params);
2366 DBG("Setup %s autoscanning", list_params[0]);
2368 g_strfreev(list_params);
2370 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2372 DBG("Could not allocate memory for autoscan");
2376 DBG("base %d - limit %d", base, limit);
2377 autoscan->base = base;
2378 autoscan->limit = limit;
2383 static void setup_autoscan(struct wifi_data *wifi)
2386 * If BackgroundScanning is enabled, setup exponential
2387 * autoscanning if it has not been previously done.
2389 if (connman_setting_get_bool("BackgroundScanning")) {
2390 wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
2395 * On the contrary, if BackgroundScanning is disabled, update autoscan
2396 * parameters based on the type of scanning that is being performed.
2398 if (wifi->autoscan) {
2399 g_free(wifi->autoscan);
2400 wifi->autoscan = NULL;
2403 switch (wifi->scanning_type) {
2404 case WIFI_SCANNING_PASSIVE:
2405 /* Do not setup autoscan. */
2407 case WIFI_SCANNING_ACTIVE:
2408 /* Setup one single passive scan after active. */
2409 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2411 case WIFI_SCANNING_UNKNOWN:
2412 /* Setup autoscan in this case but we should never fall here. */
2413 wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
2418 static void finalize_interface_creation(struct wifi_data *wifi)
2420 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2422 if (!wifi->device) {
2423 connman_error("WiFi device not set");
2427 connman_device_set_powered(wifi->device, true);
2429 if (wifi->p2p_device)
2432 if (!wifi->autoscan)
2433 setup_autoscan(wifi);
2435 start_autoscan(wifi->device);
2438 static void interface_create_callback(int result,
2439 GSupplicantInterface *interface,
2442 struct wifi_data *wifi = user_data;
2444 DBG("result %d ifname %s, wifi %p", result,
2445 g_supplicant_interface_get_ifname(interface),
2448 if (result < 0 || !wifi)
2451 wifi->interface = interface;
2452 g_supplicant_interface_set_data(interface, wifi);
2454 if (g_supplicant_interface_get_ready(interface)) {
2455 wifi->interface_ready = true;
2456 finalize_interface_creation(wifi);
2460 static int wifi_enable(struct connman_device *device)
2462 struct wifi_data *wifi = connman_device_get_data(device);
2465 const char *driver = connman_option_get_string("wifi");
2468 DBG("device %p %p", device, wifi);
2470 index = connman_device_get_index(device);
2471 if (!wifi || index < 0)
2474 if (is_p2p_connecting())
2475 return -EINPROGRESS;
2477 interface = connman_inet_ifname(index);
2478 ret = g_supplicant_interface_create(interface, driver, NULL,
2479 interface_create_callback,
2486 return -EINPROGRESS;
2489 static int wifi_disable(struct connman_device *device)
2491 struct wifi_data *wifi = connman_device_get_data(device);
2494 DBG("device %p wifi %p", device, wifi);
2499 wifi->connected = false;
2500 wifi->disconnecting = false;
2502 if (wifi->pending_network)
2503 wifi->pending_network = NULL;
2505 #if !defined TIZEN_EXT
2506 stop_autoscan(device);
2509 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
2510 g_source_remove(wifi->p2p_find_timeout);
2511 wifi->p2p_find_timeout = 0;
2512 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2513 connman_device_unref(wifi->device);
2516 #if defined TIZEN_EXT
2517 if (wifi->automaxspeed_timeout != 0) {
2518 g_source_remove(wifi->automaxspeed_timeout);
2519 wifi->automaxspeed_timeout = 0;
2523 /* In case of a user scan, device is still referenced */
2524 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) {
2525 connman_device_set_scanning(device,
2526 CONNMAN_SERVICE_TYPE_WIFI, false);
2527 connman_device_unref(wifi->device);
2530 #if defined TIZEN_EXT
2531 stop_autoscan(device);
2534 remove_networks(device, wifi);
2537 #if defined TIZEN_EXT
2538 wifi->scan_pending_network = NULL;
2540 if (is_wifi_notifier_registered == true) {
2541 connman_notifier_unregister(¬ifier);
2542 is_wifi_notifier_registered = false;
2546 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2550 return -EINPROGRESS;
2553 static int get_latest_connections(int max_ssids,
2554 GSupplicantScanParams *scan_data)
2556 GSequenceIter *iter;
2557 GSequence *latest_list;
2558 struct last_connected *entry;
2567 latest_list = g_sequence_new(free_entry);
2571 services = connman_storage_get_services();
2572 for (i = 0; services && services[i]; i++) {
2573 if (strncmp(services[i], "wifi_", 5) != 0)
2576 keyfile = connman_storage_load_service(services[i]);
2580 str = g_key_file_get_string(keyfile,
2581 services[i], "Favorite", NULL);
2582 if (!str || g_strcmp0(str, "true")) {
2584 g_key_file_free(keyfile);
2589 str = g_key_file_get_string(keyfile,
2590 services[i], "AutoConnect", NULL);
2591 if (!str || g_strcmp0(str, "true")) {
2593 g_key_file_free(keyfile);
2598 str = g_key_file_get_string(keyfile,
2599 services[i], "Modified", NULL);
2601 g_key_file_free(keyfile);
2604 g_time_val_from_iso8601(str, &modified);
2607 ssid = g_key_file_get_string(keyfile,
2608 services[i], "SSID", NULL);
2610 freq = g_key_file_get_integer(keyfile, services[i],
2613 entry = g_try_new(struct last_connected, 1);
2615 g_sequence_free(latest_list);
2616 g_key_file_free(keyfile);
2622 entry->modified = modified;
2625 g_sequence_insert_sorted(latest_list, entry,
2631 g_key_file_free(keyfile);
2634 g_strfreev(services);
2636 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2638 iter = g_sequence_get_begin_iter(latest_list);
2640 for (i = 0; i < num_ssids; i++) {
2641 entry = g_sequence_get(iter);
2643 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2644 entry->modified.tv_sec);
2646 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2647 max_ssids, entry->ssid);
2649 iter = g_sequence_iter_next(iter);
2652 g_sequence_free(latest_list);
2656 static void wifi_update_scanner_type(struct wifi_data *wifi,
2657 enum wifi_scanning_type new_type)
2661 if (!wifi || wifi->scanning_type == new_type)
2664 wifi->scanning_type = new_type;
2666 setup_autoscan(wifi);
2669 static int wifi_scan_simple(struct connman_device *device)
2671 struct wifi_data *wifi = connman_device_get_data(device);
2673 reset_autoscan(device);
2675 /* Distinguish between devices performing passive and active scanning */
2677 wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE);
2679 return throw_wifi_scan(device, scan_callback_hidden);
2682 static gboolean p2p_find_stop(gpointer data)
2684 struct connman_device *device = data;
2685 struct wifi_data *wifi = connman_device_get_data(device);
2690 wifi->p2p_find_timeout = 0;
2692 g_supplicant_interface_p2p_stop_find(wifi->interface);
2695 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2697 connman_device_unref(device);
2698 start_autoscan(device);
2703 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2706 struct connman_device *device = user_data;
2707 struct wifi_data *wifi = connman_device_get_data(device);
2709 DBG("result %d wifi %p", result, wifi);
2714 if (wifi->p2p_find_timeout) {
2715 g_source_remove(wifi->p2p_find_timeout);
2716 wifi->p2p_find_timeout = 0;
2722 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2723 p2p_find_stop, device);
2724 if (!wifi->p2p_find_timeout)
2729 p2p_find_stop(device);
2732 static int p2p_find(struct connman_device *device)
2734 struct wifi_data *wifi;
2739 if (!p2p_technology)
2742 wifi = connman_device_get_data(device);
2744 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2747 reset_autoscan(device);
2748 connman_device_ref(device);
2750 ret = g_supplicant_interface_p2p_find(wifi->interface,
2751 p2p_find_callback, device);
2753 connman_device_unref(device);
2754 start_autoscan(device);
2756 connman_device_set_scanning(device,
2757 CONNMAN_SERVICE_TYPE_P2P, true);
2763 #if defined TIZEN_EXT
2764 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2767 struct connman_device *device = user_data;
2768 struct wifi_data *wifi = connman_device_get_data(device);
2771 DBG("result %d wifi %p", result, wifi);
2773 if (wifi && wifi->scan_params) {
2774 g_supplicant_free_scan_params(wifi->scan_params);
2775 wifi->scan_params = NULL;
2778 scanning = connman_device_get_scanning(device,
2779 CONNMAN_SERVICE_TYPE_WIFI);
2781 connman_device_set_scanning(device,
2782 CONNMAN_SERVICE_TYPE_WIFI, false);
2783 connman_device_unref(device);
2787 static int wifi_specific_scan(enum connman_service_type type,
2788 struct connman_device *device, int scan_type,
2789 GSList *specific_scan_list, void *user_data)
2791 GSList *list = NULL;
2793 struct wifi_data *wifi = connman_device_get_data(device);
2794 GSupplicantScanParams *scan_params = NULL;
2795 struct scan_ssid *scan_ssid = NULL;
2804 if (wifi->p2p_device)
2807 if (type == CONNMAN_SERVICE_TYPE_P2P)
2808 return p2p_find(device);
2810 if (wifi->tethering)
2814 connman_device_get_scanning(device,
2815 CONNMAN_SERVICE_TYPE_WIFI);
2819 DBG("scan_type: %d", scan_type);
2820 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2821 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2823 DBG("Failed to allocate memory.");
2827 for (list = specific_scan_list; list; list = list->next) {
2828 ssid = (char *)list->data;
2829 int ssid_len = strlen(ssid);
2831 scan_ssid = g_try_new0(struct scan_ssid, 1);
2833 DBG("Failed to allocate memory.");
2834 g_supplicant_free_scan_params(scan_params);
2838 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2839 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2840 scan_ssid->ssid_len = ssid_len;
2841 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2844 scan_params->num_ssids = count;
2846 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2848 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2850 DBG("Failed to allocate memory.");
2854 guint num_freqs = g_slist_length(specific_scan_list);
2855 DBG("num_freqs: %d", num_freqs);
2857 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2858 if (!scan_params->freqs) {
2859 DBG("Failed to allocate memory.");
2860 g_free(scan_params);
2865 for (list = specific_scan_list; list; list = list->next) {
2866 freq = (int)list->data;
2868 scan_params->freqs[count] = freq;
2869 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2872 scan_params->num_freqs = count;
2874 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2875 int freq_count, ap_count;
2876 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2878 DBG("Failed to allocate memory.");
2882 guint size = g_slist_length(specific_scan_list);
2884 scan_params->freqs = g_try_new0(uint16_t, size/2);
2885 if (!scan_params->freqs) {
2886 DBG("Failed to allocate memory.");
2887 g_free(scan_params);
2891 ap_count = freq_count = 0;
2892 for (list = specific_scan_list; list; list = list->next) {
2893 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2894 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2895 int ssid_len = strlen(ssid);
2897 scan_ssid = g_try_new0(struct scan_ssid, 1);
2899 DBG("Failed to allocate memory.");
2900 g_supplicant_free_scan_params(scan_params);
2904 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2905 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2906 scan_ssid->ssid_len = ssid_len;
2907 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2911 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2912 scan_params->freqs[freq_count] = freq;
2913 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2917 scan_params->num_ssids = ap_count;
2918 scan_params->num_freqs = freq_count;
2920 DBG("Invalid scan");
2924 reset_autoscan(device);
2925 connman_device_ref(device);
2927 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2928 specific_scan_callback, device);
2931 connman_device_set_scanning(device,
2932 CONNMAN_SERVICE_TYPE_WIFI, true);
2934 g_supplicant_free_scan_params(scan_params);
2935 connman_device_unref(device);
2942 #if defined TIZEN_EXT_WIFI_MESH
2943 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2946 struct connman_device *device = user_data;
2947 struct wifi_data *wifi = connman_device_get_data(device);
2950 DBG("result %d wifi %p", result, wifi);
2952 scanning = connman_device_get_scanning(device,
2953 CONNMAN_SERVICE_TYPE_MESH);
2955 connman_device_set_scanning(device,
2956 CONNMAN_SERVICE_TYPE_MESH, false);
2959 connman_device_unref(device);
2962 static int mesh_scan(struct connman_device *device)
2964 struct wifi_data *wifi;
2965 struct wifi_mesh_info *mesh_info;
2970 wifi = connman_device_get_data(device);
2972 if (!wifi->mesh_interface)
2975 mesh_info = wifi->mesh_info;
2976 reset_autoscan(device);
2977 connman_device_ref(device);
2979 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2980 mesh_scan_callback, device);
2982 connman_device_unref(device);
2984 connman_device_set_scanning(device,
2985 CONNMAN_SERVICE_TYPE_MESH, true);
2990 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2993 struct connman_device *device = user_data;
2994 struct wifi_data *wifi = connman_device_get_data(device);
2996 DBG("result %d wifi %p", result, wifi);
2998 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
3001 static int mesh_abort_scan(enum connman_service_type type,
3002 struct connman_device *device)
3004 struct wifi_data *wifi = connman_device_get_data(device);
3005 struct wifi_mesh_info *mesh_info;
3009 if (!wifi || !wifi->mesh_interface)
3012 if (type != CONNMAN_SERVICE_TYPE_MESH)
3015 mesh_info = wifi->mesh_info;
3017 scanning = connman_device_get_scanning(device,
3018 CONNMAN_SERVICE_TYPE_MESH);
3022 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
3023 abort_scan_callback, device);
3028 static int mesh_specific_scan(enum connman_service_type type,
3029 struct connman_device *device, const char *ssid,
3030 unsigned int freq, void *user_data)
3032 struct wifi_data *wifi = connman_device_get_data(device);
3033 GSupplicantScanParams *scan_params = NULL;
3034 struct wifi_mesh_info *mesh_info;
3035 struct scan_ssid *scan_ssid;
3039 if (!wifi || !wifi->mesh_interface)
3042 if (type != CONNMAN_SERVICE_TYPE_MESH)
3045 if (wifi->p2p_device)
3048 mesh_info = wifi->mesh_info;
3050 scanning = connman_device_get_scanning(device,
3051 CONNMAN_SERVICE_TYPE_MESH);
3055 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3059 scan_ssid = g_try_new(struct scan_ssid, 1);
3061 g_free(scan_params);
3065 scan_ssid->ssid_len = strlen(ssid);
3066 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
3067 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
3068 scan_params->num_ssids = 1;
3070 scan_params->freqs = g_try_new(uint16_t, 1);
3071 if (!scan_params->freqs) {
3072 g_slist_free_full(scan_params->ssids, g_free);
3073 g_free(scan_params);
3077 scan_params->freqs[0] = freq;
3078 scan_params->num_freqs = 1;
3080 reset_autoscan(device);
3081 connman_device_ref(device);
3083 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
3084 mesh_scan_callback, device);
3087 connman_device_set_scanning(device,
3088 CONNMAN_SERVICE_TYPE_MESH, true);
3090 g_supplicant_free_scan_params(scan_params);
3091 connman_device_unref(device);
3099 * Note that the hidden scan is only used when connecting to this specific
3100 * hidden AP first time. It is not used when system autoconnects to hidden AP.
3102 static int wifi_scan(struct connman_device *device,
3103 struct connman_device_scan_params *params)
3105 struct wifi_data *wifi = connman_device_get_data(device);
3106 GSupplicantScanParams *scan_params = NULL;
3107 struct scan_ssid *scan_ssid;
3108 struct hidden_params *hidden;
3110 int driver_max_ssids = 0;
3117 if (wifi->p2p_device)
3120 if (wifi->tethering)
3123 if (params->type == CONNMAN_SERVICE_TYPE_P2P)
3124 return p2p_find(device);
3126 #if defined TIZEN_EXT_WIFI_MESH
3127 if (params->type == CONNMAN_SERVICE_TYPE_MESH)
3128 return mesh_scan(device);
3131 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface,
3134 scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
3136 if (!params->ssid || params->ssid_len == 0 || params->ssid_len > 32) {
3140 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
3142 DBG("max ssids %d", driver_max_ssids);
3143 if (driver_max_ssids == 0)
3144 return wifi_scan_simple(device);
3148 if (scanning && wifi->hidden && wifi->postpone_hidden)
3154 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
3159 scan_ssid = g_try_new(struct scan_ssid, 1);
3161 g_free(scan_params);
3165 memcpy(scan_ssid->ssid, params->ssid, params->ssid_len);
3166 scan_ssid->ssid_len = params->ssid_len;
3167 scan_params->ssids = g_slist_prepend(scan_params->ssids,
3169 scan_params->num_ssids = 1;
3171 hidden = g_try_new0(struct hidden_params, 1);
3173 g_supplicant_free_scan_params(scan_params);
3178 hidden_free(wifi->hidden);
3179 wifi->hidden = NULL;
3182 memcpy(hidden->ssid, params->ssid, params->ssid_len);
3183 hidden->ssid_len = params->ssid_len;
3184 hidden->identity = g_strdup(params->identity);
3185 hidden->passphrase = g_strdup(params->passphrase);
3186 hidden->security = g_strdup(params->security);
3187 hidden->user_data = params->user_data;
3188 wifi->hidden = hidden;
3191 /* Let's keep this active scan for later,
3192 * when current scan will be over. */
3193 wifi->postpone_hidden = TRUE;
3194 hidden->scan_params = scan_params;
3198 } else if (wifi->connected) {
3199 g_supplicant_free_scan_params(scan_params);
3200 return wifi_scan_simple(device);
3201 } else if (!params->force_full_scan) {
3202 ret = get_latest_connections(driver_max_ssids, scan_params);
3204 g_supplicant_free_scan_params(scan_params);
3205 return wifi_scan_simple(device);
3209 /* Distinguish between devices performing passive and active scanning */
3210 wifi_update_scanner_type(wifi, WIFI_SCANNING_ACTIVE);
3212 connman_device_ref(device);
3214 reset_autoscan(device);
3216 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
3217 scan_callback, device);
3219 connman_device_set_scanning(device,
3220 CONNMAN_SERVICE_TYPE_WIFI, true);
3221 #if defined TIZEN_EXT
3222 /*To allow the Full Scan after ssid based scan, set the flag here
3223 It is required because Tizen does not use the ConnMan specific
3224 backgroung Scan feature.Tizen has added the BG Scan feature in
3225 net-config. To sync with up ConnMan, we need to issue the Full Scan
3226 after SSID specific scan.*/
3227 wifi->allow_full_scan = TRUE;
3230 g_supplicant_free_scan_params(scan_params);
3231 connman_device_unref(device);
3234 hidden_free(wifi->hidden);
3235 wifi->hidden = NULL;
3242 static void wifi_stop_scan(enum connman_service_type type,
3243 struct connman_device *device)
3245 struct wifi_data *wifi = connman_device_get_data(device);
3247 DBG("device %p wifi %p", device, wifi);
3252 if (type == CONNMAN_SERVICE_TYPE_P2P) {
3253 if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
3254 g_source_remove(wifi->p2p_find_timeout);
3255 p2p_find_stop(device);
3260 static void wifi_regdom_callback(int result,
3264 struct connman_device *device = user_data;
3266 connman_device_regdom_notify(device, result, alpha2);
3268 connman_device_unref(device);
3271 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3273 struct wifi_data *wifi = connman_device_get_data(device);
3279 connman_device_ref(device);
3281 ret = g_supplicant_interface_set_country(wifi->interface,
3282 wifi_regdom_callback,
3285 connman_device_unref(device);
3290 static struct connman_device_driver wifi_ng_driver = {
3292 .type = CONNMAN_DEVICE_TYPE_WIFI,
3293 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3294 .probe = wifi_probe,
3295 .remove = wifi_remove,
3296 .enable = wifi_enable,
3297 .disable = wifi_disable,
3299 .stop_scan = wifi_stop_scan,
3300 .set_regdom = wifi_set_regdom,
3301 #if defined TIZEN_EXT
3302 .specific_scan = wifi_specific_scan,
3304 #if defined TIZEN_EXT_WIFI_MESH
3305 .abort_scan = mesh_abort_scan,
3306 .mesh_specific_scan = mesh_specific_scan,
3310 static void system_ready(void)
3314 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3315 connman_error("Failed to register WiFi driver");
3318 static void system_killed(void)
3322 connman_device_driver_unregister(&wifi_ng_driver);
3325 static int network_probe(struct connman_network *network)
3327 DBG("network %p", network);
3332 static void network_remove(struct connman_network *network)
3334 struct connman_device *device = connman_network_get_device(network);
3335 struct wifi_data *wifi;
3337 DBG("network %p", network);
3339 wifi = connman_device_get_data(device);
3343 if (wifi->network != network)
3346 wifi->network = NULL;
3348 #if defined TIZEN_EXT
3349 wifi->disconnecting = false;
3351 if (wifi->pending_network == network)
3352 wifi->pending_network = NULL;
3354 if (wifi->scan_pending_network == network)
3355 wifi->scan_pending_network = NULL;
3359 static void connect_callback(int result, GSupplicantInterface *interface,
3362 #if defined TIZEN_EXT
3364 struct wifi_data *wifi;
3366 struct connman_network *network = user_data;
3368 DBG("network %p result %d", network, result);
3370 #if defined TIZEN_EXT
3371 set_connman_bssid(RESET_BSSID, NULL);
3373 for (list = iface_list; list; list = list->next) {
3376 if (wifi && wifi->network == network)
3380 /* wifi_data may be invalid because wifi is already disabled */
3385 if (result == -ENOKEY) {
3386 connman_network_set_error(network,
3387 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3388 } else if (result < 0) {
3389 connman_network_set_error(network,
3390 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3393 connman_network_unref(network);
3396 static GSupplicantSecurity network_security(const char *security)
3398 if (g_str_equal(security, "none"))
3399 return G_SUPPLICANT_SECURITY_NONE;
3400 else if (g_str_equal(security, "wep"))
3401 return G_SUPPLICANT_SECURITY_WEP;
3402 else if (g_str_equal(security, "psk"))
3403 return G_SUPPLICANT_SECURITY_PSK;
3404 else if (g_str_equal(security, "wpa"))
3405 return G_SUPPLICANT_SECURITY_PSK;
3406 else if (g_str_equal(security, "rsn"))
3407 return G_SUPPLICANT_SECURITY_PSK;
3408 else if (g_str_equal(security, "ieee8021x"))
3409 return G_SUPPLICANT_SECURITY_IEEE8021X;
3410 #if defined TIZEN_EXT
3411 else if (g_str_equal(security, "ft_psk") == TRUE)
3412 return G_SUPPLICANT_SECURITY_FT_PSK;
3413 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3414 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3415 else if (g_str_equal(security, "sae"))
3416 return G_SUPPLICANT_SECURITY_SAE;
3417 else if (g_str_equal(security, "owe"))
3418 return G_SUPPLICANT_SECURITY_OWE;
3419 else if (g_str_equal(security, "dpp"))
3420 return G_SUPPLICANT_SECURITY_DPP;
3423 return G_SUPPLICANT_SECURITY_UNKNOWN;
3426 #if defined TIZEN_EXT
3427 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3429 if (security == NULL)
3430 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3432 if (g_str_equal(security, "FT") == TRUE)
3433 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3434 else if (g_str_equal(security, "CCKM") == TRUE)
3435 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3437 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3441 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3443 const char *security;
3444 #if defined TIZEN_EXT
3445 const void *ssid_data;
3448 memset(ssid, 0, sizeof(*ssid));
3449 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3450 #if defined TIZEN_EXT
3451 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3453 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3458 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3460 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3463 ssid->scan_ssid = 1;
3464 security = connman_network_get_string(network, "WiFi.Security");
3465 ssid->security = network_security(security);
3466 #if defined TIZEN_EXT
3467 ssid->ieee80211w = 1;
3469 ssid->passphrase = connman_network_get_string(network,
3472 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3475 * If our private key password is unset,
3476 * we use the supplied passphrase. That is needed
3477 * for PEAP where 2 passphrases (identity and client
3478 * cert may have to be provided.
3480 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3481 connman_network_set_string(network,
3482 "WiFi.PrivateKeyPassphrase",
3484 /* We must have an identity for both PEAP and TLS */
3485 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3487 /* Use agent provided identity as a fallback */
3488 if (!ssid->identity || strlen(ssid->identity) == 0)
3489 ssid->identity = connman_network_get_string(network,
3490 "WiFi.AgentIdentity");
3492 ssid->anonymous_identity = connman_network_get_string(network,
3493 "WiFi.AnonymousIdentity");
3494 ssid->ca_cert_path = connman_network_get_string(network,
3496 ssid->subject_match = connman_network_get_string(network,
3497 "WiFi.SubjectMatch");
3498 ssid->altsubject_match = connman_network_get_string(network,
3499 "WiFi.AltSubjectMatch");
3500 ssid->domain_suffix_match = connman_network_get_string(network,
3501 "WiFi.DomainSuffixMatch");
3502 ssid->domain_match = connman_network_get_string(network,
3503 "WiFi.DomainMatch");
3504 ssid->client_cert_path = connman_network_get_string(network,
3505 "WiFi.ClientCertFile");
3506 ssid->private_key_path = connman_network_get_string(network,
3507 "WiFi.PrivateKeyFile");
3508 ssid->private_key_passphrase = connman_network_get_string(network,
3509 "WiFi.PrivateKeyPassphrase");
3510 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3512 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3513 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3514 #if defined TIZEN_EXT
3515 ssid->connector = connman_network_get_string(network,
3517 ssid->c_sign_key = connman_network_get_string(network,
3519 ssid->net_access_key = connman_network_get_string(network,
3520 "WiFi.NetAccessKey");
3523 #if defined TIZEN_EXT
3524 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3525 ssid->bssid_for_connect_len = 6;
3526 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3527 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3528 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3529 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3530 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3532 ssid->freq = connman_network_get_frequency(network);
3535 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
3536 if (bssid_list && g_slist_length(bssid_list) > 1) {
3538 /* If there are more than one bssid,
3539 * the user-specified bssid is tried only once at the beginning.
3540 * After that, the bssids in the list are tried in order.
3542 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3543 set_connman_bssid(RESET_BSSID, NULL);
3548 char buff[MAC_ADDRESS_LENGTH];
3549 for (list = bssid_list; list; list = list->next) {
3550 struct connman_bssids * bssids = (struct connman_bssids *)list->data;
3552 g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
3553 bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
3554 bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
3555 buff[MAC_ADDRESS_LENGTH - 1] = '\0';
3557 gchar *curr_bssid = g_strdup((const gchar *)buff);
3559 if (g_hash_table_contains(failed_bssids, curr_bssid)) {
3560 DBG("bssid match, try next bssid");
3564 g_hash_table_add(failed_bssids, curr_bssid);
3566 memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
3567 ssid->bssid = buff_bssid;
3568 ssid->freq = (unsigned int)bssids->frequency;
3574 ssid->bssid = connman_network_get_bssid(network);
3575 g_hash_table_remove_all(failed_bssids);
3578 ssid->bssid = connman_network_get_bssid(network);
3581 ssid->eap_keymgmt = network_eap_keymgmt(
3582 connman_network_get_string(network, "WiFi.KeymgmtType"));
3583 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3585 if(g_strcmp0(ssid->eap, "fast") == 0)
3586 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3589 if (connman_setting_get_bool("BackgroundScanning"))
3590 ssid->bgscan = BGSCAN_DEFAULT;
3593 static int network_connect(struct connman_network *network)
3595 struct connman_device *device = connman_network_get_device(network);
3596 struct wifi_data *wifi;
3597 GSupplicantInterface *interface;
3598 GSupplicantSSID *ssid;
3600 DBG("network %p", network);
3605 wifi = connman_device_get_data(device);
3609 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3613 interface = wifi->interface;
3615 ssid_init(ssid, network);
3617 if (wifi->disconnecting) {
3618 wifi->pending_network = network;
3619 #if defined TIZEN_EXT
3624 wifi->network = connman_network_ref(network);
3626 #if defined TIZEN_EXT
3627 wifi->scan_pending_network = NULL;
3630 return g_supplicant_interface_connect(interface, ssid,
3631 connect_callback, network);
3634 return -EINPROGRESS;
3637 static void disconnect_callback(int result, GSupplicantInterface *interface,
3640 #if defined TIZEN_EXT
3642 struct wifi_data *wifi;
3643 struct connman_network *network = user_data;
3645 DBG("network %p result %d", network, result);
3647 for (list = iface_list; list; list = list->next) {
3650 if (wifi->network == NULL && wifi->disconnecting == true)
3651 wifi->disconnecting = false;
3653 if (wifi->network == network)
3657 /* wifi_data may be invalid because wifi is already disabled */
3662 struct wifi_data *wifi = user_data;
3665 DBG("result %d supplicant interface %p wifi %p",
3666 result, interface, wifi);
3668 if (result == -ECONNABORTED) {
3669 DBG("wifi interface no longer available");
3673 if (wifi->network != wifi->pending_network)
3674 connman_network_set_connected(wifi->network, false);
3675 wifi->network = NULL;
3677 wifi->disconnecting = false;
3678 wifi->connected = false;
3680 if (wifi->pending_network) {
3681 network_connect(wifi->pending_network);
3682 wifi->pending_network = NULL;
3685 start_autoscan(wifi->device);
3688 static int network_disconnect(struct connman_network *network)
3690 struct connman_device *device = connman_network_get_device(network);
3691 struct wifi_data *wifi;
3693 #if defined TIZEN_EXT
3694 struct connman_service *service;
3697 DBG("network %p", network);
3699 wifi = connman_device_get_data(device);
3700 if (!wifi || !wifi->interface)
3703 #if defined TIZEN_EXT
3704 if (connman_network_get_associating(network) == true) {
3705 connman_network_clear_associating(network);
3706 connman_network_set_bool(network, "WiFi.UseWPS", false);
3708 service = connman_service_lookup_from_network(network);
3710 if (service != NULL &&
3711 (__connman_service_is_connected_state(service,
3712 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3713 __connman_service_is_connected_state(service,
3714 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3715 (connman_service_get_favorite(service) == false))
3716 __connman_service_set_passphrase(service, NULL);
3719 if (wifi->pending_network == network)
3720 wifi->pending_network = NULL;
3722 if (wifi->scan_pending_network == network)
3723 wifi->scan_pending_network = NULL;
3726 connman_network_set_associating(network, false);
3728 if (wifi->disconnecting)
3731 wifi->disconnecting = true;
3733 #if defined TIZEN_EXT
3734 err = g_supplicant_interface_disconnect(wifi->interface,
3735 disconnect_callback, network);
3737 err = g_supplicant_interface_disconnect(wifi->interface,
3738 disconnect_callback, wifi);
3742 wifi->disconnecting = false;
3747 #if defined TIZEN_EXT
3748 static void set_connection_mode(struct connman_network *network,
3751 ieee80211_modes_e phy_mode;
3752 connection_mode_e conn_mode;
3754 phy_mode = connman_network_get_phy_mode(network);
3756 case IEEE80211_MODE_B:
3757 if (linkspeed > 0 && linkspeed <= 11)
3758 conn_mode = CONNECTION_MODE_IEEE80211B;
3760 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3763 case IEEE80211_MODE_BG:
3764 if (linkspeed > 0 && linkspeed <= 11)
3765 conn_mode = CONNECTION_MODE_IEEE80211B;
3766 else if (linkspeed > 11 && linkspeed <= 54)
3767 conn_mode = CONNECTION_MODE_IEEE80211G;
3769 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3772 case IEEE80211_MODE_BGN:
3773 if (linkspeed > 0 && linkspeed <= 11)
3774 conn_mode = CONNECTION_MODE_IEEE80211B;
3775 else if (linkspeed > 11 && linkspeed <= 54)
3776 conn_mode = CONNECTION_MODE_IEEE80211G;
3777 else if (linkspeed > 54 && linkspeed <= 450)
3778 conn_mode = CONNECTION_MODE_IEEE80211N;
3780 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3783 case IEEE80211_MODE_A:
3784 if (linkspeed > 0 && linkspeed <= 54)
3785 conn_mode = CONNECTION_MODE_IEEE80211A;
3787 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3790 case IEEE80211_MODE_AN:
3791 if (linkspeed > 0 && linkspeed <= 54)
3792 conn_mode = CONNECTION_MODE_IEEE80211A;
3793 else if (linkspeed > 54 && linkspeed <= 450)
3794 conn_mode = CONNECTION_MODE_IEEE80211N;
3796 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3799 case IEEE80211_MODE_ANAC:
3800 if (linkspeed > 0 && linkspeed <= 54)
3801 conn_mode = CONNECTION_MODE_IEEE80211A;
3802 else if (linkspeed > 54 && linkspeed <= 450)
3803 conn_mode = CONNECTION_MODE_IEEE80211N;
3804 else if (linkspeed > 450 && linkspeed <= 1300)
3805 conn_mode = CONNECTION_MODE_IEEE80211AC;
3807 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3811 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3815 DBG("connection mode(%d)", conn_mode);
3816 connman_network_set_connection_mode(network, conn_mode);
3819 static void signalpoll_callback(int result, int maxspeed, uint8_t strength,
3822 struct connman_network *network = user_data;
3825 DBG("Failed to get maxspeed from signalpoll !");
3833 DBG("maxspeed = %d, strength = %d", maxspeed, strength);
3835 connman_network_set_strength(network, strength);
3836 connman_network_set_maxspeed(network, maxspeed);
3837 set_connection_mode(network, maxspeed);
3841 static int network_signalpoll(struct wifi_data *wifi)
3843 GSupplicantInterface *interface;
3844 struct connman_network *network;
3846 if (!wifi || !wifi->network)
3849 interface = wifi->interface;
3850 network = wifi->network;
3852 DBG("network %p", network);
3854 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3857 static gboolean autosignalpoll_timeout(gpointer data)
3859 struct wifi_data *wifi = data;
3861 if (!wifi || !wifi->automaxspeed_timeout) {
3862 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3866 int ret = network_signalpoll(wifi);
3868 DBG("Fail to get max speed !!");
3869 wifi->automaxspeed_timeout = 0;
3877 static struct connman_network_driver network_driver = {
3879 .type = CONNMAN_NETWORK_TYPE_WIFI,
3880 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3881 .probe = network_probe,
3882 .remove = network_remove,
3883 .connect = network_connect,
3884 .disconnect = network_disconnect,
3887 static void interface_added(GSupplicantInterface *interface)
3889 const char *ifname = g_supplicant_interface_get_ifname(interface);
3890 const char *driver = g_supplicant_interface_get_driver(interface);
3891 #if defined TIZEN_EXT
3892 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3895 struct wifi_data *wifi;
3897 wifi = g_supplicant_interface_get_data(interface);
3899 wifi = get_pending_wifi_data(ifname);
3903 wifi->interface = interface;
3904 g_supplicant_interface_set_data(interface, wifi);
3905 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3906 wifi->p2p_device = true;
3909 DBG("ifname %s driver %s wifi %p tethering %d",
3910 ifname, driver, wifi, wifi->tethering);
3912 if (!wifi->device) {
3913 connman_error("WiFi device not set");
3917 connman_device_set_powered(wifi->device, true);
3918 #if defined TIZEN_EXT
3919 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3920 /* Max number of SSIDs supported by wlan chipset that can be scanned */
3921 int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
3922 connman_techonology_set_max_scan_ssids(wifi_technology, max_scan_ssids);
3926 static bool is_idle(struct wifi_data *wifi)
3928 DBG("state %d", wifi->state);
3930 switch (wifi->state) {
3931 case G_SUPPLICANT_STATE_UNKNOWN:
3932 case G_SUPPLICANT_STATE_DISABLED:
3933 case G_SUPPLICANT_STATE_DISCONNECTED:
3934 case G_SUPPLICANT_STATE_INACTIVE:
3935 case G_SUPPLICANT_STATE_SCANNING:
3938 case G_SUPPLICANT_STATE_AUTHENTICATING:
3939 case G_SUPPLICANT_STATE_ASSOCIATING:
3940 case G_SUPPLICANT_STATE_ASSOCIATED:
3941 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3942 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3943 case G_SUPPLICANT_STATE_COMPLETED:
3950 static bool is_idle_wps(GSupplicantInterface *interface,
3951 struct wifi_data *wifi)
3953 /* First, let's check if WPS processing did not went wrong */
3954 if (g_supplicant_interface_get_wps_state(interface) ==
3955 G_SUPPLICANT_WPS_STATE_FAIL)
3958 /* Unlike normal connection, being associated while processing wps
3959 * actually means that we are idling. */
3960 switch (wifi->state) {
3961 case G_SUPPLICANT_STATE_UNKNOWN:
3962 case G_SUPPLICANT_STATE_DISABLED:
3963 case G_SUPPLICANT_STATE_DISCONNECTED:
3964 case G_SUPPLICANT_STATE_INACTIVE:
3965 case G_SUPPLICANT_STATE_SCANNING:
3966 case G_SUPPLICANT_STATE_ASSOCIATED:
3968 case G_SUPPLICANT_STATE_AUTHENTICATING:
3969 case G_SUPPLICANT_STATE_ASSOCIATING:
3970 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3971 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3972 case G_SUPPLICANT_STATE_COMPLETED:
3979 static bool handle_wps_completion(GSupplicantInterface *interface,
3980 struct connman_network *network,
3981 struct connman_device *device,
3982 struct wifi_data *wifi)
3986 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3988 const unsigned char *ssid, *wps_ssid;
3989 unsigned int ssid_len, wps_ssid_len;
3990 const char *wps_key;
3992 /* Checking if we got associated with requested
3994 ssid = connman_network_get_blob(network, "WiFi.SSID",
3997 wps_ssid = g_supplicant_interface_get_wps_ssid(
3998 interface, &wps_ssid_len);
4000 if (!wps_ssid || wps_ssid_len != ssid_len ||
4001 memcmp(ssid, wps_ssid, ssid_len) != 0) {
4002 connman_network_set_associating(network, false);
4003 #if defined TIZEN_EXT
4004 g_supplicant_interface_disconnect(wifi->interface,
4005 disconnect_callback, wifi->network);
4007 connman_network_set_bool(network, "WiFi.UseWPS", false);
4008 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4010 g_supplicant_interface_disconnect(wifi->interface,
4011 disconnect_callback, wifi);
4016 wps_key = g_supplicant_interface_get_wps_key(interface);
4017 #if defined TIZEN_EXT
4018 /* Check the passphrase and encrypt it
4021 gchar *passphrase = g_strdup(wps_key);
4023 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4025 if (check_passphrase_ext(network, passphrase) < 0) {
4026 DBG("[WPS] Invalid passphrase");
4031 ret = send_encryption_request(passphrase, network);
4036 DBG("[WPS] Encryption request succeeded");
4038 DBG("[WPS] Encryption request failed %d", ret);
4041 connman_network_set_string(network, "WiFi.Passphrase",
4044 connman_network_set_string(network, "WiFi.PinWPS", NULL);
4051 static bool handle_assoc_status_code(GSupplicantInterface *interface,
4052 struct wifi_data *wifi)
4054 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
4055 #if defined TIZEN_EXT
4056 wifi->assoc_code > 0 &&
4058 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
4060 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
4061 wifi->load_shaping_retries ++;
4064 wifi->load_shaping_retries = 0;
4068 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
4069 struct connman_network *network,
4070 struct wifi_data *wifi)
4072 #if defined TIZEN_EXT
4073 const char *security;
4074 struct connman_service *service;
4076 if (wifi->connected)
4079 security = connman_network_get_string(network, "WiFi.Security");
4081 if (security && g_str_equal(security, "ieee8021x") == true &&
4082 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4084 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4089 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4092 struct connman_service *service;
4094 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
4097 if (wifi->connected)
4101 service = connman_service_lookup_from_network(network);
4107 if (connman_service_get_favorite(service)) {
4108 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
4113 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
4118 #if defined TIZEN_EXT
4119 static bool handle_wifi_assoc_retry(struct connman_network *network,
4120 struct wifi_data *wifi)
4122 const char *security;
4124 if (!wifi->network || wifi->connected || wifi->disconnecting ||
4125 connman_network_get_connecting(network) != true) {
4126 wifi->assoc_retry_count = 0;
4130 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
4131 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
4132 wifi->assoc_retry_count = 0;
4136 security = connman_network_get_string(network, "WiFi.Security");
4137 if (security && g_str_equal(security, "ieee8021x") == true &&
4138 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
4139 wifi->assoc_retry_count = 0;
4143 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
4144 wifi->assoc_retry_count = 0;
4146 /* Honestly it's not an invalid-key error,
4147 * however QA team recommends that the invalid-key error
4148 * might be better to display for user experience.
4150 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
4159 static void interface_state(GSupplicantInterface *interface)
4161 struct connman_network *network;
4162 struct connman_device *device;
4163 struct wifi_data *wifi;
4164 GSupplicantState state = g_supplicant_interface_get_state(interface);
4168 wifi = g_supplicant_interface_get_data(interface);
4170 DBG("wifi %p interface state %d", wifi, state);
4175 device = wifi->device;
4179 if (state == G_SUPPLICANT_STATE_COMPLETED) {
4180 if (wifi->tethering_param) {
4181 g_free(wifi->tethering_param->ssid);
4182 g_free(wifi->tethering_param);
4183 wifi->tethering_param = NULL;
4186 if (wifi->tethering)
4187 stop_autoscan(device);
4190 if (g_supplicant_interface_get_ready(interface) &&
4191 !wifi->interface_ready) {
4192 wifi->interface_ready = true;
4193 finalize_interface_creation(wifi);
4196 network = wifi->network;
4201 case G_SUPPLICANT_STATE_SCANNING:
4202 if (wifi->connected)
4203 connman_network_set_connected(network, false);
4207 case G_SUPPLICANT_STATE_AUTHENTICATING:
4208 case G_SUPPLICANT_STATE_ASSOCIATING:
4209 #if defined TIZEN_EXT
4210 reset_autoscan(device);
4212 stop_autoscan(device);
4215 if (!wifi->connected)
4216 connman_network_set_associating(network, true);
4220 case G_SUPPLICANT_STATE_COMPLETED:
4221 #if defined TIZEN_EXT
4222 /* though it should be already reset: */
4223 reset_autoscan(device);
4225 wifi->assoc_retry_count = 0;
4227 wifi->scan_pending_network = NULL;
4229 /* should be cleared scanning flag */
4230 bool scanning = connman_device_get_scanning(device,
4231 CONNMAN_SERVICE_TYPE_WIFI);
4233 connman_device_set_scanning(device,
4234 CONNMAN_SERVICE_TYPE_WIFI, false);
4235 connman_device_unref(device);
4238 if (!wifi->automaxspeed_timeout) {
4239 DBG("Going to start signalpoll timer!!");
4240 int ret = network_signalpoll(wifi);
4242 DBG("Fail to get max speed !!");
4244 wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
4247 g_hash_table_remove_all(failed_bssids);
4249 /* though it should be already stopped: */
4250 stop_autoscan(device);
4253 if (!handle_wps_completion(interface, network, device, wifi))
4256 connman_network_set_connected(network, true);
4258 wifi->disconnect_code = 0;
4259 wifi->assoc_code = 0;
4260 wifi->load_shaping_retries = 0;
4263 case G_SUPPLICANT_STATE_DISCONNECTED:
4264 #if defined TIZEN_EXT
4265 connman_network_set_strength(network, 0);
4266 connman_network_set_maxspeed(network, 0);
4268 if (wifi->automaxspeed_timeout != 0) {
4269 g_source_remove(wifi->automaxspeed_timeout);
4270 wifi->automaxspeed_timeout = 0;
4271 DBG("Remove signalpoll timer!!");
4275 * If we're in one of the idle modes, we have
4276 * not started association yet and thus setting
4277 * those ones to FALSE could cancel an association
4280 wps = connman_network_get_bool(network, "WiFi.UseWPS");
4282 if (is_idle_wps(interface, wifi))
4288 #if defined TIZEN_EXT
4289 if (handle_assoc_status_code(interface, wifi)) {
4290 GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
4291 guint bssid_length = 0;
4294 bssid_length = g_slist_length(bssid_list);
4296 if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
4297 network_connect(network);
4301 wifi->load_shaping_retries = 0;
4304 g_hash_table_remove_all(failed_bssids);
4306 if (handle_assoc_status_code(interface, wifi))
4310 /* If previous state was 4way-handshake, then
4311 * it's either: psk was incorrect and thus we retry
4312 * or if we reach the maximum retries we declare the
4314 if (handle_4way_handshake_failure(interface,
4318 /* See table 8-36 Reason codes in IEEE Std 802.11 */
4319 switch (wifi->disconnect_code) {
4320 case 1: /* Unspecified reason */
4321 /* Let's assume it's because we got blocked */
4323 case 6: /* Class 2 frame received from nonauthenticated STA */
4324 connman_network_set_error(network,
4325 CONNMAN_NETWORK_ERROR_BLOCKED);
4332 #if defined TIZEN_EXT
4333 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
4334 * Retry association until its retry count is expired */
4335 if (handle_wifi_assoc_retry(network, wifi) == true) {
4336 throw_wifi_scan(wifi->device, scan_callback);
4337 wifi->scan_pending_network = wifi->network;
4341 if(wifi->disconnect_code > 0){
4342 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
4343 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
4347 if (network != wifi->pending_network) {
4348 connman_network_set_connected(network, false);
4349 connman_network_set_associating(network, false);
4351 wifi->disconnecting = false;
4353 start_autoscan(device);
4357 case G_SUPPLICANT_STATE_INACTIVE:
4358 #if defined TIZEN_EXT
4359 if (handle_wps_completion(interface, network, device, wifi) == false)
4362 connman_network_set_associating(network, false);
4363 start_autoscan(device);
4367 case G_SUPPLICANT_STATE_UNKNOWN:
4368 case G_SUPPLICANT_STATE_DISABLED:
4369 case G_SUPPLICANT_STATE_ASSOCIATED:
4370 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4371 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4375 old_connected = wifi->connected;
4376 wifi->state = state;
4378 /* Saving wpa_s state policy:
4379 * If connected and if the state changes are roaming related:
4380 * --> We stay connected
4382 * --> We are connected
4384 * --> We are not connected
4387 case G_SUPPLICANT_STATE_AUTHENTICATING:
4388 case G_SUPPLICANT_STATE_ASSOCIATING:
4389 case G_SUPPLICANT_STATE_ASSOCIATED:
4390 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4391 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4392 if (wifi->connected)
4393 connman_warn("Probably roaming right now!"
4394 " Staying connected...");
4396 case G_SUPPLICANT_STATE_SCANNING:
4397 wifi->connected = false;
4400 start_autoscan(device);
4402 case G_SUPPLICANT_STATE_COMPLETED:
4403 wifi->connected = true;
4406 wifi->connected = false;
4413 static void interface_removed(GSupplicantInterface *interface)
4415 const char *ifname = g_supplicant_interface_get_ifname(interface);
4416 struct wifi_data *wifi;
4418 DBG("ifname %s", ifname);
4420 wifi = g_supplicant_interface_get_data(interface);
4422 #if defined TIZEN_EXT_WIFI_MESH
4423 if (wifi && wifi->mesh_interface) {
4424 DBG("Notify mesh interface remove");
4425 connman_mesh_notify_interface_remove(true);
4426 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4427 g_free(mesh_info->parent_ifname);
4428 g_free(mesh_info->ifname);
4429 g_free(mesh_info->identifier);
4431 wifi->mesh_interface = false;
4432 wifi->mesh_info = NULL;
4438 wifi->interface = NULL;
4440 if (wifi && wifi->tethering)
4443 if (!wifi || !wifi->device) {
4444 DBG("wifi interface already removed");
4448 connman_device_set_powered(wifi->device, false);
4450 check_p2p_technology();
4451 #if defined TIZEN_EXT_WIFI_MESH
4452 check_mesh_technology();
4456 static void set_device_type(const char *type, char dev_type[17])
4458 const char *oui = "0050F204";
4459 const char *category = "0001";
4460 const char *sub_category = "0000";
4462 if (!g_strcmp0(type, "handset")) {
4464 sub_category = "0005";
4465 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4466 sub_category = "0001";
4467 else if (!g_strcmp0(type, "server"))
4468 sub_category = "0002";
4469 else if (!g_strcmp0(type, "laptop"))
4470 sub_category = "0005";
4471 else if (!g_strcmp0(type, "desktop"))
4472 sub_category = "0006";
4473 else if (!g_strcmp0(type, "tablet"))
4474 sub_category = "0009";
4475 else if (!g_strcmp0(type, "watch"))
4478 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4481 static void p2p_support(GSupplicantInterface *interface)
4483 char dev_type[17] = {};
4484 const char *hostname;
4491 if (!g_supplicant_interface_has_p2p(interface))
4494 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4495 DBG("Could not register P2P technology driver");
4499 hostname = connman_utsname_get_hostname();
4501 hostname = "ConnMan";
4503 set_device_type(connman_machine_get_type(), dev_type);
4504 g_supplicant_interface_set_p2p_device_config(interface,
4505 hostname, dev_type);
4506 connman_peer_driver_register(&peer_driver);
4509 static void scan_started(GSupplicantInterface *interface)
4514 static void scan_finished(GSupplicantInterface *interface)
4516 #if defined TIZEN_EXT
4517 struct wifi_data *wifi;
4518 bool is_associating = false;
4519 static bool is_scanning = true;
4524 #if defined TIZEN_EXT
4525 wifi = g_supplicant_interface_get_data(interface);
4526 if (wifi && wifi->scan_pending_network) {
4527 network_connect(wifi->scan_pending_network);
4528 wifi->scan_pending_network = NULL;
4531 //service state - associating
4532 if(!wifi || !wifi->network)
4535 is_associating = connman_network_get_associating(wifi->network);
4536 if(is_associating && is_scanning){
4537 is_scanning = false;
4538 DBG("send scan for connecting");
4539 throw_wifi_scan(wifi->device, scan_callback);
4550 static void ap_create_fail(GSupplicantInterface *interface)
4552 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4555 if ((wifi->tethering) && (wifi->tethering_param)) {
4556 DBG("%s create AP fail \n",
4557 g_supplicant_interface_get_ifname(wifi->interface));
4559 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4560 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4561 wifi->tethering = false;
4563 ret = tech_set_tethering(wifi->tethering_param->technology,
4564 wifi->tethering_param->ssid->ssid,
4565 wifi->tethering_param->ssid->passphrase,
4566 wifi->bridge, true);
4568 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4569 connman_technology_tethering_notify(wifi_technology,false);
4572 g_free(wifi->tethering_param->ssid);
4573 g_free(wifi->tethering_param);
4574 wifi->tethering_param = NULL;
4578 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4580 unsigned char strength;
4582 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4583 #if !defined TIZEN_EXT
4591 #if defined TIZEN_EXT_WIFI_MESH
4592 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4594 GSupplicantInterface *interface;
4595 struct wifi_data *wifi;
4596 const char *name, *security;
4597 struct connman_mesh *connman_mesh;
4598 struct wifi_mesh_info *mesh_info;
4599 const unsigned char *bssid;
4600 const char *identifier;
4605 interface = g_supplicant_network_get_interface(supplicant_network);
4606 wifi = g_supplicant_interface_get_data(interface);
4607 if (!wifi || !wifi->mesh_interface) {
4608 DBG("Virtual Mesh interface not created");
4612 bssid = g_supplicant_network_get_bssid(supplicant_network);
4613 address = g_malloc0(19);
4614 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4615 bssid[2], bssid[3], bssid[4], bssid[5]);
4617 identifier = g_supplicant_network_get_identifier(supplicant_network);
4618 name = g_supplicant_network_get_name(supplicant_network);
4619 security = g_supplicant_network_get_security(supplicant_network);
4620 frequency = g_supplicant_network_get_frequency(supplicant_network);
4622 mesh_info = wifi->mesh_info;
4623 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4627 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4629 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4630 connman_mesh_set_name(connman_mesh, name);
4631 connman_mesh_set_security(connman_mesh, security);
4632 connman_mesh_set_frequency(connman_mesh, frequency);
4633 connman_mesh_set_address(connman_mesh, address);
4634 connman_mesh_set_index(connman_mesh, mesh_info->index);
4635 connman_mesh_set_strength(connman_mesh,
4636 calculate_strength(supplicant_network));
4637 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4639 ret = connman_mesh_register(connman_mesh);
4640 if (ret == -EALREADY)
4641 DBG("Mesh Peer is already registered");
4647 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4649 GSupplicantInterface *interface;
4650 struct wifi_data *wifi;
4651 struct connman_mesh *connman_mesh;
4652 struct wifi_mesh_info *mesh_info;
4653 const char *identifier;
4655 interface = g_supplicant_network_get_interface(supplicant_network);
4656 wifi = g_supplicant_interface_get_data(interface);
4657 if (!wifi || !wifi->mesh_interface) {
4658 DBG("Virtual Mesh interface not created");
4662 identifier = g_supplicant_network_get_identifier(supplicant_network);
4664 DBG("Failed to get Mesh Peer identifier");
4668 mesh_info = wifi->mesh_info;
4669 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4671 /* Do not unregister connected mesh peer */
4672 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4673 DBG("Mesh Peer %s is connected", identifier);
4676 DBG("Mesh Peer identifier %s removed", identifier);
4677 connman_mesh_unregister(connman_mesh);
4682 static void network_added(GSupplicantNetwork *supplicant_network)
4684 struct connman_network *network;
4685 GSupplicantInterface *interface;
4686 struct wifi_data *wifi;
4687 const char *name, *identifier, *security, *group, *mode;
4688 const unsigned char *ssid;
4689 unsigned int ssid_len;
4693 bool wps_advertizing;
4695 #if defined TIZEN_EXT
4696 GSList *vsie_list = NULL;
4697 const unsigned char *country_code;
4698 ieee80211_modes_e phy_mode;
4701 mode = g_supplicant_network_get_mode(supplicant_network);
4702 identifier = g_supplicant_network_get_identifier(supplicant_network);
4704 DBG("%s", identifier);
4706 if (!g_strcmp0(mode, "adhoc"))
4709 #if defined TIZEN_EXT_WIFI_MESH
4710 if (!g_strcmp0(mode, "mesh")) {
4711 mesh_peer_added(supplicant_network);
4716 interface = g_supplicant_network_get_interface(supplicant_network);
4717 wifi = g_supplicant_interface_get_data(interface);
4718 name = g_supplicant_network_get_name(supplicant_network);
4719 security = g_supplicant_network_get_security(supplicant_network);
4720 group = g_supplicant_network_get_identifier(supplicant_network);
4721 wps = g_supplicant_network_get_wps(supplicant_network);
4722 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4723 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4724 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4725 supplicant_network);
4730 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4732 network = connman_device_get_network(wifi->device, identifier);
4735 network = connman_network_create(identifier,
4736 CONNMAN_NETWORK_TYPE_WIFI);
4740 connman_network_set_index(network, wifi->index);
4742 if (connman_device_add_network(wifi->device, network) < 0) {
4743 connman_network_unref(network);
4747 wifi->networks = g_slist_prepend(wifi->networks, network);
4750 if (name && name[0] != '\0')
4751 connman_network_set_name(network, name);
4753 connman_network_set_blob(network, "WiFi.SSID",
4755 #if defined TIZEN_EXT
4756 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4758 connman_network_set_vsie_list(network, vsie_list);
4760 DBG("vsie_list is NULL");
4761 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4762 connman_network_set_countrycode(network, country_code);
4763 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4764 connman_network_set_phy_mode(network, phy_mode);
4766 connman_network_set_string(network, "WiFi.Security", security);
4767 connman_network_set_strength(network,
4768 calculate_strength(supplicant_network));
4769 connman_network_set_bool(network, "WiFi.WPS", wps);
4770 connman_network_set_bool(network, "WiFi.WPSAdvertising",
4774 /* Is AP advertizing for WPS association?
4775 * If so, we decide to use WPS by default */
4776 if (wps_ready && wps_pbc &&
4778 #if !defined TIZEN_EXT
4779 connman_network_set_bool(network, "WiFi.UseWPS", true);
4781 DBG("wps is activating by ap but ignore it.");
4785 connman_network_set_frequency(network,
4786 g_supplicant_network_get_frequency(supplicant_network));
4788 #if defined TIZEN_EXT
4789 connman_network_set_bssid(network,
4790 g_supplicant_network_get_bssid(supplicant_network));
4791 connman_network_set_maxrate(network,
4792 g_supplicant_network_get_maxrate(supplicant_network));
4793 connman_network_set_enc_mode(network,
4794 g_supplicant_network_get_enc_mode(supplicant_network));
4795 connman_network_set_rsn_mode(network,
4796 g_supplicant_network_get_rsn_mode(supplicant_network));
4797 connman_network_set_keymgmt(network,
4798 g_supplicant_network_get_keymgmt(supplicant_network));
4799 connman_network_set_bool(network, "WiFi.HS20AP",
4800 g_supplicant_network_is_hs20AP(supplicant_network));
4801 connman_network_set_bssid_list(network,
4802 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4804 connman_network_set_available(network, true);
4805 connman_network_set_string(network, "WiFi.Mode", mode);
4807 #if defined TIZEN_EXT
4812 connman_network_set_group(network, group);
4814 #if defined TIZEN_EXT
4815 if (wifi_first_scan == true)
4816 found_with_first_scan = true;
4819 if (wifi->hidden && ssid) {
4820 #if defined TIZEN_EXT
4821 if (network_security(wifi->hidden->security) ==
4822 network_security(security) &&
4824 if (!g_strcmp0(wifi->hidden->security, security) &&
4826 wifi->hidden->ssid_len == ssid_len &&
4827 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4828 connman_network_connect_hidden(network,
4829 wifi->hidden->identity,
4830 wifi->hidden->passphrase,
4831 wifi->hidden->user_data);
4832 wifi->hidden->user_data = NULL;
4833 hidden_free(wifi->hidden);
4834 wifi->hidden = NULL;
4839 static void network_removed(GSupplicantNetwork *network)
4841 GSupplicantInterface *interface;
4842 struct wifi_data *wifi;
4843 const char *name, *identifier;
4844 struct connman_network *connman_network;
4846 #if defined TIZEN_EXT_WIFI_MESH
4848 mode = g_supplicant_network_get_mode(network);
4849 if (!g_strcmp0(mode, "mesh")) {
4850 mesh_peer_removed(network);
4855 interface = g_supplicant_network_get_interface(network);
4856 wifi = g_supplicant_interface_get_data(interface);
4857 identifier = g_supplicant_network_get_identifier(network);
4858 name = g_supplicant_network_get_name(network);
4860 DBG("name %s", name);
4865 connman_network = connman_device_get_network(wifi->device, identifier);
4866 if (!connman_network)
4869 #if defined TIZEN_EXT
4870 if (connman_network == wifi->scan_pending_network)
4871 wifi->scan_pending_network = NULL;
4873 if (connman_network == wifi->pending_network)
4874 wifi->pending_network = NULL;
4876 if(connman_network_get_connecting(connman_network) == true){
4877 connman_network_set_connected(connman_network, false);
4881 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4883 connman_device_remove_network(wifi->device, connman_network);
4884 connman_network_unref(connman_network);
4887 static void network_changed(GSupplicantNetwork *network, const char *property)
4889 GSupplicantInterface *interface;
4890 struct wifi_data *wifi;
4891 const char *name, *identifier;
4892 struct connman_network *connman_network;
4895 #if defined TIZEN_EXT
4896 const unsigned char *bssid;
4897 unsigned int maxrate;
4900 const unsigned char *country_code;
4901 ieee80211_modes_e phy_mode;
4905 interface = g_supplicant_network_get_interface(network);
4906 wifi = g_supplicant_interface_get_data(interface);
4907 identifier = g_supplicant_network_get_identifier(network);
4908 name = g_supplicant_network_get_name(network);
4910 DBG("name %s", name);
4915 connman_network = connman_device_get_network(wifi->device, identifier);
4916 if (!connman_network)
4919 if (g_str_equal(property, "WPSCapabilities")) {
4923 bool wps_advertizing;
4925 wps = g_supplicant_network_get_wps(network);
4926 wps_pbc = g_supplicant_network_is_wps_pbc(network);
4927 wps_ready = g_supplicant_network_is_wps_active(network);
4929 g_supplicant_network_is_wps_advertizing(network);
4931 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4932 connman_network_set_bool(connman_network,
4933 "WiFi.WPSAdvertising", wps_advertizing);
4937 * Is AP advertizing for WPS association?
4938 * If so, we decide to use WPS by default
4940 if (wps_ready && wps_pbc && wps_advertizing)
4941 connman_network_set_bool(connman_network,
4942 "WiFi.UseWPS", true);
4945 update_needed = true;
4946 } else if (g_str_equal(property, "Signal")) {
4947 connman_network_set_strength(connman_network,
4948 calculate_strength(network));
4949 update_needed = true;
4951 update_needed = false;
4954 connman_network_update(connman_network);
4956 #if defined TIZEN_EXT
4957 bssid = g_supplicant_network_get_bssid(network);
4958 maxrate = g_supplicant_network_get_maxrate(network);
4959 frequency = g_supplicant_network_get_frequency(network);
4960 wps = g_supplicant_network_get_wps(network);
4961 phy_mode = g_supplicant_network_get_phy_mode(network);
4963 connman_network_set_bssid(connman_network, bssid);
4964 connman_network_set_maxrate(connman_network, maxrate);
4965 connman_network_set_frequency(connman_network, frequency);
4966 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4967 country_code = g_supplicant_network_get_countrycode(network);
4968 connman_network_set_countrycode(connman_network, country_code);
4969 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4970 connman_network_set_bssid_list(connman_network, bssid_list);
4971 connman_network_set_phy_mode(connman_network, phy_mode);
4973 if (g_str_equal(property, "CheckMultiBssidConnect") &&
4974 connman_network_get_associating(connman_network))
4975 network_connect(connman_network);
4979 static void network_associated(GSupplicantNetwork *network)
4981 GSupplicantInterface *interface;
4982 struct wifi_data *wifi;
4983 struct connman_network *connman_network;
4984 const char *identifier;
4988 interface = g_supplicant_network_get_interface(network);
4992 wifi = g_supplicant_interface_get_data(interface);
4996 /* P2P networks must not be treated as WiFi networks */
4997 if (wifi->p2p_connecting || wifi->p2p_device)
5000 identifier = g_supplicant_network_get_identifier(network);
5002 connman_network = connman_device_get_network(wifi->device, identifier);
5003 if (!connman_network)
5006 if (wifi->network) {
5007 if (wifi->network == connman_network)
5011 * This should never happen, we got associated with
5012 * a network different than the one we were expecting.
5014 DBG("Associated to %p while expecting %p",
5015 connman_network, wifi->network);
5017 connman_network_set_associating(wifi->network, false);
5020 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
5022 wifi->network = connman_network_ref(connman_network);
5026 * Interface state changes callback (interface_state) is always
5027 * called before network_associated callback thus we need to call
5028 * interface_state again in order to process the new state now that
5029 * we have the network properly set.
5031 interface_state(interface);
5034 static void sta_authorized(GSupplicantInterface *interface,
5037 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5039 DBG("wifi %p station %s authorized", wifi, addr);
5041 if (!wifi || !wifi->tethering)
5044 __connman_tethering_client_register(addr);
5047 static void sta_deauthorized(GSupplicantInterface *interface,
5050 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5052 DBG("wifi %p station %s deauthorized", wifi, addr);
5054 if (!wifi || !wifi->tethering)
5057 __connman_tethering_client_unregister(addr);
5060 static void apply_peer_services(GSupplicantPeer *peer,
5061 struct connman_peer *connman_peer)
5063 const unsigned char *data;
5068 connman_peer_reset_services(connman_peer);
5070 data = g_supplicant_peer_get_widi_ies(peer, &length);
5072 connman_peer_add_service(connman_peer,
5073 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
5077 static void peer_found(GSupplicantPeer *peer)
5079 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5080 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5081 struct connman_peer *connman_peer;
5082 const char *identifier, *name;
5085 #if defined TIZEN_EXT
5089 identifier = g_supplicant_peer_get_identifier(peer);
5090 name = g_supplicant_peer_get_name(peer);
5092 DBG("ident: %s", identifier);
5094 connman_peer = connman_peer_get(wifi->device, identifier);
5098 connman_peer = connman_peer_create(identifier);
5099 connman_peer_set_name(connman_peer, name);
5100 connman_peer_set_device(connman_peer, wifi->device);
5101 apply_peer_services(peer, connman_peer);
5103 ret = connman_peer_register(connman_peer);
5104 if (ret < 0 && ret != -EALREADY)
5105 connman_peer_unref(connman_peer);
5107 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
5110 static void peer_lost(GSupplicantPeer *peer)
5112 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5113 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5114 struct connman_peer *connman_peer;
5115 const char *identifier;
5120 identifier = g_supplicant_peer_get_identifier(peer);
5122 DBG("ident: %s", identifier);
5124 connman_peer = connman_peer_get(wifi->device, identifier);
5126 if (wifi->p2p_connecting &&
5127 wifi->pending_peer == connman_peer) {
5128 peer_connect_timeout(wifi);
5130 connman_peer_unregister(connman_peer);
5131 connman_peer_unref(connman_peer);
5134 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
5137 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
5139 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5140 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5141 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
5142 struct connman_peer *connman_peer;
5143 const char *identifier;
5145 identifier = g_supplicant_peer_get_identifier(peer);
5147 DBG("ident: %s", identifier);
5152 connman_peer = connman_peer_get(wifi->device, identifier);
5157 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
5158 apply_peer_services(peer, connman_peer);
5159 connman_peer_services_changed(connman_peer);
5161 case G_SUPPLICANT_PEER_GROUP_CHANGED:
5162 if (!g_supplicant_peer_is_in_a_group(peer))
5163 p_state = CONNMAN_PEER_STATE_IDLE;
5165 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
5167 case G_SUPPLICANT_PEER_GROUP_STARTED:
5169 case G_SUPPLICANT_PEER_GROUP_FINISHED:
5170 p_state = CONNMAN_PEER_STATE_IDLE;
5172 case G_SUPPLICANT_PEER_GROUP_JOINED:
5173 connman_peer_set_iface_address(connman_peer,
5174 g_supplicant_peer_get_iface_address(peer));
5176 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
5177 p_state = CONNMAN_PEER_STATE_IDLE;
5179 case G_SUPPLICANT_PEER_GROUP_FAILED:
5180 if (g_supplicant_peer_has_requested_connection(peer))
5181 p_state = CONNMAN_PEER_STATE_IDLE;
5183 p_state = CONNMAN_PEER_STATE_FAILURE;
5187 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
5188 p_state == CONNMAN_PEER_STATE_FAILURE) {
5189 if (wifi->p2p_connecting
5190 && connman_peer == wifi->pending_peer)
5191 peer_cancel_timeout(wifi);
5193 p_state = CONNMAN_PEER_STATE_UNKNOWN;
5196 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
5199 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
5200 GSupplicantInterface *g_iface;
5201 struct wifi_data *g_wifi;
5203 g_iface = g_supplicant_peer_get_group_interface(peer);
5207 g_wifi = g_supplicant_interface_get_data(g_iface);
5211 connman_peer_set_as_master(connman_peer,
5212 !g_supplicant_peer_is_client(peer));
5213 connman_peer_set_sub_device(connman_peer, g_wifi->device);
5216 * If wpa_supplicant didn't create a dedicated p2p-group
5217 * interface then mark this interface as p2p_device to avoid
5218 * scan and auto-scan are launched on it while P2P is connected.
5220 if (!g_list_find(p2p_iface_list, g_wifi))
5221 wifi->p2p_device = true;
5224 connman_peer_set_state(connman_peer, p_state);
5227 static void peer_request(GSupplicantPeer *peer)
5229 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
5230 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
5231 struct connman_peer *connman_peer;
5232 const char *identifier;
5234 #if defined TIZEN_EXT
5239 identifier = g_supplicant_peer_get_identifier(peer);
5241 DBG("ident: %s", identifier);
5243 connman_peer = connman_peer_get(wifi->device, identifier);
5247 connman_peer_request_connection(connman_peer);
5250 #if defined TIZEN_EXT
5251 static void system_power_off(void)
5254 struct wifi_data *wifi;
5255 struct connman_service *service;
5256 struct connman_ipconfig *ipconfig_ipv4;
5258 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
5259 for (list = iface_list; list; list = list->next) {
5262 if (wifi->network != NULL) {
5263 service = connman_service_lookup_from_network(wifi->network);
5264 ipconfig_ipv4 = __connman_service_get_ip4config(service);
5265 __connman_dhcp_stop(ipconfig_ipv4);
5271 static void network_merged(GSupplicantNetwork *network)
5273 GSupplicantInterface *interface;
5274 GSupplicantState state;
5275 struct wifi_data *wifi;
5276 const char *identifier;
5277 struct connman_network *connman_network;
5281 interface = g_supplicant_network_get_interface(network);
5285 state = g_supplicant_interface_get_state(interface);
5286 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
5289 wifi = g_supplicant_interface_get_data(interface);
5293 identifier = g_supplicant_network_get_identifier(network);
5295 connman_network = connman_device_get_network(wifi->device, identifier);
5296 if (!connman_network)
5299 DBG("merged identifier %s", identifier);
5301 if (wifi->connected == FALSE) {
5303 case G_SUPPLICANT_STATE_AUTHENTICATING:
5304 case G_SUPPLICANT_STATE_ASSOCIATING:
5305 case G_SUPPLICANT_STATE_ASSOCIATED:
5306 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
5307 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
5308 connman_network_set_associating(connman_network, TRUE);
5310 case G_SUPPLICANT_STATE_COMPLETED:
5311 connman_network_set_connected(connman_network, TRUE);
5314 DBG("Not handled the state : %d", state);
5319 ishs20AP = g_supplicant_network_is_hs20AP(network);
5322 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
5323 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
5324 connman_network_set_string(connman_network, "WiFi.EAP",
5326 connman_network_set_string(connman_network, "WiFi.Identity",
5327 g_supplicant_network_get_identity(network));
5328 connman_network_set_string(connman_network, "WiFi.Phase2",
5329 g_supplicant_network_get_phase2(network));
5334 wifi->network = connman_network;
5337 static void assoc_failed(void *user_data)
5339 struct connman_network *network = user_data;
5340 connman_network_set_associating(network, false);
5344 static void debug(const char *str)
5346 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
5347 connman_debug("%s", str);
5350 static void disconnect_reasoncode(GSupplicantInterface *interface,
5353 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5356 wifi->disconnect_code = reasoncode;
5360 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
5362 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
5365 wifi->assoc_code = status_code;
5369 static const GSupplicantCallbacks callbacks = {
5370 .system_ready = system_ready,
5371 .system_killed = system_killed,
5372 .interface_added = interface_added,
5373 .interface_state = interface_state,
5374 .interface_removed = interface_removed,
5375 .p2p_support = p2p_support,
5376 .scan_started = scan_started,
5377 .scan_finished = scan_finished,
5378 .ap_create_fail = ap_create_fail,
5379 .network_added = network_added,
5380 .network_removed = network_removed,
5381 .network_changed = network_changed,
5382 .network_associated = network_associated,
5383 .sta_authorized = sta_authorized,
5384 .sta_deauthorized = sta_deauthorized,
5385 .peer_found = peer_found,
5386 .peer_lost = peer_lost,
5387 .peer_changed = peer_changed,
5388 .peer_request = peer_request,
5389 #if defined TIZEN_EXT
5390 .system_power_off = system_power_off,
5391 .network_merged = network_merged,
5392 .assoc_failed = assoc_failed,
5395 .disconnect_reasoncode = disconnect_reasoncode,
5396 .assoc_status_code = assoc_status_code,
5397 #if defined TIZEN_EXT_WIFI_MESH
5398 .mesh_support = mesh_support,
5399 .mesh_group_started = mesh_group_started,
5400 .mesh_group_removed = mesh_group_removed,
5401 .mesh_peer_connected = mesh_peer_connected,
5402 .mesh_peer_disconnected = mesh_peer_disconnected,
5407 static int tech_probe(struct connman_technology *technology)
5409 wifi_technology = technology;
5414 static void tech_remove(struct connman_technology *technology)
5416 wifi_technology = NULL;
5419 static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
5421 GSupplicantSSID *ap;
5423 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5427 ap->mode = G_SUPPLICANT_MODE_MASTER;
5428 #if defined TIZEN_EXT
5429 ap->ssid = (void *) ssid;
5433 ap->ssid_len = strlen(ssid);
5437 if (!passphrase || strlen(passphrase) == 0) {
5438 ap->security = G_SUPPLICANT_SECURITY_NONE;
5439 ap->passphrase = NULL;
5441 ap->security = G_SUPPLICANT_SECURITY_PSK;
5442 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5443 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5444 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5445 ap->passphrase = passphrase;
5451 static void ap_start_callback(int result, GSupplicantInterface *interface,
5454 struct wifi_tethering_info *info = user_data;
5456 DBG("result %d index %d bridge %s",
5457 result, info->wifi->index, info->wifi->bridge);
5459 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5460 connman_inet_remove_from_bridge(info->wifi->index,
5461 info->wifi->bridge);
5463 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5464 connman_technology_tethering_notify(info->technology, false);
5465 g_free(info->wifi->tethering_param->ssid);
5466 g_free(info->wifi->tethering_param);
5467 info->wifi->tethering_param = NULL;
5471 g_free(info->ifname);
5475 static void ap_create_callback(int result,
5476 GSupplicantInterface *interface,
5479 struct wifi_tethering_info *info = user_data;
5481 DBG("result %d ifname %s", result,
5482 g_supplicant_interface_get_ifname(interface));
5484 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5485 connman_inet_remove_from_bridge(info->wifi->index,
5486 info->wifi->bridge);
5488 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5489 connman_technology_tethering_notify(info->technology, false);
5490 g_free(info->wifi->tethering_param->ssid);
5491 g_free(info->wifi->tethering_param);
5492 info->wifi->tethering_param = NULL;
5496 g_free(info->ifname);
5502 info->wifi->interface = interface;
5503 g_supplicant_interface_set_data(interface, info->wifi);
5505 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5506 connman_error("Failed to set interface ap_scan property");
5508 g_supplicant_interface_connect(interface, info->ssid,
5509 ap_start_callback, info);
5512 static void sta_remove_callback(int result,
5513 GSupplicantInterface *interface,
5516 struct wifi_tethering_info *info = user_data;
5517 const char *driver = connman_option_get_string("wifi");
5519 DBG("ifname %s result %d ", info->ifname, result);
5521 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5522 info->wifi->tethering = false;
5523 connman_technology_tethering_notify(info->technology, false);
5524 #if !defined TIZEN_EXT
5526 g_free(info->ifname);
5529 #endif /* !defined TIZEN_EXT */
5531 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5532 g_free(info->wifi->tethering_param->ssid);
5533 g_free(info->wifi->tethering_param);
5534 info->wifi->tethering_param = NULL;
5536 #if defined TIZEN_EXT
5538 g_free(info->ifname);
5541 #endif /* defined TIZEN_EXT */
5545 info->wifi->interface = NULL;
5547 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5552 static int enable_wifi_tethering(struct connman_technology *technology,
5553 const char *bridge, const char *identifier,
5554 const char *passphrase, bool available)
5557 GSupplicantInterface *interface;
5558 struct wifi_data *wifi;
5559 struct wifi_tethering_info *info;
5564 for (list = iface_list; list; list = list->next) {
5567 DBG("wifi %p network %p pending_network %p", wifi,
5568 wifi->network, wifi->pending_network);
5570 interface = wifi->interface;
5575 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5579 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5580 DBG("%s does not support AP mode (detected)", ifname);
5584 mode = g_supplicant_interface_get_mode(interface);
5585 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5586 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5587 DBG("%s does not support AP mode (capability)", ifname);
5591 if (wifi->network && available)
5594 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5598 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5599 if (!wifi->tethering_param) {
5605 info->technology = technology;
5606 info->wifi->bridge = bridge;
5607 info->ssid = ssid_ap_init(identifier, passphrase);
5611 info->ifname = g_strdup(ifname);
5613 wifi->tethering_param->technology = technology;
5614 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5615 if (!wifi->tethering_param->ssid)
5618 info->wifi->tethering = true;
5619 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5621 berr = connman_technology_tethering_notify(technology, true);
5625 err = g_supplicant_interface_remove(interface,
5626 sta_remove_callback,
5629 DBG("tethering wifi %p ifname %s", wifi, ifname);
5634 g_free(info->ifname);
5637 g_free(wifi->tethering_param);
5638 wifi->tethering_param = NULL;
5641 * Remove bridge if it was correctly created but remove
5642 * operation failed. Instead, if bridge creation failed then
5643 * break out and do not try again on another interface,
5644 * bridge set-up does not depend on it.
5647 connman_technology_tethering_notify(technology, false);
5655 static int tech_set_tethering(struct connman_technology *technology,
5656 const char *identifier, const char *passphrase,
5657 const char *bridge, bool enabled)
5660 struct wifi_data *wifi;
5666 for (list = iface_list; list; list = list->next) {
5669 if (wifi->tethering) {
5670 wifi->tethering = false;
5672 connman_inet_remove_from_bridge(wifi->index,
5674 wifi->bridged = false;
5678 connman_technology_tethering_notify(technology, false);
5683 DBG("trying tethering for available devices");
5684 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5688 DBG("trying tethering for any device");
5689 err = enable_wifi_tethering(technology, bridge, identifier,
5696 static void regdom_callback(int result, const char *alpha2, void *user_data)
5700 if (!wifi_technology)
5706 connman_technology_regdom_notify(wifi_technology, alpha2);
5709 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5711 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5714 static struct connman_technology_driver tech_driver = {
5716 .type = CONNMAN_SERVICE_TYPE_WIFI,
5717 .probe = tech_probe,
5718 .remove = tech_remove,
5719 .set_tethering = tech_set_tethering,
5720 .set_regdom = tech_set_regdom,
5723 static int wifi_init(void)
5727 err = connman_network_driver_register(&network_driver);
5731 err = g_supplicant_register(&callbacks);
5733 connman_network_driver_unregister(&network_driver);
5737 err = connman_technology_driver_register(&tech_driver);
5739 g_supplicant_unregister(&callbacks);
5740 connman_network_driver_unregister(&network_driver);
5744 #if defined TIZEN_EXT
5745 failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
5750 static void wifi_exit(void)
5754 connman_technology_driver_unregister(&tech_driver);
5756 g_supplicant_unregister(&callbacks);
5758 connman_network_driver_unregister(&network_driver);
5760 #if defined TIZEN_EXT
5761 g_hash_table_unref(failed_bssids);
5765 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5766 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)