5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <linux/if_arp.h>
34 #include <linux/wireless.h>
35 #include <net/ethernet.h>
38 #define IFF_LOWER_UP 0x10000
41 #include <dbus/dbus.h>
44 #define CONNMAN_API_SUBJECT_TO_CHANGE
45 #include <connman/plugin.h>
46 #include <connman/inet.h>
47 #include <connman/device.h>
48 #include <connman/rtnl.h>
49 #include <connman/technology.h>
50 #include <connman/service.h>
51 #include <connman/peer.h>
52 #include <connman/log.h>
53 #include <connman/option.h>
54 #include <connman/storage.h>
55 #include <include/setting.h>
56 #include <connman/provision.h>
57 #include <connman/utsname.h>
58 #include <connman/machine.h>
60 #include <gsupplicant/gsupplicant.h>
62 #define CLEANUP_TIMEOUT 8 /* in seconds */
63 #define INACTIVE_TIMEOUT 12 /* in seconds */
64 #define FAVORITE_MAXIMUM_RETRIES 2
66 #define BGSCAN_DEFAULT "simple:30:-45:300"
67 #define AUTOSCAN_DEFAULT "exponential:3:300"
69 #define P2P_FIND_TIMEOUT 30
70 #define P2P_CONNECTION_TIMEOUT 100
71 #define P2P_LISTEN_PERIOD 500
72 #define P2P_LISTEN_INTERVAL 2000
74 #define ASSOC_STATUS_NO_CLIENT 17
75 #define LOAD_SHAPING_MAX_RETRIES 3
78 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
81 static struct connman_technology *wifi_technology = NULL;
82 static struct connman_technology *p2p_technology = NULL;
84 enum wifi_ap_capability{
86 WIFI_AP_SUPPORTED = 1,
87 WIFI_AP_NOT_SUPPORTED = 2,
90 struct hidden_params {
92 unsigned int ssid_len;
94 char *anonymous_identity;
96 char *altsubject_match;
97 char *domain_suffix_match;
101 GSupplicantScanParams *scan_params;
106 * Used for autoscan "emulation".
107 * Should be removed when wpa_s autoscan support will be by default.
109 struct autoscan_params {
113 unsigned int timeout;
116 struct wifi_tethering_info {
117 struct wifi_data *wifi;
118 struct connman_technology *technology;
120 GSupplicantSSID *ssid;
125 struct connman_device *device;
126 struct connman_network *network;
127 struct connman_network *pending_network;
129 GSupplicantInterface *interface;
130 GSupplicantState state;
134 enum wifi_ap_capability ap_supported;
136 bool interface_ready;
142 int load_shaping_retries;
143 struct hidden_params *hidden;
144 bool postpone_hidden;
145 struct wifi_tethering_info *tethering_param;
147 * autoscan "emulation".
149 struct autoscan_params *autoscan;
151 GSupplicantScanParams *scan_params;
152 unsigned int p2p_find_timeout;
153 unsigned int p2p_connection_timeout;
154 struct connman_peer *pending_peer;
159 #if defined TIZEN_EXT
160 int assoc_retry_count;
161 struct connman_network *scan_pending_network;
162 bool allow_full_scan;
166 #if defined TIZEN_EXT_WIFI_MESH
168 struct wifi_mesh_info *mesh_info;
172 #if defined TIZEN_EXT
176 #define TIZEN_ASSOC_RETRY_COUNT 4
178 static gboolean wifi_first_scan = false;
179 static gboolean found_with_first_scan = false;
180 static gboolean is_wifi_notifier_registered = false;
184 static GList *iface_list = NULL;
186 static GList *pending_wifi_device = NULL;
187 static GList *p2p_iface_list = NULL;
188 bool wfd_service_registered = false;
190 static void start_autoscan(struct connman_device *device);
192 static int tech_set_tethering(struct connman_technology *technology,
193 const char *identifier, const char *passphrase,
194 const char *bridge, bool enabled);
196 #if defined TIZEN_EXT
197 #define NETCONFIG_SERVICE "net.netconfig"
198 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
199 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
201 struct enc_method_call_data {
202 DBusConnection *connection;
203 struct connman_network *network;
206 static struct enc_method_call_data encrypt_request_data;
208 static void encryption_request_reply(DBusPendingCall *call,
213 DBusMessageIter args;
215 struct connman_service *service;
216 gchar* encrypted_value = NULL;
217 struct connman_network *network = encrypt_request_data.network;
221 reply = dbus_pending_call_steal_reply(call);
223 dbus_error_init(&error);
224 if (dbus_set_error_from_message(&error, reply)) {
225 DBG("send_encryption_request() %s %s", error.name, error.message);
226 dbus_error_free(&error);
230 if (dbus_message_iter_init(reply, &args) == FALSE)
233 dbus_message_iter_get_basic(&args, &out_data);
235 encrypted_value = g_strdup((const gchar *)out_data);
236 service = connman_service_lookup_from_network(network);
239 DBG("encryption result: no service");
243 if (connman_service_get_favorite(service)) {
244 __connman_service_set_passphrase(service, encrypted_value);
245 __connman_service_save(service);
247 connman_network_set_string(network, "WiFi.Passphrase",
250 DBG("encryption result: succeeded");
253 dbus_message_unref(reply);
254 dbus_pending_call_unref(call);
255 dbus_connection_unref(encrypt_request_data.connection);
256 g_free(encrypted_value);
258 encrypt_request_data.connection = NULL;
259 encrypt_request_data.network = NULL;
262 static int send_encryption_request(const char *passphrase,
263 struct connman_network *network)
265 DBusConnection *connection = NULL;
266 DBusMessage *msg = NULL;
267 DBusPendingCall *call;
270 DBG("Invalid parameter");
274 connection = connman_dbus_get_connection();
276 DBG("dbus connection does not exist");
280 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
281 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
283 dbus_connection_unref(connection);
287 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
290 if (!dbus_connection_send_with_reply(connection, msg,
291 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
292 dbus_message_unref(msg);
293 dbus_connection_unref(connection);
298 dbus_message_unref(msg);
299 dbus_connection_unref(connection);
303 encrypt_request_data.connection = connection;
304 encrypt_request_data.network = network;
306 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
307 dbus_message_unref(msg);
313 static int p2p_tech_probe(struct connman_technology *technology)
315 p2p_technology = technology;
320 static void p2p_tech_remove(struct connman_technology *technology)
322 p2p_technology = NULL;
325 static struct connman_technology_driver p2p_tech_driver = {
327 .type = CONNMAN_SERVICE_TYPE_P2P,
328 .probe = p2p_tech_probe,
329 .remove = p2p_tech_remove,
332 static bool is_p2p_connecting(void)
336 for (list = iface_list; list; list = list->next) {
337 struct wifi_data *wifi = list->data;
339 if (wifi->p2p_connecting)
346 static void add_pending_wifi_device(struct wifi_data *wifi)
348 if (g_list_find(pending_wifi_device, wifi))
351 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
354 #if defined TIZEN_EXT_WIFI_MESH
355 struct wifi_mesh_info {
356 struct wifi_data *wifi;
357 GSupplicantInterface *interface;
358 struct connman_mesh *mesh;
365 struct mesh_change_peer_status_info {
367 enum connman_mesh_peer_status peer_status;
368 mesh_change_peer_status_cb_t callback;
372 static struct connman_technology_driver mesh_tech_driver = {
374 .type = CONNMAN_SERVICE_TYPE_MESH,
377 static void mesh_interface_create_callback(int result,
378 GSupplicantInterface *interface,
381 struct wifi_mesh_info *mesh_info = user_data;
382 struct wifi_data *wifi;
383 bool success = false;
385 DBG("result %d ifname %s, mesh_info %p", result,
386 g_supplicant_interface_get_ifname(interface),
389 if (result < 0 || !mesh_info)
392 wifi = mesh_info->wifi;
394 mesh_info->interface = interface;
395 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
396 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
397 DBG("Mesh Interface identifier %s", mesh_info->identifier);
398 wifi->mesh_interface = true;
399 wifi->mesh_info = mesh_info;
400 g_supplicant_interface_set_data(interface, wifi);
404 connman_mesh_notify_interface_create(success);
407 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
410 struct wifi_data *wifi;
411 struct wifi_mesh_info *mesh_info;
412 const char *wifi_ifname;
413 bool parent_found = false;
414 const char *driver = "nl80211";
416 for (list = iface_list; list; list = list->next) {
419 if (!g_supplicant_interface_has_mesh(wifi->interface))
422 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
426 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
433 DBG("Parent interface %s doesn't exist", parent_ifname);
437 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
441 mesh_info->wifi = wifi;
442 mesh_info->ifname = g_strdup(ifname);
443 mesh_info->parent_ifname = g_strdup(parent_ifname);
445 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
446 mesh_interface_create_callback, mesh_info);
450 static void mesh_interface_remove_callback(int result,
451 GSupplicantInterface *interface,
454 struct wifi_data *wifi = user_data;
455 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
456 bool success = false;
458 DBG("result %d mesh_info %p", result, mesh_info);
460 if (result < 0 || !mesh_info)
463 mesh_info->interface = NULL;
464 g_free(mesh_info->parent_ifname);
465 g_free(mesh_info->ifname);
466 g_free(mesh_info->identifier);
468 wifi->mesh_interface = false;
469 wifi->mesh_info = NULL;
473 connman_mesh_notify_interface_remove(success);
476 static int remove_mesh_interface(const char *ifname)
479 struct wifi_data *wifi;
480 struct wifi_mesh_info *mesh_info;
481 bool mesh_if_found = false;
484 for (list = iface_list; list; list = list->next) {
487 if (wifi->mesh_interface) {
488 mesh_if_found = true;
493 if (!mesh_if_found) {
494 DBG("Mesh interface %s doesn't exist", ifname);
498 mesh_info = wifi->mesh_info;
499 ret = g_supplicant_interface_remove(mesh_info->interface,
500 mesh_interface_remove_callback, wifi);
507 static void mesh_disconnect_callback(int result,
508 GSupplicantInterface *interface, void *user_data)
510 struct connman_mesh *mesh = user_data;
512 DBG("result %d interface %p mesh %p", result, interface, mesh);
515 static int mesh_peer_disconnect(struct connman_mesh *mesh)
518 struct wifi_data *wifi;
519 struct wifi_mesh_info *mesh_info;
520 bool mesh_if_found = false;
521 GSupplicantInterface *interface;
523 for (list = iface_list; list; list = list->next) {
526 if (wifi->mesh_interface) {
527 mesh_if_found = true;
532 if (!mesh_if_found) {
533 DBG("Mesh interface is not created");
537 mesh_info = wifi->mesh_info;
539 interface = mesh_info->interface;
540 return g_supplicant_interface_disconnect(interface,
541 mesh_disconnect_callback, mesh);
544 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
547 struct connman_mesh *mesh = user_data;
548 DBG("mesh %p result %d", mesh, result);
551 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
553 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
556 static GSupplicantSecurity mesh_network_security(const char *security)
558 if (g_str_equal(security, "none"))
559 return G_SUPPLICANT_SECURITY_NONE;
560 else if (g_str_equal(security, "sae"))
561 return G_SUPPLICANT_SECURITY_SAE;
563 return G_SUPPLICANT_SECURITY_UNKNOWN;
566 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
569 const char *security;
574 memset(ssid, 0, sizeof(*ssid));
575 ssid->mode = G_SUPPLICANT_MODE_MESH;
577 security = connman_mesh_get_security(mesh);
578 ssid->security = mesh_network_security(security);
580 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
581 ssid->passphrase = connman_mesh_get_passphrase(mesh);
583 ssid->freq = connman_mesh_get_frequency(mesh);
584 name = connman_mesh_get_name(mesh);
586 ssid->ssid_len = strlen(name);
587 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
588 memcpy(ssid->ssid, name, ssid->ssid_len);
593 static int mesh_peer_connect(struct connman_mesh *mesh)
596 struct wifi_data *wifi;
597 struct wifi_mesh_info *mesh_info;
598 bool mesh_if_found = false;
599 GSupplicantInterface *interface;
600 GSupplicantSSID *ssid;
602 for (list = iface_list; list; list = list->next) {
605 if (wifi->mesh_interface) {
606 mesh_if_found = true;
611 if (!mesh_if_found) {
612 DBG("Mesh interface is not created");
616 mesh_info = wifi->mesh_info;
618 interface = mesh_info->interface;
620 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
624 mesh_info->mesh = mesh;
626 mesh_ssid_init(ssid, mesh);
627 return g_supplicant_interface_connect(interface, ssid,
628 mesh_connect_callback, mesh);
631 static void mesh_peer_change_status_callback(int result,
632 GSupplicantInterface *interface,
635 struct mesh_change_peer_status_info *data = user_data;
637 DBG("result %d Peer Status %d", result, data->peer_status);
639 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
640 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
641 connman_mesh_remove_connected_peer(data->peer_address, 52);
645 data->callback(result, data->user_data);
647 g_free(data->peer_address);
652 static int mesh_change_peer_status(const char *peer_address,
653 enum connman_mesh_peer_status status,
654 mesh_change_peer_status_cb_t callback, void *user_data)
657 struct wifi_data *wifi;
658 struct wifi_mesh_info *mesh_info;
659 bool mesh_if_found = false;
660 GSupplicantInterface *interface;
661 struct mesh_change_peer_status_info *data;
664 for (list = iface_list; list; list = list->next) {
667 if (wifi->mesh_interface) {
668 mesh_if_found = true;
673 if (!mesh_if_found) {
674 DBG("Mesh interface is not created");
678 mesh_info = wifi->mesh_info;
680 interface = mesh_info->interface;
683 case CONNMAN_MESH_PEER_ADD:
684 method = "MeshPeerAdd";
686 case CONNMAN_MESH_PEER_REMOVE:
687 method = "MeshPeerRemove";
690 DBG("Invalid method");
694 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
696 DBG("Memory allocation failed");
700 data->peer_address = g_strdup(peer_address);
701 data->peer_status = status;
702 data->callback = callback;
703 data->user_data = user_data;
705 return g_supplicant_interface_mesh_peer_change_status(interface,
706 mesh_peer_change_status_callback, peer_address, method,
710 static struct connman_mesh_driver mesh_driver = {
711 .add_interface = add_mesh_interface,
712 .remove_interface = remove_mesh_interface,
713 .connect = mesh_peer_connect,
714 .disconnect = mesh_peer_disconnect,
715 .change_peer_status = mesh_change_peer_status,
718 static void mesh_support(GSupplicantInterface *interface)
722 if (!g_supplicant_interface_has_mesh(interface))
725 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
726 DBG("Could not register Mesh technology driver");
730 connman_mesh_driver_register(&mesh_driver);
733 static void check_mesh_technology(void)
735 bool mesh_exists = false;
738 for (list = iface_list; list; list = list->next) {
739 struct wifi_data *w = list->data;
742 g_supplicant_interface_has_mesh(w->interface))
747 connman_technology_driver_unregister(&mesh_tech_driver);
748 connman_mesh_driver_unregister(&mesh_driver);
752 static void mesh_group_started(GSupplicantInterface *interface)
754 struct wifi_data *wifi;
755 struct wifi_mesh_info *mesh_info;
756 struct connman_mesh *mesh;
757 const unsigned char *ssid;
758 unsigned int ssid_len;
761 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
762 memcpy(name, ssid, ssid_len);
763 name[ssid_len] = '\0';
764 DBG("name %s", name);
765 wifi = g_supplicant_interface_get_data(interface);
766 DBG("wifi %p", wifi);
771 mesh_info = wifi->mesh_info;
775 mesh = mesh_info->mesh;
779 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
782 static void mesh_group_removed(GSupplicantInterface *interface)
784 struct wifi_data *wifi;
785 struct wifi_mesh_info *mesh_info;
786 struct connman_mesh *mesh;
787 const unsigned char *ssid;
788 unsigned int ssid_len;
789 int disconnect_reason;
792 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
793 memcpy(name, ssid, ssid_len);
794 name[ssid_len] = '\0';
795 DBG("name %s", name);
797 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
798 DBG("Disconnect Reason %d", disconnect_reason);
800 wifi = g_supplicant_interface_get_data(interface);
801 DBG("wifi %p", wifi);
806 mesh_info = wifi->mesh_info;
810 mesh = connman_get_connected_mesh_from_name(name);
812 DBG("%s is not connected", name);
813 mesh = connman_get_connecting_mesh_from_name(name);
815 DBG("%s is not connecting", name);
820 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
821 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
824 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
826 const char *peer_address;
828 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
833 DBG("Peer %s connected", peer_address);
834 connman_mesh_add_connected_peer(peer_address);
837 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
839 const char *peer_address;
842 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
847 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
849 DBG("Peer %s disconnected with reason %d", peer_address, reason);
850 connman_mesh_remove_connected_peer(peer_address, reason);
854 static struct wifi_data *get_pending_wifi_data(const char *ifname)
858 for (list = pending_wifi_device; list; list = list->next) {
859 struct wifi_data *wifi;
860 const char *dev_name;
863 if (!wifi || !wifi->device)
866 dev_name = connman_device_get_string(wifi->device, "Interface");
867 if (!g_strcmp0(ifname, dev_name)) {
868 pending_wifi_device = g_list_delete_link(
869 pending_wifi_device, list);
877 static void remove_pending_wifi_device(struct wifi_data *wifi)
881 link = g_list_find(pending_wifi_device, wifi);
886 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
889 static void peer_cancel_timeout(struct wifi_data *wifi)
891 if (wifi->p2p_connection_timeout > 0)
892 g_source_remove(wifi->p2p_connection_timeout);
894 wifi->p2p_connection_timeout = 0;
895 wifi->p2p_connecting = false;
897 if (wifi->pending_peer) {
898 connman_peer_unref(wifi->pending_peer);
899 wifi->pending_peer = NULL;
903 static gboolean peer_connect_timeout(gpointer data)
905 struct wifi_data *wifi = data;
909 if (wifi->p2p_connecting) {
910 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
911 GSupplicantPeer *gs_peer =
912 g_supplicant_interface_peer_lookup(wifi->interface,
913 connman_peer_get_identifier(wifi->pending_peer));
915 if (g_supplicant_peer_has_requested_connection(gs_peer))
916 state = CONNMAN_PEER_STATE_IDLE;
918 connman_peer_set_state(wifi->pending_peer, state);
921 peer_cancel_timeout(wifi);
926 static void peer_connect_callback(int result, GSupplicantInterface *interface,
929 struct wifi_data *wifi = user_data;
930 struct connman_peer *peer = wifi->pending_peer;
932 DBG("peer %p - %d", peer, result);
938 peer_connect_timeout(wifi);
942 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
944 wifi->p2p_connection_timeout = g_timeout_add_seconds(
945 P2P_CONNECTION_TIMEOUT,
946 peer_connect_timeout, wifi);
949 static int peer_connect(struct connman_peer *peer,
950 enum connman_peer_wps_method wps_method,
953 struct connman_device *device = connman_peer_get_device(peer);
954 GSupplicantPeerParams *peer_params;
955 GSupplicantPeer *gs_peer;
956 struct wifi_data *wifi;
960 DBG("peer %p", peer);
965 wifi = connman_device_get_data(device);
966 if (!wifi || !wifi->interface)
969 if (wifi->p2p_connecting)
972 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
973 connman_peer_get_identifier(peer));
977 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
978 pin = g_supplicant_peer_is_wps_pin(gs_peer);
980 switch (wps_method) {
981 case CONNMAN_PEER_WPS_UNKNOWN:
982 if ((pbc && pin) || pin)
985 case CONNMAN_PEER_WPS_PBC:
990 case CONNMAN_PEER_WPS_PIN:
991 if (!pin || !wps_pin)
996 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1000 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1002 peer_params->wps_pin = g_strdup(wps_pin);
1004 peer_params->master = connman_peer_service_is_master();
1006 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1007 peer_connect_callback, wifi);
1008 if (ret == -EINPROGRESS) {
1009 wifi->pending_peer = connman_peer_ref(peer);
1010 wifi->p2p_connecting = true;
1011 } else if (ret < 0) {
1012 g_free(peer_params->path);
1013 g_free(peer_params->wps_pin);
1014 g_free(peer_params);
1020 static int peer_disconnect(struct connman_peer *peer)
1022 struct connman_device *device = connman_peer_get_device(peer);
1023 GSupplicantPeerParams peer_params = {};
1024 GSupplicantPeer *gs_peer;
1025 struct wifi_data *wifi;
1028 DBG("peer %p", peer);
1033 wifi = connman_device_get_data(device);
1037 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1038 connman_peer_get_identifier(peer));
1042 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1044 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1046 g_free(peer_params.path);
1048 if (ret == -EINPROGRESS) {
1049 peer_cancel_timeout(wifi);
1050 wifi->p2p_device = false;
1056 struct peer_service_registration {
1057 peer_service_registration_cb_t callback;
1061 static bool is_service_wfd(const unsigned char *specs, int length)
1063 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1069 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1071 struct wifi_data *wifi = data;
1073 if (!wifi->interface ||
1074 !g_supplicant_interface_has_p2p(wifi->interface))
1077 if (!wifi->servicing) {
1078 g_supplicant_interface_p2p_listen(wifi->interface,
1079 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1085 static void register_wfd_service_cb(int result,
1086 GSupplicantInterface *iface, void *user_data)
1088 struct peer_service_registration *reg_data = user_data;
1093 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1095 if (reg_data && reg_data->callback) {
1096 reg_data->callback(result, reg_data->user_data);
1101 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1102 const unsigned char *spec,
1103 int spec_length, const unsigned char *query,
1104 int query_length, int version)
1106 GSupplicantP2PServiceParams *params;
1108 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1113 params->version = version;
1114 params->service = g_memdup(spec, spec_length);
1115 } else if (query_length > 0 && spec_length > 0) {
1116 params->query = g_memdup(query, query_length);
1117 params->query_length = query_length;
1119 params->response = g_memdup(spec, spec_length);
1120 params->response_length = spec_length;
1122 params->wfd_ies = g_memdup(spec, spec_length);
1123 params->wfd_ies_length = spec_length;
1129 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1134 g_free(params->service);
1135 g_free(params->query);
1136 g_free(params->response);
1137 g_free(params->wfd_ies);
1142 static int peer_register_wfd_service(const unsigned char *specification,
1143 int specification_length,
1144 peer_service_registration_cb_t callback,
1147 struct peer_service_registration *reg_data = NULL;
1148 static GSupplicantP2PServiceParams *params;
1153 if (wfd_service_registered)
1156 params = fill_in_peer_service_params(specification,
1157 specification_length, NULL, 0, 0);
1161 reg_data = g_try_malloc0(sizeof(*reg_data));
1167 reg_data->callback = callback;
1168 reg_data->user_data = user_data;
1170 ret = g_supplicant_set_widi_ies(params,
1171 register_wfd_service_cb, reg_data);
1172 if (ret < 0 && ret != -EINPROGRESS)
1175 wfd_service_registered = true;
1179 free_peer_service_params(params);
1185 static void register_peer_service_cb(int result,
1186 GSupplicantInterface *iface, void *user_data)
1188 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1189 struct peer_service_registration *reg_data = user_data;
1191 #if defined TIZEN_EXT
1199 apply_p2p_listen_on_iface(wifi, NULL);
1201 if (reg_data->callback)
1202 reg_data->callback(result, reg_data->user_data);
1207 static int peer_register_service(const unsigned char *specification,
1208 int specification_length,
1209 const unsigned char *query,
1210 int query_length, int version,
1211 peer_service_registration_cb_t callback,
1214 struct peer_service_registration *reg_data;
1215 GSupplicantP2PServiceParams *params;
1222 if (specification && !version && !query &&
1223 is_service_wfd(specification, specification_length)) {
1224 return peer_register_wfd_service(specification,
1225 specification_length, callback, user_data);
1228 reg_data = g_try_malloc0(sizeof(*reg_data));
1232 reg_data->callback = callback;
1233 reg_data->user_data = user_data;
1235 ret_f = -EOPNOTSUPP;
1237 for (list = iface_list; list; list = list->next) {
1238 struct wifi_data *wifi = list->data;
1239 GSupplicantInterface *iface = wifi->interface;
1241 if (!g_supplicant_interface_has_p2p(iface))
1244 params = fill_in_peer_service_params(specification,
1245 specification_length, query,
1246 query_length, version);
1253 ret_f = g_supplicant_interface_p2p_add_service(iface,
1254 register_peer_service_cb, params, reg_data);
1255 if (ret_f == 0 || ret_f == -EINPROGRESS)
1259 ret = g_supplicant_interface_p2p_add_service(iface,
1260 register_peer_service_cb, params, NULL);
1261 if (ret != 0 && ret != -EINPROGRESS)
1262 free_peer_service_params(params);
1265 if (ret_f != 0 && ret_f != -EINPROGRESS)
1271 static int peer_unregister_wfd_service(void)
1273 GSupplicantP2PServiceParams *params;
1276 if (!wfd_service_registered)
1279 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1283 wfd_service_registered = false;
1285 g_supplicant_set_widi_ies(params, NULL, NULL);
1287 for (list = iface_list; list; list = list->next) {
1288 struct wifi_data *wifi = list->data;
1290 if (!g_supplicant_interface_has_p2p(wifi->interface))
1294 if (!wifi->servicing || wifi->servicing < 0) {
1295 g_supplicant_interface_p2p_listen(wifi->interface,
1297 wifi->servicing = 0;
1304 static int peer_unregister_service(const unsigned char *specification,
1305 int specification_length,
1306 const unsigned char *query,
1307 int query_length, int version)
1309 GSupplicantP2PServiceParams *params;
1314 if (specification && !version && !query &&
1315 is_service_wfd(specification, specification_length)) {
1316 ret = peer_unregister_wfd_service();
1317 if (ret != 0 && ret != -EINPROGRESS)
1322 for (list = iface_list; list; list = list->next) {
1323 struct wifi_data *wifi = list->data;
1324 GSupplicantInterface *iface = wifi->interface;
1327 goto stop_listening;
1329 if (!g_supplicant_interface_has_p2p(iface))
1332 params = fill_in_peer_service_params(specification,
1333 specification_length, query,
1334 query_length, version);
1340 ret = g_supplicant_interface_p2p_del_service(iface, params);
1341 if (ret != 0 && ret != -EINPROGRESS)
1342 free_peer_service_params(params);
1345 if (!wifi->servicing || wifi->servicing < 0) {
1346 g_supplicant_interface_p2p_listen(iface, 0, 0);
1347 wifi->servicing = 0;
1354 static struct connman_peer_driver peer_driver = {
1355 .connect = peer_connect,
1356 .disconnect = peer_disconnect,
1357 .register_service = peer_register_service,
1358 .unregister_service = peer_unregister_service,
1361 static void handle_tethering(struct wifi_data *wifi)
1363 if (!wifi->tethering)
1372 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1374 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1377 wifi->bridged = true;
1380 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1382 struct connman_device *device = user_data;
1383 struct wifi_data *wifi = connman_device_get_data(device);
1388 DBG("index %d flags %d change %d", wifi->index, flags, change);
1390 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1392 DBG("interface up");
1394 DBG("interface down");
1397 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1398 if (flags & IFF_LOWER_UP) {
1401 handle_tethering(wifi);
1406 wifi->flags = flags;
1409 static int wifi_probe(struct connman_device *device)
1411 struct wifi_data *wifi;
1413 DBG("device %p", device);
1415 wifi = g_try_new0(struct wifi_data, 1);
1419 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1420 wifi->ap_supported = WIFI_AP_UNKNOWN;
1421 wifi->tethering_param = NULL;
1423 connman_device_set_data(device, wifi);
1424 wifi->device = connman_device_ref(device);
1426 wifi->index = connman_device_get_index(device);
1429 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1430 wifi_newlink, device);
1431 if (is_p2p_connecting())
1432 add_pending_wifi_device(wifi);
1434 iface_list = g_list_append(iface_list, wifi);
1439 static void remove_networks(struct connman_device *device,
1440 struct wifi_data *wifi)
1444 for (list = wifi->networks; list; list = list->next) {
1445 struct connman_network *network = list->data;
1447 connman_device_remove_network(device, network);
1448 connman_network_unref(network);
1451 g_slist_free(wifi->networks);
1452 wifi->networks = NULL;
1455 static void remove_peers(struct wifi_data *wifi)
1459 for (list = wifi->peers; list; list = list->next) {
1460 struct connman_peer *peer = list->data;
1462 connman_peer_unregister(peer);
1463 connman_peer_unref(peer);
1466 g_slist_free(wifi->peers);
1470 static void reset_autoscan(struct connman_device *device)
1472 struct wifi_data *wifi = connman_device_get_data(device);
1473 struct autoscan_params *autoscan;
1477 if (!wifi || !wifi->autoscan)
1480 autoscan = wifi->autoscan;
1482 if (autoscan->timeout == 0 && autoscan->interval == 0)
1485 g_source_remove(autoscan->timeout);
1487 autoscan->timeout = 0;
1488 autoscan->interval = 0;
1490 connman_device_unref(device);
1493 static void stop_autoscan(struct connman_device *device)
1495 const struct wifi_data *wifi = connman_device_get_data(device);
1497 if (!wifi || !wifi->autoscan)
1500 reset_autoscan(device);
1502 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1505 static void check_p2p_technology(void)
1507 bool p2p_exists = false;
1510 for (list = iface_list; list; list = list->next) {
1511 struct wifi_data *w = list->data;
1514 g_supplicant_interface_has_p2p(w->interface))
1519 connman_technology_driver_unregister(&p2p_tech_driver);
1520 connman_peer_driver_unregister(&peer_driver);
1524 static void wifi_remove(struct connman_device *device)
1526 struct wifi_data *wifi = connman_device_get_data(device);
1528 DBG("device %p wifi %p", device, wifi);
1533 stop_autoscan(device);
1535 if (wifi->p2p_device)
1536 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1538 iface_list = g_list_remove(iface_list, wifi);
1540 check_p2p_technology();
1541 #if defined TIZEN_EXT_WIFI_MESH
1542 check_mesh_technology();
1545 remove_pending_wifi_device(wifi);
1547 if (wifi->p2p_find_timeout) {
1548 g_source_remove(wifi->p2p_find_timeout);
1549 connman_device_unref(wifi->device);
1552 if (wifi->p2p_connection_timeout)
1553 g_source_remove(wifi->p2p_connection_timeout);
1555 remove_networks(device, wifi);
1558 connman_device_set_powered(device, false);
1559 connman_device_set_data(device, NULL);
1560 connman_device_unref(wifi->device);
1561 connman_rtnl_remove_watch(wifi->watch);
1563 g_supplicant_interface_set_data(wifi->interface, NULL);
1565 g_supplicant_interface_cancel(wifi->interface);
1567 if (wifi->scan_params)
1568 g_supplicant_free_scan_params(wifi->scan_params);
1570 g_free(wifi->autoscan);
1571 g_free(wifi->identifier);
1575 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1579 for (iter = list; iter; iter = g_slist_next(iter)) {
1580 struct scan_ssid *scan_ssid = iter->data;
1582 if (ssid_len == scan_ssid->ssid_len &&
1583 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1590 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1591 int freq, GSupplicantScanParams *scan_data,
1592 int driver_max_scan_ssids, char *ssid_name)
1595 struct scan_ssid *scan_ssid;
1597 if ((driver_max_scan_ssids == 0 ||
1598 driver_max_scan_ssids > scan_data->num_ssids) &&
1599 (hex_ssid || raw_ssid)) {
1601 unsigned int j = 0, hex;
1604 size_t hex_ssid_len = strlen(hex_ssid);
1606 ssid = g_try_malloc0(hex_ssid_len / 2);
1610 for (i = 0; i < hex_ssid_len; i += 2) {
1611 sscanf(hex_ssid + i, "%02x", &hex);
1620 * If we have already added hidden AP to the list,
1621 * then do not do it again. This might happen if you have
1622 * used or are using multiple wifi cards, so in that case
1623 * you might have multiple service files for same AP.
1625 if (is_duplicate(scan_data->ssids, ssid, j)) {
1631 scan_ssid = g_try_new(struct scan_ssid, 1);
1638 memcpy(scan_ssid->ssid, ssid, j);
1639 scan_ssid->ssid_len = j;
1640 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1643 scan_data->num_ssids++;
1645 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1646 scan_data->num_ssids);
1653 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1655 if (!scan_data->freqs) {
1656 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1657 if (!scan_data->freqs) {
1658 g_slist_free_full(scan_data->ssids, g_free);
1662 scan_data->num_freqs = 1;
1663 scan_data->freqs[0] = freq;
1665 bool duplicate = false;
1667 /* Don't add duplicate entries */
1668 for (i = 0; i < scan_data->num_freqs; i++) {
1669 if (scan_data->freqs[i] == freq) {
1676 scan_data->num_freqs++;
1677 scan_data->freqs = g_try_realloc(scan_data->freqs,
1678 sizeof(uint16_t) * scan_data->num_freqs);
1679 if (!scan_data->freqs) {
1680 g_slist_free_full(scan_data->ssids, g_free);
1683 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1690 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1692 struct connman_config_entry **entries;
1698 int num_ssids = 0, add_param_failed = 0;
1700 services = connman_storage_get_services();
1701 for (i = 0; services && services[i]; i++) {
1702 if (strncmp(services[i], "wifi_", 5) != 0)
1705 keyfile = connman_storage_load_service(services[i]);
1709 value = g_key_file_get_boolean(keyfile,
1710 services[i], "Hidden", NULL);
1712 g_key_file_free(keyfile);
1716 value = g_key_file_get_boolean(keyfile,
1717 services[i], "Favorite", NULL);
1719 g_key_file_free(keyfile);
1723 #if defined TIZEN_EXT
1724 value = g_key_file_get_boolean(keyfile,
1725 services[i], "AutoConnect", NULL);
1727 g_key_file_free(keyfile);
1732 ssid = g_key_file_get_string(keyfile,
1733 services[i], "SSID", NULL);
1735 name = g_key_file_get_string(keyfile, services[i], "Name",
1738 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1746 g_key_file_free(keyfile);
1750 * Check if there are any hidden AP that needs to be provisioned.
1752 entries = connman_config_get_entries("wifi");
1753 for (i = 0; entries && entries[i]; i++) {
1756 if (!entries[i]->hidden)
1759 if (!entries[i]->ssid) {
1760 ssid = entries[i]->name;
1763 ssid = entries[i]->ssid;
1764 len = entries[i]->ssid_len;
1770 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1777 connman_config_free_entries(entries);
1779 if (add_param_failed > 0)
1780 DBG("Unable to scan %d out of %d SSIDs",
1781 add_param_failed, num_ssids);
1783 g_strfreev(services);
1788 static int get_hidden_connections_params(struct wifi_data *wifi,
1789 GSupplicantScanParams *scan_params)
1791 int driver_max_ssids, i;
1792 GSupplicantScanParams *orig_params;
1795 * Scan hidden networks so that we can autoconnect to them.
1796 * We will assume 1 as a default number of ssid to scan.
1798 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1800 if (driver_max_ssids == 0)
1801 driver_max_ssids = 1;
1803 DBG("max ssids %d", driver_max_ssids);
1805 if (!wifi->scan_params) {
1806 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1807 if (!wifi->scan_params)
1810 if (get_hidden_connections(wifi->scan_params) == 0) {
1811 g_supplicant_free_scan_params(wifi->scan_params);
1812 wifi->scan_params = NULL;
1818 orig_params = wifi->scan_params;
1820 /* Let's transfer driver_max_ssids params */
1821 for (i = 0; i < driver_max_ssids; i++) {
1822 struct scan_ssid *ssid;
1824 if (!wifi->scan_params->ssids)
1827 ssid = orig_params->ssids->data;
1828 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1829 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1833 scan_params->num_ssids = i;
1834 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1836 scan_params->freqs = g_memdup(orig_params->freqs,
1837 sizeof(uint16_t) * orig_params->num_freqs);
1838 if (!scan_params->freqs)
1841 scan_params->num_freqs = orig_params->num_freqs;
1846 orig_params->num_ssids -= scan_params->num_ssids;
1848 return scan_params->num_ssids;
1851 g_slist_free_full(scan_params->ssids, g_free);
1852 g_supplicant_free_scan_params(wifi->scan_params);
1853 wifi->scan_params = NULL;
1858 static int throw_wifi_scan(struct connman_device *device,
1859 GSupplicantInterfaceCallback callback)
1861 struct wifi_data *wifi = connman_device_get_data(device);
1867 DBG("device %p %p", device, wifi->interface);
1869 if (wifi->tethering)
1871 #if defined TIZEN_EXT
1872 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1874 if (connman_device_get_scanning(device))
1878 connman_device_ref(device);
1880 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1883 connman_device_set_scanning(device,
1884 CONNMAN_SERVICE_TYPE_WIFI, true);
1886 connman_device_unref(device);
1891 static void hidden_free(struct hidden_params *hidden)
1896 if (hidden->scan_params)
1897 g_supplicant_free_scan_params(hidden->scan_params);
1898 g_free(hidden->identity);
1899 g_free(hidden->passphrase);
1900 g_free(hidden->security);
1904 #if defined TIZEN_EXT
1905 static void service_state_changed(struct connman_service *service,
1906 enum connman_service_state state);
1908 static int network_connect(struct connman_network *network);
1910 static struct connman_notifier notifier = {
1912 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1913 .service_state_changed = service_state_changed,
1916 static void service_state_changed(struct connman_service *service,
1917 enum connman_service_state state)
1919 enum connman_service_type type;
1921 type = connman_service_get_type(service);
1922 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1925 DBG("service %p state %d", service, state);
1928 case CONNMAN_SERVICE_STATE_READY:
1929 case CONNMAN_SERVICE_STATE_ONLINE:
1930 case CONNMAN_SERVICE_STATE_FAILURE:
1931 connman_notifier_unregister(¬ifier);
1932 is_wifi_notifier_registered = FALSE;
1934 __connman_device_request_scan(type);
1943 static void scan_callback(int result, GSupplicantInterface *interface,
1946 struct connman_device *device = user_data;
1947 struct wifi_data *wifi = connman_device_get_data(device);
1950 DBG("result %d wifi %p", result, wifi);
1953 if (wifi->hidden && !wifi->postpone_hidden) {
1954 connman_network_clear_hidden(wifi->hidden->user_data);
1955 hidden_free(wifi->hidden);
1956 wifi->hidden = NULL;
1959 if (wifi->scan_params) {
1960 g_supplicant_free_scan_params(wifi->scan_params);
1961 wifi->scan_params = NULL;
1966 connman_device_reset_scanning(device);
1968 /* User is connecting to a hidden AP, let's wait for finished event */
1969 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1970 GSupplicantScanParams *scan_params;
1973 wifi->postpone_hidden = false;
1974 scan_params = wifi->hidden->scan_params;
1975 wifi->hidden->scan_params = NULL;
1977 reset_autoscan(device);
1979 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1980 scan_callback, device);
1984 /* On error, let's recall scan_callback, which will cleanup */
1985 return scan_callback(ret, interface, user_data);
1988 #if defined TIZEN_EXT
1989 if (wifi && wifi->allow_full_scan) {
1991 DBG("Trigger Full Channel Scan");
1992 wifi->allow_full_scan = FALSE;
1994 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1995 scan_callback, device);
1999 /* On error, let's recall scan_callback, which will cleanup */
2000 return scan_callback(ret, interface, user_data);
2004 scanning = connman_device_get_scanning(device);
2006 connman_device_set_scanning(device,
2007 CONNMAN_SERVICE_TYPE_WIFI, false);
2009 if (result != -ENOLINK)
2010 #if defined TIZEN_EXT
2013 start_autoscan(device);
2016 * If we are here then we were scanning; however, if we are
2017 * also mid-flight disabling the interface, then wifi_disable
2018 * has already cleared the device scanning state and
2019 * unreferenced the device, obviating the need to do it here.
2023 connman_device_unref(device);
2025 #if defined TIZEN_EXT
2026 if (wifi && wifi->scan_pending_network && result != -EIO) {
2027 network_connect(wifi->scan_pending_network);
2028 wifi->scan_pending_network = NULL;
2029 connman_network_set_connecting(wifi->network);
2032 if (is_wifi_notifier_registered != true &&
2033 wifi_first_scan == true && found_with_first_scan == true) {
2034 wifi_first_scan = false;
2035 found_with_first_scan = false;
2037 connman_notifier_register(¬ifier);
2038 is_wifi_notifier_registered = true;
2043 static void scan_callback_hidden(int result,
2044 GSupplicantInterface *interface, void *user_data)
2046 struct connman_device *device = user_data;
2047 struct wifi_data *wifi = connman_device_get_data(device);
2048 GSupplicantScanParams *scan_params;
2051 DBG("result %d wifi %p", result, wifi);
2056 /* User is trying to connect to a hidden AP */
2057 if (wifi->hidden && wifi->postpone_hidden)
2060 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2064 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2065 ret = g_supplicant_interface_scan(wifi->interface,
2067 scan_callback_hidden,
2073 g_supplicant_free_scan_params(scan_params);
2076 scan_callback(result, interface, user_data);
2079 static gboolean autoscan_timeout(gpointer data)
2081 struct connman_device *device = data;
2082 struct wifi_data *wifi = connman_device_get_data(device);
2083 struct autoscan_params *autoscan;
2089 autoscan = wifi->autoscan;
2091 if (autoscan->interval <= 0) {
2092 interval = autoscan->base;
2095 interval = autoscan->interval * autoscan->base;
2097 #if defined TIZEN_EXT
2098 if (autoscan->interval >= autoscan->limit)
2100 if (interval > autoscan->limit)
2102 interval = autoscan->limit;
2104 throw_wifi_scan(wifi->device, scan_callback_hidden);
2107 DBG("interval %d", interval);
2109 autoscan->interval = interval;
2111 autoscan->timeout = g_timeout_add_seconds(interval,
2112 autoscan_timeout, device);
2117 static void start_autoscan(struct connman_device *device)
2119 struct wifi_data *wifi = connman_device_get_data(device);
2120 struct autoscan_params *autoscan;
2127 if (wifi->p2p_device)
2130 if (wifi->connected)
2133 autoscan = wifi->autoscan;
2137 if (autoscan->timeout > 0 || autoscan->interval > 0)
2140 connman_device_ref(device);
2142 autoscan_timeout(device);
2145 static struct autoscan_params *parse_autoscan_params(const char *params)
2147 struct autoscan_params *autoscan;
2152 DBG("Emulating autoscan");
2154 list_params = g_strsplit(params, ":", 0);
2155 if (list_params == 0)
2158 if (g_strv_length(list_params) < 3) {
2159 g_strfreev(list_params);
2163 base = atoi(list_params[1]);
2164 limit = atoi(list_params[2]);
2166 g_strfreev(list_params);
2168 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2170 DBG("Could not allocate memory for autoscan");
2174 DBG("base %d - limit %d", base, limit);
2175 autoscan->base = base;
2176 autoscan->limit = limit;
2181 static void setup_autoscan(struct wifi_data *wifi)
2183 if (!wifi->autoscan)
2184 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2186 start_autoscan(wifi->device);
2189 static void finalize_interface_creation(struct wifi_data *wifi)
2191 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2193 if (!wifi->device) {
2194 connman_error("WiFi device not set");
2198 connman_device_set_powered(wifi->device, true);
2200 if (!connman_setting_get_bool("BackgroundScanning"))
2203 if (wifi->p2p_device)
2206 setup_autoscan(wifi);
2209 static void interface_create_callback(int result,
2210 GSupplicantInterface *interface,
2213 struct wifi_data *wifi = user_data;
2215 DBG("result %d ifname %s, wifi %p", result,
2216 g_supplicant_interface_get_ifname(interface),
2219 if (result < 0 || !wifi)
2222 wifi->interface = interface;
2223 g_supplicant_interface_set_data(interface, wifi);
2225 if (g_supplicant_interface_get_ready(interface)) {
2226 wifi->interface_ready = true;
2227 finalize_interface_creation(wifi);
2231 static int wifi_enable(struct connman_device *device)
2233 struct wifi_data *wifi = connman_device_get_data(device);
2236 const char *driver = connman_option_get_string("wifi");
2239 DBG("device %p %p", device, wifi);
2241 index = connman_device_get_index(device);
2242 if (!wifi || index < 0)
2245 if (is_p2p_connecting())
2246 return -EINPROGRESS;
2248 interface = connman_inet_ifname(index);
2249 ret = g_supplicant_interface_create(interface, driver, NULL,
2250 interface_create_callback,
2257 return -EINPROGRESS;
2260 static int wifi_disable(struct connman_device *device)
2262 struct wifi_data *wifi = connman_device_get_data(device);
2265 DBG("device %p wifi %p", device, wifi);
2270 wifi->connected = false;
2271 wifi->disconnecting = false;
2273 if (wifi->pending_network)
2274 wifi->pending_network = NULL;
2276 stop_autoscan(device);
2278 if (wifi->p2p_find_timeout) {
2279 g_source_remove(wifi->p2p_find_timeout);
2280 wifi->p2p_find_timeout = 0;
2281 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2282 connman_device_unref(wifi->device);
2285 /* In case of a user scan, device is still referenced */
2286 if (connman_device_get_scanning(device)) {
2287 connman_device_set_scanning(device,
2288 CONNMAN_SERVICE_TYPE_WIFI, false);
2289 connman_device_unref(wifi->device);
2292 remove_networks(device, wifi);
2295 #if defined TIZEN_EXT
2296 wifi->scan_pending_network = NULL;
2298 if (is_wifi_notifier_registered == true) {
2299 connman_notifier_unregister(¬ifier);
2300 is_wifi_notifier_registered = false;
2304 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2308 return -EINPROGRESS;
2311 struct last_connected {
2317 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
2319 GTimeVal *aval = (GTimeVal *)a;
2320 GTimeVal *bval = (GTimeVal *)b;
2322 /* Note that the sort order is descending */
2323 if (aval->tv_sec < bval->tv_sec)
2326 if (aval->tv_sec > bval->tv_sec)
2332 static void free_entry(gpointer data)
2334 struct last_connected *entry = data;
2336 g_free(entry->ssid);
2340 static int get_latest_connections(int max_ssids,
2341 GSupplicantScanParams *scan_data)
2343 GSequenceIter *iter;
2344 GSequence *latest_list;
2345 struct last_connected *entry;
2354 latest_list = g_sequence_new(free_entry);
2358 services = connman_storage_get_services();
2359 for (i = 0; services && services[i]; i++) {
2360 if (strncmp(services[i], "wifi_", 5) != 0)
2363 keyfile = connman_storage_load_service(services[i]);
2367 str = g_key_file_get_string(keyfile,
2368 services[i], "Favorite", NULL);
2369 if (!str || g_strcmp0(str, "true")) {
2371 g_key_file_free(keyfile);
2376 str = g_key_file_get_string(keyfile,
2377 services[i], "AutoConnect", NULL);
2378 if (!str || g_strcmp0(str, "true")) {
2380 g_key_file_free(keyfile);
2385 str = g_key_file_get_string(keyfile,
2386 services[i], "Modified", NULL);
2388 g_key_file_free(keyfile);
2391 g_time_val_from_iso8601(str, &modified);
2394 ssid = g_key_file_get_string(keyfile,
2395 services[i], "SSID", NULL);
2397 freq = g_key_file_get_integer(keyfile, services[i],
2400 entry = g_try_new(struct last_connected, 1);
2402 g_sequence_free(latest_list);
2403 g_key_file_free(keyfile);
2409 entry->modified = modified;
2412 g_sequence_insert_sorted(latest_list, entry,
2418 g_key_file_free(keyfile);
2421 g_strfreev(services);
2423 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2425 iter = g_sequence_get_begin_iter(latest_list);
2427 for (i = 0; i < num_ssids; i++) {
2428 entry = g_sequence_get(iter);
2430 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2431 entry->modified.tv_sec);
2433 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2434 max_ssids, entry->ssid);
2436 iter = g_sequence_iter_next(iter);
2439 g_sequence_free(latest_list);
2443 static int wifi_scan_simple(struct connman_device *device)
2445 reset_autoscan(device);
2447 return throw_wifi_scan(device, scan_callback_hidden);
2450 static gboolean p2p_find_stop(gpointer data)
2452 struct connman_device *device = data;
2453 struct wifi_data *wifi = connman_device_get_data(device);
2458 wifi->p2p_find_timeout = 0;
2460 g_supplicant_interface_p2p_stop_find(wifi->interface);
2463 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2465 connman_device_unref(device);
2466 reset_autoscan(device);
2471 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2474 struct connman_device *device = user_data;
2475 struct wifi_data *wifi = connman_device_get_data(device);
2477 DBG("result %d wifi %p", result, wifi);
2482 if (wifi->p2p_find_timeout) {
2483 g_source_remove(wifi->p2p_find_timeout);
2484 wifi->p2p_find_timeout = 0;
2490 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2491 p2p_find_stop, device);
2492 if (!wifi->p2p_find_timeout)
2497 p2p_find_stop(device);
2500 static int p2p_find(struct connman_device *device)
2502 struct wifi_data *wifi;
2507 if (!p2p_technology)
2510 wifi = connman_device_get_data(device);
2512 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2515 reset_autoscan(device);
2516 connman_device_ref(device);
2518 ret = g_supplicant_interface_p2p_find(wifi->interface,
2519 p2p_find_callback, device);
2521 connman_device_unref(device);
2522 start_autoscan(device);
2524 connman_device_set_scanning(device,
2525 CONNMAN_SERVICE_TYPE_P2P, true);
2531 #if defined TIZEN_EXT
2532 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2535 struct connman_device *device = user_data;
2536 struct wifi_data *wifi = connman_device_get_data(device);
2539 DBG("result %d wifi %p", result, wifi);
2541 if (wifi && wifi->scan_params) {
2542 g_supplicant_free_scan_params(wifi->scan_params);
2543 wifi->scan_params = NULL;
2546 scanning = connman_device_get_scanning(device);
2548 connman_device_set_scanning(device,
2549 CONNMAN_SERVICE_TYPE_WIFI, false);
2550 connman_device_unref(device);
2554 static int wifi_specific_scan(enum connman_service_type type,
2555 struct connman_device *device, int scan_type,
2556 GSList *specific_scan_list, void *user_data)
2558 GSList *list = NULL;
2560 struct wifi_data *wifi = connman_device_get_data(device);
2561 GSupplicantScanParams *scan_params = NULL;
2562 struct scan_ssid *scan_ssid = NULL;
2571 if (wifi->p2p_device)
2574 if (type == CONNMAN_SERVICE_TYPE_P2P)
2575 return p2p_find(device);
2577 if (wifi->tethering)
2580 scanning = connman_device_get_scanning(device);
2584 DBG("scan_type: %d", scan_type);
2585 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2586 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2588 DBG("Failed to allocate memory.");
2592 for (list = specific_scan_list; list; list = list->next) {
2593 ssid = (char *)list->data;
2594 int ssid_len = strlen(ssid);
2596 scan_ssid = g_try_new0(struct scan_ssid, 1);
2598 DBG("Failed to allocate memory.");
2599 g_supplicant_free_scan_params(scan_params);
2603 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2604 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2605 scan_ssid->ssid_len = ssid_len;
2606 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2609 scan_params->num_ssids = count;
2611 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2613 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2615 DBG("Failed to allocate memory.");
2619 guint num_freqs = g_slist_length(specific_scan_list);
2620 DBG("num_freqs: %d", num_freqs);
2622 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2623 if (!scan_params->freqs) {
2624 DBG("Failed to allocate memory.");
2625 g_free(scan_params);
2630 for (list = specific_scan_list; list; list = list->next) {
2631 freq = (int)list->data;
2633 scan_params->freqs[count] = freq;
2634 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2637 scan_params->num_freqs = count;
2639 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2640 int freq_count, ap_count;
2641 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2643 DBG("Failed to allocate memory.");
2647 guint size = g_slist_length(specific_scan_list);
2649 scan_params->freqs = g_try_new0(uint16_t, size/2);
2650 if (!scan_params->freqs) {
2651 DBG("Failed to allocate memory.");
2652 g_free(scan_params);
2656 ap_count = freq_count = 0;
2657 for (list = specific_scan_list; list; list = list->next) {
2658 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2659 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2660 int ssid_len = strlen(ssid);
2662 scan_ssid = g_try_new0(struct scan_ssid, 1);
2664 DBG("Failed to allocate memory.");
2665 g_supplicant_free_scan_params(scan_params);
2669 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2670 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2671 scan_ssid->ssid_len = ssid_len;
2672 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2676 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2677 scan_params->freqs[freq_count] = freq;
2678 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2682 scan_params->num_ssids = ap_count;
2683 scan_params->num_freqs = freq_count;
2685 DBG("Invalid scan");
2689 reset_autoscan(device);
2690 connman_device_ref(device);
2692 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2693 specific_scan_callback, device);
2696 connman_device_set_scanning(device,
2697 CONNMAN_SERVICE_TYPE_WIFI, true);
2699 g_supplicant_free_scan_params(scan_params);
2700 connman_device_unref(device);
2707 #if defined TIZEN_EXT_WIFI_MESH
2708 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2711 struct connman_device *device = user_data;
2712 struct wifi_data *wifi = connman_device_get_data(device);
2715 DBG("result %d wifi %p", result, wifi);
2717 scanning = connman_device_get_scanning(device);
2719 connman_device_set_scanning(device,
2720 CONNMAN_SERVICE_TYPE_MESH, false);
2723 connman_device_unref(device);
2726 static int mesh_scan(struct connman_device *device)
2728 struct wifi_data *wifi;
2729 struct wifi_mesh_info *mesh_info;
2734 wifi = connman_device_get_data(device);
2736 if (!wifi->mesh_interface)
2739 mesh_info = wifi->mesh_info;
2740 reset_autoscan(device);
2741 connman_device_ref(device);
2743 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2744 mesh_scan_callback, device);
2746 connman_device_unref(device);
2748 connman_device_set_scanning(device,
2749 CONNMAN_SERVICE_TYPE_MESH, true);
2754 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2757 struct connman_device *device = user_data;
2758 struct wifi_data *wifi = connman_device_get_data(device);
2760 DBG("result %d wifi %p", result, wifi);
2762 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2765 static int mesh_abort_scan(enum connman_service_type type,
2766 struct connman_device *device)
2768 struct wifi_data *wifi = connman_device_get_data(device);
2769 struct wifi_mesh_info *mesh_info;
2773 if (!wifi || !wifi->mesh_interface)
2776 if (type != CONNMAN_SERVICE_TYPE_MESH)
2779 mesh_info = wifi->mesh_info;
2781 scanning = connman_device_get_scanning(device);
2785 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2786 abort_scan_callback, device);
2791 static int mesh_specific_scan(enum connman_service_type type,
2792 struct connman_device *device, const char *ssid,
2793 unsigned int freq, void *user_data)
2795 struct wifi_data *wifi = connman_device_get_data(device);
2796 GSupplicantScanParams *scan_params = NULL;
2797 struct wifi_mesh_info *mesh_info;
2798 struct scan_ssid *scan_ssid;
2802 if (!wifi || !wifi->mesh_interface)
2805 if (type != CONNMAN_SERVICE_TYPE_MESH)
2808 if (wifi->p2p_device)
2811 mesh_info = wifi->mesh_info;
2813 scanning = connman_device_get_scanning(device);
2817 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2821 scan_ssid = g_try_new(struct scan_ssid, 1);
2823 g_free(scan_params);
2827 scan_ssid->ssid_len = strlen(ssid);
2828 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2829 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2830 scan_params->num_ssids = 1;
2832 scan_params->freqs = g_try_new(uint16_t, 1);
2833 if (!scan_params->freqs) {
2834 g_slist_free_full(scan_params->ssids, g_free);
2835 g_free(scan_params);
2839 scan_params->freqs[0] = freq;
2840 scan_params->num_freqs = 1;
2842 reset_autoscan(device);
2843 connman_device_ref(device);
2845 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2846 mesh_scan_callback, device);
2849 connman_device_set_scanning(device,
2850 CONNMAN_SERVICE_TYPE_MESH, true);
2852 g_supplicant_free_scan_params(scan_params);
2853 connman_device_unref(device);
2861 * Note that the hidden scan is only used when connecting to this specific
2862 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2864 static int wifi_scan(enum connman_service_type type,
2865 struct connman_device *device,
2866 const char *ssid, unsigned int ssid_len,
2867 const char *identity, const char* passphrase,
2868 const char *security, void *user_data)
2870 struct wifi_data *wifi = connman_device_get_data(device);
2871 GSupplicantScanParams *scan_params = NULL;
2872 struct scan_ssid *scan_ssid;
2873 struct hidden_params *hidden;
2875 int driver_max_ssids = 0;
2882 if (wifi->p2p_device)
2885 if (wifi->tethering)
2888 if (type == CONNMAN_SERVICE_TYPE_P2P)
2889 return p2p_find(device);
2891 #if defined TIZEN_EXT_WIFI_MESH
2892 if (type == CONNMAN_SERVICE_TYPE_MESH)
2893 return mesh_scan(device);
2896 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2898 scanning = connman_device_get_scanning(device);
2900 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2904 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2906 DBG("max ssids %d", driver_max_ssids);
2907 if (driver_max_ssids == 0)
2908 return wifi_scan_simple(device);
2912 if (scanning && wifi->hidden && wifi->postpone_hidden)
2918 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2923 scan_ssid = g_try_new(struct scan_ssid, 1);
2925 g_free(scan_params);
2929 memcpy(scan_ssid->ssid, ssid, ssid_len);
2930 scan_ssid->ssid_len = ssid_len;
2931 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2933 scan_params->num_ssids = 1;
2935 hidden = g_try_new0(struct hidden_params, 1);
2937 g_supplicant_free_scan_params(scan_params);
2942 hidden_free(wifi->hidden);
2943 wifi->hidden = NULL;
2946 memcpy(hidden->ssid, ssid, ssid_len);
2947 hidden->ssid_len = ssid_len;
2948 hidden->identity = g_strdup(identity);
2949 hidden->passphrase = g_strdup(passphrase);
2950 hidden->security = g_strdup(security);
2951 hidden->user_data = user_data;
2952 wifi->hidden = hidden;
2955 /* Let's keep this active scan for later,
2956 * when current scan will be over. */
2957 wifi->postpone_hidden = TRUE;
2958 hidden->scan_params = scan_params;
2962 } else if (wifi->connected) {
2963 g_supplicant_free_scan_params(scan_params);
2964 return wifi_scan_simple(device);
2966 ret = get_latest_connections(driver_max_ssids, scan_params);
2968 g_supplicant_free_scan_params(scan_params);
2969 return wifi_scan_simple(device);
2973 connman_device_ref(device);
2975 reset_autoscan(device);
2977 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2978 scan_callback, device);
2981 connman_device_set_scanning(device,
2982 CONNMAN_SERVICE_TYPE_WIFI, true);
2983 #if defined TIZEN_EXT
2984 /*To allow the Full Scan after ssid based scan, set the flag here
2985 It is required because Tizen does not use the ConnMan specific
2986 backgroung Scan feature.Tizen has added the BG Scan feature in
2987 net-config. To sync with up ConnMan, we need to issue the Full Scan
2988 after SSID specific scan.*/
2989 wifi->allow_full_scan = TRUE;
2992 g_supplicant_free_scan_params(scan_params);
2993 connman_device_unref(device);
2996 hidden_free(wifi->hidden);
2997 wifi->hidden = NULL;
3004 static void wifi_regdom_callback(int result,
3008 struct connman_device *device = user_data;
3010 connman_device_regdom_notify(device, result, alpha2);
3012 connman_device_unref(device);
3015 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3017 struct wifi_data *wifi = connman_device_get_data(device);
3023 connman_device_ref(device);
3025 ret = g_supplicant_interface_set_country(wifi->interface,
3026 wifi_regdom_callback,
3029 connman_device_unref(device);
3034 static struct connman_device_driver wifi_ng_driver = {
3036 .type = CONNMAN_DEVICE_TYPE_WIFI,
3037 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3038 .probe = wifi_probe,
3039 .remove = wifi_remove,
3040 .enable = wifi_enable,
3041 .disable = wifi_disable,
3043 .set_regdom = wifi_set_regdom,
3044 #if defined TIZEN_EXT
3045 .specific_scan = wifi_specific_scan,
3047 #if defined TIZEN_EXT_WIFI_MESH
3048 .abort_scan = mesh_abort_scan,
3049 .mesh_specific_scan = mesh_specific_scan,
3053 static void system_ready(void)
3057 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3058 connman_error("Failed to register WiFi driver");
3061 static void system_killed(void)
3065 connman_device_driver_unregister(&wifi_ng_driver);
3068 static int network_probe(struct connman_network *network)
3070 DBG("network %p", network);
3075 static void network_remove(struct connman_network *network)
3077 struct connman_device *device = connman_network_get_device(network);
3078 struct wifi_data *wifi;
3080 DBG("network %p", network);
3082 wifi = connman_device_get_data(device);
3086 if (wifi->network != network)
3089 wifi->network = NULL;
3091 #if defined TIZEN_EXT
3092 wifi->disconnecting = false;
3094 if (wifi->pending_network == network)
3095 wifi->pending_network = NULL;
3097 if (wifi->scan_pending_network == network)
3098 wifi->scan_pending_network = NULL;
3102 static void connect_callback(int result, GSupplicantInterface *interface,
3105 #if defined TIZEN_EXT
3107 struct wifi_data *wifi;
3109 struct connman_network *network = user_data;
3111 DBG("network %p result %d", network, result);
3113 #if defined TIZEN_EXT
3114 set_connman_bssid(RESET_BSSID, NULL);
3116 for (list = iface_list; list; list = list->next) {
3119 if (wifi && wifi->network == network)
3123 /* wifi_data may be invalid because wifi is already disabled */
3128 if (result == -ENOKEY) {
3129 connman_network_set_error(network,
3130 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3131 } else if (result < 0) {
3132 connman_network_set_error(network,
3133 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3136 connman_network_unref(network);
3139 static GSupplicantSecurity network_security(const char *security)
3141 if (g_str_equal(security, "none"))
3142 return G_SUPPLICANT_SECURITY_NONE;
3143 else if (g_str_equal(security, "wep"))
3144 return G_SUPPLICANT_SECURITY_WEP;
3145 else if (g_str_equal(security, "psk"))
3146 return G_SUPPLICANT_SECURITY_PSK;
3147 else if (g_str_equal(security, "wpa"))
3148 return G_SUPPLICANT_SECURITY_PSK;
3149 else if (g_str_equal(security, "rsn"))
3150 return G_SUPPLICANT_SECURITY_PSK;
3151 else if (g_str_equal(security, "ieee8021x"))
3152 return G_SUPPLICANT_SECURITY_IEEE8021X;
3153 #if defined TIZEN_EXT
3154 else if (g_str_equal(security, "ft_psk") == TRUE)
3155 return G_SUPPLICANT_SECURITY_FT_PSK;
3156 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3157 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3160 return G_SUPPLICANT_SECURITY_UNKNOWN;
3163 #if defined TIZEN_EXT
3164 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3166 if (security == NULL)
3167 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3169 if (g_str_equal(security, "FT") == TRUE)
3170 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3171 else if (g_str_equal(security, "CCKM") == TRUE)
3172 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3174 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3178 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3180 const char *security;
3181 #if defined TIZEN_EXT
3182 const void *ssid_data;
3185 memset(ssid, 0, sizeof(*ssid));
3186 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3187 #if defined TIZEN_EXT
3188 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3190 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3195 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3197 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3200 ssid->scan_ssid = 1;
3201 security = connman_network_get_string(network, "WiFi.Security");
3202 ssid->security = network_security(security);
3203 ssid->passphrase = connman_network_get_string(network,
3205 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3208 * If our private key password is unset,
3209 * we use the supplied passphrase. That is needed
3210 * for PEAP where 2 passphrases (identity and client
3211 * cert may have to be provided.
3213 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3214 connman_network_set_string(network,
3215 "WiFi.PrivateKeyPassphrase",
3217 /* We must have an identity for both PEAP and TLS */
3218 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3220 /* Use agent provided identity as a fallback */
3221 if (!ssid->identity || strlen(ssid->identity) == 0)
3222 ssid->identity = connman_network_get_string(network,
3223 "WiFi.AgentIdentity");
3225 ssid->anonymous_identity = connman_network_get_string(network,
3226 "WiFi.AnonymousIdentity");
3227 ssid->ca_cert_path = connman_network_get_string(network,
3229 ssid->subject_match = connman_network_get_string(network,
3230 "WiFi.SubjectMatch");
3231 ssid->altsubject_match = connman_network_get_string(network,
3232 "WiFi.AltSubjectMatch");
3233 ssid->domain_suffix_match = connman_network_get_string(network,
3234 "WiFi.DomainSuffixMatch");
3235 ssid->domain_match = connman_network_get_string(network,
3236 "WiFi.DomainMatch");
3237 ssid->client_cert_path = connman_network_get_string(network,
3238 "WiFi.ClientCertFile");
3239 ssid->private_key_path = connman_network_get_string(network,
3240 "WiFi.PrivateKeyFile");
3241 ssid->private_key_passphrase = connman_network_get_string(network,
3242 "WiFi.PrivateKeyPassphrase");
3243 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3245 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3246 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3248 #if defined TIZEN_EXT
3249 ssid->bssid = connman_network_get_bssid(network);
3251 ssid->eap_keymgmt = network_eap_keymgmt(
3252 connman_network_get_string(network, "WiFi.KeymgmtType"));
3253 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3255 if(g_strcmp0(ssid->eap, "fast") == 0)
3256 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3258 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3259 ssid->bssid_for_connect_len = 6;
3260 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3261 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3262 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3263 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3264 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3266 ssid->freq = connman_network_get_frequency(network);
3270 if (connman_setting_get_bool("BackgroundScanning"))
3271 ssid->bgscan = BGSCAN_DEFAULT;
3274 static int network_connect(struct connman_network *network)
3276 struct connman_device *device = connman_network_get_device(network);
3277 struct wifi_data *wifi;
3278 GSupplicantInterface *interface;
3279 GSupplicantSSID *ssid;
3281 DBG("network %p", network);
3286 wifi = connman_device_get_data(device);
3290 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3294 interface = wifi->interface;
3296 ssid_init(ssid, network);
3298 if (wifi->disconnecting) {
3299 wifi->pending_network = network;
3300 #if defined TIZEN_EXT
3305 wifi->network = connman_network_ref(network);
3307 #if defined TIZEN_EXT
3308 wifi->scan_pending_network = NULL;
3311 return g_supplicant_interface_connect(interface, ssid,
3312 connect_callback, network);
3315 return -EINPROGRESS;
3318 static void disconnect_callback(int result, GSupplicantInterface *interface,
3321 #if defined TIZEN_EXT
3323 struct wifi_data *wifi;
3324 struct connman_network *network = user_data;
3326 DBG("network %p result %d", network, result);
3328 for (list = iface_list; list; list = list->next) {
3331 if (wifi->network == NULL && wifi->disconnecting == true)
3332 wifi->disconnecting = false;
3334 if (wifi->network == network)
3338 /* wifi_data may be invalid because wifi is already disabled */
3343 struct wifi_data *wifi = user_data;
3346 DBG("result %d supplicant interface %p wifi %p",
3347 result, interface, wifi);
3349 if (result == -ECONNABORTED) {
3350 DBG("wifi interface no longer available");
3354 if (wifi->network) {
3355 connman_network_set_connected(wifi->network, false);
3356 wifi->network = NULL;
3359 wifi->disconnecting = false;
3360 wifi->connected = false;
3362 if (wifi->pending_network) {
3363 network_connect(wifi->pending_network);
3364 wifi->pending_network = NULL;
3367 start_autoscan(wifi->device);
3370 static int network_disconnect(struct connman_network *network)
3372 struct connman_device *device = connman_network_get_device(network);
3373 struct wifi_data *wifi;
3375 #if defined TIZEN_EXT
3376 struct connman_service *service;
3379 DBG("network %p", network);
3381 wifi = connman_device_get_data(device);
3382 if (!wifi || !wifi->interface)
3385 #if defined TIZEN_EXT
3386 if (connman_network_get_associating(network) == true) {
3387 connman_network_clear_associating(network);
3388 connman_network_set_bool(network, "WiFi.UseWPS", false);
3390 service = connman_service_lookup_from_network(network);
3392 if (service != NULL &&
3393 (__connman_service_is_connected_state(service,
3394 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3395 __connman_service_is_connected_state(service,
3396 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3397 (connman_service_get_favorite(service) == false))
3398 __connman_service_set_passphrase(service, NULL);
3401 if (wifi->pending_network == network)
3402 wifi->pending_network = NULL;
3404 if (wifi->scan_pending_network == network)
3405 wifi->scan_pending_network = NULL;
3408 connman_network_set_associating(network, false);
3410 if (wifi->disconnecting)
3413 wifi->disconnecting = true;
3415 #if defined TIZEN_EXT
3416 err = g_supplicant_interface_disconnect(wifi->interface,
3417 disconnect_callback, network);
3419 err = g_supplicant_interface_disconnect(wifi->interface,
3420 disconnect_callback, wifi);
3424 wifi->disconnecting = false;
3429 #if defined TIZEN_EXT
3430 static unsigned int automaxspeed_timeout = 0;
3432 static void set_connection_mode(struct connman_network *network,
3435 ieee80211_modes_e phy_mode;
3436 connection_mode_e conn_mode;
3438 phy_mode = connman_network_get_phy_mode(network);
3440 case IEEE80211_MODE_B:
3441 if (linkspeed > 0 && linkspeed <= 11)
3442 conn_mode = CONNECTION_MODE_IEEE80211B;
3444 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3447 case IEEE80211_MODE_BG:
3448 if (linkspeed > 0 && linkspeed <= 11)
3449 conn_mode = CONNECTION_MODE_IEEE80211B;
3450 else if (linkspeed > 11 && linkspeed <= 54)
3451 conn_mode = CONNECTION_MODE_IEEE80211G;
3453 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3456 case IEEE80211_MODE_BGN:
3457 if (linkspeed > 0 && linkspeed <= 11)
3458 conn_mode = CONNECTION_MODE_IEEE80211B;
3459 else if (linkspeed > 11 && linkspeed <= 54)
3460 conn_mode = CONNECTION_MODE_IEEE80211G;
3461 else if (linkspeed > 54 && linkspeed <= 450)
3462 conn_mode = CONNECTION_MODE_IEEE80211N;
3464 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3467 case IEEE80211_MODE_A:
3468 if (linkspeed > 0 && linkspeed <= 54)
3469 conn_mode = CONNECTION_MODE_IEEE80211A;
3471 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3474 case IEEE80211_MODE_AN:
3475 if (linkspeed > 0 && linkspeed <= 54)
3476 conn_mode = CONNECTION_MODE_IEEE80211A;
3477 else if (linkspeed > 54 && linkspeed <= 450)
3478 conn_mode = CONNECTION_MODE_IEEE80211N;
3480 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3483 case IEEE80211_MODE_ANAC:
3484 if (linkspeed > 0 && linkspeed <= 54)
3485 conn_mode = CONNECTION_MODE_IEEE80211A;
3486 else if (linkspeed > 54 && linkspeed <= 450)
3487 conn_mode = CONNECTION_MODE_IEEE80211N;
3488 else if (linkspeed > 450 && linkspeed <= 1300)
3489 conn_mode = CONNECTION_MODE_IEEE80211AC;
3491 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3495 conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
3499 DBG("connection mode(%d)", conn_mode);
3500 connman_network_set_connection_mode(network, conn_mode);
3503 static void signalpoll_callback(int result, int maxspeed, void *user_data)
3505 struct connman_network *network = user_data;
3508 DBG("Failed to get maxspeed from signalpoll !");
3512 DBG("maxspeed = %d", maxspeed);
3514 connman_network_set_maxspeed(network, maxspeed);
3515 set_connection_mode(network, maxspeed);
3519 static int network_signalpoll(struct connman_network *network)
3521 struct connman_device *device = connman_network_get_device(network);
3522 struct wifi_data *wifi;
3523 GSupplicantInterface *interface;
3525 DBG("network %p", network);
3526 wifi = connman_device_get_data(device);
3531 interface = wifi->interface;
3533 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3536 static gboolean autosignalpoll_timeout(gpointer data)
3538 struct connman_network *network = data;
3541 automaxspeed_timeout = 0;
3542 ret = network_signalpoll(network);
3545 DBG("Fail to get max speed !!");
3549 automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, network);
3555 static struct connman_network_driver network_driver = {
3557 .type = CONNMAN_NETWORK_TYPE_WIFI,
3558 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3559 .probe = network_probe,
3560 .remove = network_remove,
3561 .connect = network_connect,
3562 .disconnect = network_disconnect,
3565 static void interface_added(GSupplicantInterface *interface)
3567 const char *ifname = g_supplicant_interface_get_ifname(interface);
3568 const char *driver = g_supplicant_interface_get_driver(interface);
3569 struct wifi_data *wifi;
3571 wifi = g_supplicant_interface_get_data(interface);
3573 wifi = get_pending_wifi_data(ifname);
3577 wifi->interface = interface;
3578 g_supplicant_interface_set_data(interface, wifi);
3579 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3580 wifi->p2p_device = true;
3583 DBG("ifname %s driver %s wifi %p tethering %d",
3584 ifname, driver, wifi, wifi->tethering);
3586 if (!wifi->device) {
3587 connman_error("WiFi device not set");
3591 connman_device_set_powered(wifi->device, true);
3594 static bool is_idle(struct wifi_data *wifi)
3596 DBG("state %d", wifi->state);
3598 switch (wifi->state) {
3599 case G_SUPPLICANT_STATE_UNKNOWN:
3600 case G_SUPPLICANT_STATE_DISABLED:
3601 case G_SUPPLICANT_STATE_DISCONNECTED:
3602 case G_SUPPLICANT_STATE_INACTIVE:
3603 case G_SUPPLICANT_STATE_SCANNING:
3606 case G_SUPPLICANT_STATE_AUTHENTICATING:
3607 case G_SUPPLICANT_STATE_ASSOCIATING:
3608 case G_SUPPLICANT_STATE_ASSOCIATED:
3609 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3610 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3611 case G_SUPPLICANT_STATE_COMPLETED:
3618 static bool is_idle_wps(GSupplicantInterface *interface,
3619 struct wifi_data *wifi)
3621 /* First, let's check if WPS processing did not went wrong */
3622 if (g_supplicant_interface_get_wps_state(interface) ==
3623 G_SUPPLICANT_WPS_STATE_FAIL)
3626 /* Unlike normal connection, being associated while processing wps
3627 * actually means that we are idling. */
3628 switch (wifi->state) {
3629 case G_SUPPLICANT_STATE_UNKNOWN:
3630 case G_SUPPLICANT_STATE_DISABLED:
3631 case G_SUPPLICANT_STATE_DISCONNECTED:
3632 case G_SUPPLICANT_STATE_INACTIVE:
3633 case G_SUPPLICANT_STATE_SCANNING:
3634 case G_SUPPLICANT_STATE_ASSOCIATED:
3636 case G_SUPPLICANT_STATE_AUTHENTICATING:
3637 case G_SUPPLICANT_STATE_ASSOCIATING:
3638 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3639 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3640 case G_SUPPLICANT_STATE_COMPLETED:
3647 static bool handle_wps_completion(GSupplicantInterface *interface,
3648 struct connman_network *network,
3649 struct connman_device *device,
3650 struct wifi_data *wifi)
3654 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3656 const unsigned char *ssid, *wps_ssid;
3657 unsigned int ssid_len, wps_ssid_len;
3658 const char *wps_key;
3660 /* Checking if we got associated with requested
3662 ssid = connman_network_get_blob(network, "WiFi.SSID",
3665 wps_ssid = g_supplicant_interface_get_wps_ssid(
3666 interface, &wps_ssid_len);
3668 if (!wps_ssid || wps_ssid_len != ssid_len ||
3669 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3670 connman_network_set_associating(network, false);
3671 #if defined TIZEN_EXT
3672 g_supplicant_interface_disconnect(wifi->interface,
3673 disconnect_callback, wifi->network);
3675 connman_network_set_bool(network, "WiFi.UseWPS", false);
3676 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3678 g_supplicant_interface_disconnect(wifi->interface,
3679 disconnect_callback, wifi);
3684 wps_key = g_supplicant_interface_get_wps_key(interface);
3685 #if defined TIZEN_EXT
3686 /* Check the passphrase and encrypt it
3689 gchar *passphrase = g_strdup(wps_key);
3691 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3693 if (check_passphrase_ext(network, passphrase) < 0) {
3694 DBG("[WPS] Invalid passphrase");
3699 ret = send_encryption_request(passphrase, network);
3704 DBG("[WPS] Encryption request succeeded");
3706 DBG("[WPS] Encryption request failed %d", ret);
3709 connman_network_set_string(network, "WiFi.Passphrase",
3712 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3719 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3720 struct wifi_data *wifi)
3722 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3723 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3724 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3725 wifi->load_shaping_retries ++;
3728 wifi->load_shaping_retries = 0;
3732 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3733 struct connman_network *network,
3734 struct wifi_data *wifi)
3736 #if defined TIZEN_EXT
3737 const char *security;
3738 struct connman_service *service;
3740 if (wifi->connected)
3743 security = connman_network_get_string(network, "WiFi.Security");
3745 if (security && g_str_equal(security, "ieee8021x") == true &&
3746 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3748 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3753 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3756 struct connman_service *service;
3758 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3761 if (wifi->connected)
3765 service = connman_service_lookup_from_network(network);
3771 if (connman_service_get_favorite(service)) {
3772 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3777 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3782 #if defined TIZEN_EXT
3783 static bool handle_wifi_assoc_retry(struct connman_network *network,
3784 struct wifi_data *wifi)
3786 const char *security;
3788 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3789 connman_network_get_connecting(network) != true) {
3790 wifi->assoc_retry_count = 0;
3794 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3795 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3796 wifi->assoc_retry_count = 0;
3800 security = connman_network_get_string(network, "WiFi.Security");
3801 if (security && g_str_equal(security, "ieee8021x") == true &&
3802 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3803 wifi->assoc_retry_count = 0;
3807 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3808 wifi->assoc_retry_count = 0;
3810 /* Honestly it's not an invalid-key error,
3811 * however QA team recommends that the invalid-key error
3812 * might be better to display for user experience.
3814 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3823 static void interface_state(GSupplicantInterface *interface)
3825 struct connman_network *network;
3826 struct connman_device *device;
3827 struct wifi_data *wifi;
3828 GSupplicantState state = g_supplicant_interface_get_state(interface);
3832 wifi = g_supplicant_interface_get_data(interface);
3834 DBG("wifi %p interface state %d", wifi, state);
3839 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3840 if (wifi->tethering_param) {
3841 g_free(wifi->tethering_param->ssid);
3842 g_free(wifi->tethering_param);
3843 wifi->tethering_param = NULL;
3847 device = wifi->device;
3851 if (g_supplicant_interface_get_ready(interface) &&
3852 !wifi->interface_ready) {
3853 wifi->interface_ready = true;
3854 finalize_interface_creation(wifi);
3857 network = wifi->network;
3862 case G_SUPPLICANT_STATE_SCANNING:
3863 if (wifi->connected)
3864 connman_network_set_connected(network, false);
3868 case G_SUPPLICANT_STATE_AUTHENTICATING:
3869 case G_SUPPLICANT_STATE_ASSOCIATING:
3870 #if defined TIZEN_EXT
3871 reset_autoscan(device);
3873 stop_autoscan(device);
3876 if (!wifi->connected)
3877 connman_network_set_associating(network, true);
3881 case G_SUPPLICANT_STATE_COMPLETED:
3882 #if defined TIZEN_EXT
3883 /* though it should be already reset: */
3884 reset_autoscan(device);
3886 wifi->assoc_retry_count = 0;
3888 wifi->scan_pending_network = NULL;
3890 /* should be cleared scanning flag */
3891 bool scanning = connman_device_get_scanning(device);
3893 connman_device_set_scanning(device,
3894 CONNMAN_SERVICE_TYPE_WIFI, false);
3895 connman_device_unref(device);
3898 if (!automaxspeed_timeout) {
3899 DBG("Going to start signalpoll timer!!");
3900 autosignalpoll_timeout(network);
3903 /* though it should be already stopped: */
3904 stop_autoscan(device);
3907 if (!handle_wps_completion(interface, network, device, wifi))
3910 connman_network_set_connected(network, true);
3912 wifi->disconnect_code = 0;
3913 wifi->assoc_code = 0;
3914 wifi->load_shaping_retries = 0;
3917 case G_SUPPLICANT_STATE_DISCONNECTED:
3918 #if defined TIZEN_EXT
3919 connman_network_set_maxspeed(network, 0);
3921 if (automaxspeed_timeout != 0) {
3922 g_source_remove(automaxspeed_timeout);
3923 automaxspeed_timeout = 0;
3924 DBG("Remove signalpoll timer!!");
3928 * If we're in one of the idle modes, we have
3929 * not started association yet and thus setting
3930 * those ones to FALSE could cancel an association
3933 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3935 if (is_idle_wps(interface, wifi))
3941 if (handle_assoc_status_code(interface, wifi))
3944 /* If previous state was 4way-handshake, then
3945 * it's either: psk was incorrect and thus we retry
3946 * or if we reach the maximum retries we declare the
3948 if (handle_4way_handshake_failure(interface,
3952 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3953 switch (wifi->disconnect_code) {
3954 case 1: /* Unspecified reason */
3955 /* Let's assume it's because we got blocked */
3957 case 6: /* Class 2 frame received from nonauthenticated STA */
3958 connman_network_set_error(network,
3959 CONNMAN_NETWORK_ERROR_BLOCKED);
3966 #if defined TIZEN_EXT
3967 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3968 * Retry association until its retry count is expired */
3969 if (handle_wifi_assoc_retry(network, wifi) == true) {
3970 throw_wifi_scan(wifi->device, scan_callback);
3971 wifi->scan_pending_network = wifi->network;
3975 if(wifi->disconnect_code > 0){
3976 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3977 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3981 connman_network_set_connected(network, false);
3982 connman_network_set_associating(network, false);
3983 wifi->disconnecting = false;
3985 start_autoscan(device);
3989 case G_SUPPLICANT_STATE_INACTIVE:
3990 #if defined TIZEN_EXT
3991 if (handle_wps_completion(interface, network, device, wifi) == false)
3994 connman_network_set_associating(network, false);
3995 start_autoscan(device);
3999 case G_SUPPLICANT_STATE_UNKNOWN:
4000 case G_SUPPLICANT_STATE_DISABLED:
4001 case G_SUPPLICANT_STATE_ASSOCIATED:
4002 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4003 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4007 old_connected = wifi->connected;
4008 wifi->state = state;
4010 /* Saving wpa_s state policy:
4011 * If connected and if the state changes are roaming related:
4012 * --> We stay connected
4014 * --> We are connected
4016 * --> We are not connected
4019 case G_SUPPLICANT_STATE_AUTHENTICATING:
4020 case G_SUPPLICANT_STATE_ASSOCIATING:
4021 case G_SUPPLICANT_STATE_ASSOCIATED:
4022 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4023 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4024 if (wifi->connected)
4025 connman_warn("Probably roaming right now!"
4026 " Staying connected...");
4028 case G_SUPPLICANT_STATE_SCANNING:
4029 wifi->connected = false;
4032 start_autoscan(device);
4034 case G_SUPPLICANT_STATE_COMPLETED:
4035 wifi->connected = true;
4038 wifi->connected = false;
4045 static void interface_removed(GSupplicantInterface *interface)
4047 const char *ifname = g_supplicant_interface_get_ifname(interface);
4048 struct wifi_data *wifi;
4050 DBG("ifname %s", ifname);
4052 wifi = g_supplicant_interface_get_data(interface);
4054 #if defined TIZEN_EXT_WIFI_MESH
4055 if (wifi && wifi->mesh_interface) {
4056 DBG("Notify mesh interface remove");
4057 connman_mesh_notify_interface_remove(true);
4058 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4059 g_free(mesh_info->parent_ifname);
4060 g_free(mesh_info->ifname);
4061 g_free(mesh_info->identifier);
4063 wifi->mesh_interface = false;
4064 wifi->mesh_info = NULL;
4070 wifi->interface = NULL;
4072 if (wifi && wifi->tethering)
4075 if (!wifi || !wifi->device) {
4076 DBG("wifi interface already removed");
4080 connman_device_set_powered(wifi->device, false);
4082 check_p2p_technology();
4083 #if defined TIZEN_EXT_WIFI_MESH
4084 check_mesh_technology();
4088 static void set_device_type(const char *type, char dev_type[17])
4090 const char *oui = "0050F204";
4091 const char *category = "0001";
4092 const char *sub_category = "0000";
4094 if (!g_strcmp0(type, "handset")) {
4096 sub_category = "0005";
4097 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4098 sub_category = "0001";
4099 else if (!g_strcmp0(type, "server"))
4100 sub_category = "0002";
4101 else if (!g_strcmp0(type, "laptop"))
4102 sub_category = "0005";
4103 else if (!g_strcmp0(type, "desktop"))
4104 sub_category = "0006";
4105 else if (!g_strcmp0(type, "tablet"))
4106 sub_category = "0009";
4107 else if (!g_strcmp0(type, "watch"))
4110 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4113 static void p2p_support(GSupplicantInterface *interface)
4115 char dev_type[17] = {};
4116 const char *hostname;
4123 if (!g_supplicant_interface_has_p2p(interface))
4126 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4127 DBG("Could not register P2P technology driver");
4131 hostname = connman_utsname_get_hostname();
4133 hostname = "ConnMan";
4135 set_device_type(connman_machine_get_type(), dev_type);
4136 g_supplicant_interface_set_p2p_device_config(interface,
4137 hostname, dev_type);
4138 connman_peer_driver_register(&peer_driver);
4141 static void scan_started(GSupplicantInterface *interface)
4146 static void scan_finished(GSupplicantInterface *interface)
4148 #if defined TIZEN_EXT
4149 struct wifi_data *wifi;
4150 bool is_associating = false;
4151 static bool is_scanning = true;
4156 #if defined TIZEN_EXT
4157 wifi = g_supplicant_interface_get_data(interface);
4158 if (wifi && wifi->scan_pending_network) {
4159 network_connect(wifi->scan_pending_network);
4160 wifi->scan_pending_network = NULL;
4163 //service state - associating
4164 if(!wifi || !wifi->network)
4167 is_associating = connman_network_get_associating(wifi->network);
4168 if(is_associating && is_scanning){
4169 is_scanning = false;
4170 DBG("send scan for connecting");
4171 throw_wifi_scan(wifi->device, scan_callback);
4182 static void ap_create_fail(GSupplicantInterface *interface)
4184 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4187 if ((wifi->tethering) && (wifi->tethering_param)) {
4188 DBG("%s create AP fail \n",
4189 g_supplicant_interface_get_ifname(wifi->interface));
4191 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4192 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4193 wifi->tethering = false;
4195 ret = tech_set_tethering(wifi->tethering_param->technology,
4196 wifi->tethering_param->ssid->ssid,
4197 wifi->tethering_param->ssid->passphrase,
4198 wifi->bridge, true);
4200 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4201 connman_technology_tethering_notify(wifi_technology,false);
4204 g_free(wifi->tethering_param->ssid);
4205 g_free(wifi->tethering_param);
4206 wifi->tethering_param = NULL;
4212 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4214 unsigned char strength;
4216 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4218 #if !defined TIZEN_EXT
4225 #if defined TIZEN_EXT_WIFI_MESH
4226 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4228 GSupplicantInterface *interface;
4229 struct wifi_data *wifi;
4230 const char *name, *security;
4231 struct connman_mesh *connman_mesh;
4232 struct wifi_mesh_info *mesh_info;
4233 const unsigned char *bssid;
4234 const char *identifier;
4239 interface = g_supplicant_network_get_interface(supplicant_network);
4240 wifi = g_supplicant_interface_get_data(interface);
4241 if (!wifi || !wifi->mesh_interface) {
4242 DBG("Virtual Mesh interface not created");
4246 bssid = g_supplicant_network_get_bssid(supplicant_network);
4247 address = g_malloc0(19);
4248 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4249 bssid[2], bssid[3], bssid[4], bssid[5]);
4251 identifier = g_supplicant_network_get_identifier(supplicant_network);
4252 name = g_supplicant_network_get_name(supplicant_network);
4253 security = g_supplicant_network_get_security(supplicant_network);
4254 frequency = g_supplicant_network_get_frequency(supplicant_network);
4256 mesh_info = wifi->mesh_info;
4257 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4261 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4263 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4264 connman_mesh_set_name(connman_mesh, name);
4265 connman_mesh_set_security(connman_mesh, security);
4266 connman_mesh_set_frequency(connman_mesh, frequency);
4267 connman_mesh_set_address(connman_mesh, address);
4268 connman_mesh_set_index(connman_mesh, mesh_info->index);
4269 connman_mesh_set_strength(connman_mesh,
4270 calculate_strength(supplicant_network));
4271 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4273 ret = connman_mesh_register(connman_mesh);
4274 if (ret == -EALREADY)
4275 DBG("Mesh Peer is already registered");
4281 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4283 GSupplicantInterface *interface;
4284 struct wifi_data *wifi;
4285 struct connman_mesh *connman_mesh;
4286 struct wifi_mesh_info *mesh_info;
4287 const char *identifier;
4289 interface = g_supplicant_network_get_interface(supplicant_network);
4290 wifi = g_supplicant_interface_get_data(interface);
4291 if (!wifi || !wifi->mesh_interface) {
4292 DBG("Virtual Mesh interface not created");
4296 identifier = g_supplicant_network_get_identifier(supplicant_network);
4298 DBG("Failed to get Mesh Peer identifier");
4302 mesh_info = wifi->mesh_info;
4303 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4305 /* Do not unregister connected mesh peer */
4306 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4307 DBG("Mesh Peer %s is connected", identifier);
4310 DBG("Mesh Peer identifier %s removed", identifier);
4311 connman_mesh_unregister(connman_mesh);
4316 static void network_added(GSupplicantNetwork *supplicant_network)
4318 struct connman_network *network;
4319 GSupplicantInterface *interface;
4320 struct wifi_data *wifi;
4321 const char *name, *identifier, *security, *group, *mode;
4322 const unsigned char *ssid;
4323 unsigned int ssid_len;
4327 bool wps_advertizing;
4329 #if defined TIZEN_EXT
4330 GSList *vsie_list = NULL;
4331 const unsigned char *country_code;
4332 ieee80211_modes_e phy_mode;
4335 mode = g_supplicant_network_get_mode(supplicant_network);
4336 identifier = g_supplicant_network_get_identifier(supplicant_network);
4338 DBG("%s", identifier);
4340 if (!g_strcmp0(mode, "adhoc"))
4343 #if defined TIZEN_EXT_WIFI_MESH
4344 if (!g_strcmp0(mode, "mesh")) {
4345 mesh_peer_added(supplicant_network);
4350 interface = g_supplicant_network_get_interface(supplicant_network);
4351 wifi = g_supplicant_interface_get_data(interface);
4352 name = g_supplicant_network_get_name(supplicant_network);
4353 security = g_supplicant_network_get_security(supplicant_network);
4354 group = g_supplicant_network_get_identifier(supplicant_network);
4355 wps = g_supplicant_network_get_wps(supplicant_network);
4356 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4357 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4358 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4359 supplicant_network);
4364 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4366 network = connman_device_get_network(wifi->device, identifier);
4369 network = connman_network_create(identifier,
4370 CONNMAN_NETWORK_TYPE_WIFI);
4374 connman_network_set_index(network, wifi->index);
4376 if (connman_device_add_network(wifi->device, network) < 0) {
4377 connman_network_unref(network);
4381 wifi->networks = g_slist_prepend(wifi->networks, network);
4384 if (name && name[0] != '\0')
4385 connman_network_set_name(network, name);
4387 connman_network_set_blob(network, "WiFi.SSID",
4389 #if defined TIZEN_EXT
4390 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4392 connman_network_set_vsie_list(network, vsie_list);
4394 DBG("vsie_list is NULL");
4395 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4396 connman_network_set_countrycode(network, country_code);
4397 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4398 connman_network_set_phy_mode(network, phy_mode);
4400 connman_network_set_string(network, "WiFi.Security", security);
4401 connman_network_set_strength(network,
4402 calculate_strength(supplicant_network));
4403 connman_network_set_bool(network, "WiFi.WPS", wps);
4406 /* Is AP advertizing for WPS association?
4407 * If so, we decide to use WPS by default */
4408 if (wps_ready && wps_pbc &&
4410 #if !defined TIZEN_EXT
4411 connman_network_set_bool(network, "WiFi.UseWPS", true);
4413 DBG("wps is activating by ap but ignore it.");
4418 connman_network_set_frequency(network,
4419 g_supplicant_network_get_frequency(supplicant_network));
4420 #if defined TIZEN_EXT
4421 connman_network_set_bssid(network,
4422 g_supplicant_network_get_bssid(supplicant_network));
4423 connman_network_set_maxrate(network,
4424 g_supplicant_network_get_maxrate(supplicant_network));
4425 connman_network_set_enc_mode(network,
4426 g_supplicant_network_get_enc_mode(supplicant_network));
4427 connman_network_set_rsn_mode(network,
4428 g_supplicant_network_get_rsn_mode(supplicant_network));
4429 connman_network_set_keymgmt(network,
4430 g_supplicant_network_get_keymgmt(supplicant_network));
4431 connman_network_set_bool(network, "WiFi.HS20AP",
4432 g_supplicant_network_is_hs20AP(supplicant_network));
4433 connman_network_set_bssid_list(network,
4434 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4436 connman_network_set_available(network, true);
4437 connman_network_set_string(network, "WiFi.Mode", mode);
4439 #if defined TIZEN_EXT
4444 connman_network_set_group(network, group);
4446 #if defined TIZEN_EXT
4447 if (wifi_first_scan == true)
4448 found_with_first_scan = true;
4451 if (wifi->hidden && ssid) {
4452 #if defined TIZEN_EXT
4453 if (network_security(wifi->hidden->security) ==
4454 network_security(security) &&
4456 if (!g_strcmp0(wifi->hidden->security, security) &&
4458 wifi->hidden->ssid_len == ssid_len &&
4459 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4460 connman_network_connect_hidden(network,
4461 wifi->hidden->identity,
4462 wifi->hidden->passphrase,
4463 wifi->hidden->user_data);
4464 wifi->hidden->user_data = NULL;
4465 hidden_free(wifi->hidden);
4466 wifi->hidden = NULL;
4471 static void network_removed(GSupplicantNetwork *network)
4473 GSupplicantInterface *interface;
4474 struct wifi_data *wifi;
4475 const char *name, *identifier;
4476 struct connman_network *connman_network;
4478 #if defined TIZEN_EXT_WIFI_MESH
4480 mode = g_supplicant_network_get_mode(network);
4481 if (!g_strcmp0(mode, "mesh")) {
4482 mesh_peer_removed(network);
4487 interface = g_supplicant_network_get_interface(network);
4488 wifi = g_supplicant_interface_get_data(interface);
4489 identifier = g_supplicant_network_get_identifier(network);
4490 name = g_supplicant_network_get_name(network);
4492 DBG("name %s", name);
4497 connman_network = connman_device_get_network(wifi->device, identifier);
4498 if (!connman_network)
4501 #if defined TIZEN_EXT
4502 if (connman_network == wifi->scan_pending_network)
4503 wifi->scan_pending_network = NULL;
4505 if (connman_network == wifi->pending_network)
4506 wifi->pending_network = NULL;
4508 if(connman_network_get_connecting(connman_network) == true){
4509 connman_network_set_connected(connman_network, false);
4513 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4515 connman_device_remove_network(wifi->device, connman_network);
4516 connman_network_unref(connman_network);
4519 static void network_changed(GSupplicantNetwork *network, const char *property)
4521 GSupplicantInterface *interface;
4522 struct wifi_data *wifi;
4523 const char *name, *identifier;
4524 struct connman_network *connman_network;
4526 #if defined TIZEN_EXT
4527 const unsigned char *bssid;
4528 unsigned int maxrate;
4531 const unsigned char *country_code;
4532 ieee80211_modes_e phy_mode;
4536 interface = g_supplicant_network_get_interface(network);
4537 wifi = g_supplicant_interface_get_data(interface);
4538 identifier = g_supplicant_network_get_identifier(network);
4539 name = g_supplicant_network_get_name(network);
4541 DBG("name %s", name);
4546 connman_network = connman_device_get_network(wifi->device, identifier);
4547 if (!connman_network)
4550 if (g_str_equal(property, "Signal")) {
4551 connman_network_set_strength(connman_network,
4552 calculate_strength(network));
4553 connman_network_update(connman_network);
4556 #if defined TIZEN_EXT
4557 bssid = g_supplicant_network_get_bssid(network);
4558 maxrate = g_supplicant_network_get_maxrate(network);
4559 frequency = g_supplicant_network_get_frequency(network);
4560 wps = g_supplicant_network_get_wps(network);
4561 phy_mode = g_supplicant_network_get_phy_mode(network);
4563 connman_network_set_bssid(connman_network, bssid);
4564 connman_network_set_maxrate(connman_network, maxrate);
4565 connman_network_set_frequency(connman_network, frequency);
4566 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4567 country_code = g_supplicant_network_get_countrycode(network);
4568 connman_network_set_countrycode(connman_network, country_code);
4569 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4570 connman_network_set_bssid_list(connman_network, bssid_list);
4571 connman_network_set_phy_mode(connman_network, phy_mode);
4575 static void network_associated(GSupplicantNetwork *network)
4577 GSupplicantInterface *interface;
4578 struct wifi_data *wifi;
4579 struct connman_network *connman_network;
4580 const char *identifier;
4584 interface = g_supplicant_network_get_interface(network);
4588 wifi = g_supplicant_interface_get_data(interface);
4592 identifier = g_supplicant_network_get_identifier(network);
4594 connman_network = connman_device_get_network(wifi->device, identifier);
4595 if (!connman_network)
4598 if (wifi->network) {
4599 if (wifi->network == connman_network)
4603 * This should never happen, we got associated with
4604 * a network different than the one we were expecting.
4606 DBG("Associated to %p while expecting %p",
4607 connman_network, wifi->network);
4609 connman_network_set_associating(wifi->network, false);
4612 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4614 wifi->network = connman_network_ref(connman_network);
4618 * Interface state changes callback (interface_state) is always
4619 * called before network_associated callback thus we need to call
4620 * interface_state again in order to process the new state now that
4621 * we have the network properly set.
4623 interface_state(interface);
4626 static void apply_peer_services(GSupplicantPeer *peer,
4627 struct connman_peer *connman_peer)
4629 const unsigned char *data;
4634 connman_peer_reset_services(connman_peer);
4636 data = g_supplicant_peer_get_widi_ies(peer, &length);
4638 connman_peer_add_service(connman_peer,
4639 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4643 static void add_station(const char *mac)
4645 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4649 static void remove_station(const char *mac)
4651 connman_technology_tethering_remove_station(mac);
4654 static void peer_found(GSupplicantPeer *peer)
4656 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4657 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4658 struct connman_peer *connman_peer;
4659 const char *identifier, *name;
4661 #if defined TIZEN_EXT
4665 identifier = g_supplicant_peer_get_identifier(peer);
4666 name = g_supplicant_peer_get_name(peer);
4668 DBG("ident: %s", identifier);
4670 connman_peer = connman_peer_get(wifi->device, identifier);
4674 connman_peer = connman_peer_create(identifier);
4675 connman_peer_set_name(connman_peer, name);
4676 connman_peer_set_device(connman_peer, wifi->device);
4677 apply_peer_services(peer, connman_peer);
4679 ret = connman_peer_register(connman_peer);
4680 if (ret < 0 && ret != -EALREADY)
4681 connman_peer_unref(connman_peer);
4683 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4686 static void peer_lost(GSupplicantPeer *peer)
4688 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4689 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4690 struct connman_peer *connman_peer;
4691 const char *identifier;
4696 identifier = g_supplicant_peer_get_identifier(peer);
4698 DBG("ident: %s", identifier);
4700 connman_peer = connman_peer_get(wifi->device, identifier);
4702 if (wifi->p2p_connecting &&
4703 wifi->pending_peer == connman_peer) {
4704 peer_connect_timeout(wifi);
4706 connman_peer_unregister(connman_peer);
4707 connman_peer_unref(connman_peer);
4710 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4713 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4715 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4716 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4717 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4718 struct connman_peer *connman_peer;
4719 const char *identifier;
4721 identifier = g_supplicant_peer_get_identifier(peer);
4723 DBG("ident: %s", identifier);
4728 connman_peer = connman_peer_get(wifi->device, identifier);
4733 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4734 apply_peer_services(peer, connman_peer);
4735 connman_peer_services_changed(connman_peer);
4737 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4738 if (!g_supplicant_peer_is_in_a_group(peer))
4739 p_state = CONNMAN_PEER_STATE_IDLE;
4741 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4743 case G_SUPPLICANT_PEER_GROUP_STARTED:
4745 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4746 p_state = CONNMAN_PEER_STATE_IDLE;
4748 case G_SUPPLICANT_PEER_GROUP_JOINED:
4749 connman_peer_set_iface_address(connman_peer,
4750 g_supplicant_peer_get_iface_address(peer));
4752 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4753 p_state = CONNMAN_PEER_STATE_IDLE;
4755 case G_SUPPLICANT_PEER_GROUP_FAILED:
4756 if (g_supplicant_peer_has_requested_connection(peer))
4757 p_state = CONNMAN_PEER_STATE_IDLE;
4759 p_state = CONNMAN_PEER_STATE_FAILURE;
4763 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4764 p_state == CONNMAN_PEER_STATE_FAILURE) {
4765 if (wifi->p2p_connecting
4766 && connman_peer == wifi->pending_peer)
4767 peer_cancel_timeout(wifi);
4769 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4772 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4775 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4776 GSupplicantInterface *g_iface;
4777 struct wifi_data *g_wifi;
4779 g_iface = g_supplicant_peer_get_group_interface(peer);
4783 g_wifi = g_supplicant_interface_get_data(g_iface);
4787 connman_peer_set_as_master(connman_peer,
4788 !g_supplicant_peer_is_client(peer));
4789 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4792 * If wpa_supplicant didn't create a dedicated p2p-group
4793 * interface then mark this interface as p2p_device to avoid
4794 * scan and auto-scan are launched on it while P2P is connected.
4796 if (!g_list_find(p2p_iface_list, g_wifi))
4797 wifi->p2p_device = true;
4800 connman_peer_set_state(connman_peer, p_state);
4803 static void peer_request(GSupplicantPeer *peer)
4805 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4806 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4807 struct connman_peer *connman_peer;
4808 const char *identifier;
4810 #if defined TIZEN_EXT
4815 identifier = g_supplicant_peer_get_identifier(peer);
4817 DBG("ident: %s", identifier);
4819 connman_peer = connman_peer_get(wifi->device, identifier);
4823 connman_peer_request_connection(connman_peer);
4826 #if defined TIZEN_EXT
4827 static void system_power_off(void)
4830 struct wifi_data *wifi;
4831 struct connman_service *service;
4832 struct connman_ipconfig *ipconfig_ipv4;
4834 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4835 for (list = iface_list; list; list = list->next) {
4838 if (wifi->network != NULL) {
4839 service = connman_service_lookup_from_network(wifi->network);
4840 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4841 __connman_dhcp_stop(ipconfig_ipv4);
4847 static void network_merged(GSupplicantNetwork *network)
4849 GSupplicantInterface *interface;
4850 GSupplicantState state;
4851 struct wifi_data *wifi;
4852 const char *identifier;
4853 struct connman_network *connman_network;
4857 interface = g_supplicant_network_get_interface(network);
4861 state = g_supplicant_interface_get_state(interface);
4862 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4865 wifi = g_supplicant_interface_get_data(interface);
4869 identifier = g_supplicant_network_get_identifier(network);
4871 connman_network = connman_device_get_network(wifi->device, identifier);
4872 if (!connman_network)
4875 DBG("merged identifier %s", identifier);
4877 if (wifi->connected == FALSE) {
4879 case G_SUPPLICANT_STATE_AUTHENTICATING:
4880 case G_SUPPLICANT_STATE_ASSOCIATING:
4881 case G_SUPPLICANT_STATE_ASSOCIATED:
4882 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4883 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4884 connman_network_set_associating(connman_network, TRUE);
4886 case G_SUPPLICANT_STATE_COMPLETED:
4887 connman_network_set_connected(connman_network, TRUE);
4890 DBG("Not handled the state : %d", state);
4895 ishs20AP = g_supplicant_network_is_hs20AP(network);
4898 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
4899 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
4900 connman_network_set_string(connman_network, "WiFi.EAP",
4902 connman_network_set_string(connman_network, "WiFi.Identity",
4903 g_supplicant_network_get_identity(network));
4904 connman_network_set_string(connman_network, "WiFi.Phase2",
4905 g_supplicant_network_get_phase2(network));
4910 wifi->network = connman_network;
4913 static void assoc_failed(void *user_data)
4915 struct connman_network *network = user_data;
4916 connman_network_set_associating(network, false);
4920 static void debug(const char *str)
4922 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
4923 connman_debug("%s", str);
4926 static void disconnect_reasoncode(GSupplicantInterface *interface,
4929 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4932 wifi->disconnect_code = reasoncode;
4936 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
4938 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4941 wifi->assoc_code = status_code;
4945 static const GSupplicantCallbacks callbacks = {
4946 .system_ready = system_ready,
4947 .system_killed = system_killed,
4948 .interface_added = interface_added,
4949 .interface_state = interface_state,
4950 .interface_removed = interface_removed,
4951 .p2p_support = p2p_support,
4952 .scan_started = scan_started,
4953 .scan_finished = scan_finished,
4954 .ap_create_fail = ap_create_fail,
4955 .network_added = network_added,
4956 .network_removed = network_removed,
4957 .network_changed = network_changed,
4958 .network_associated = network_associated,
4959 .add_station = add_station,
4960 .remove_station = remove_station,
4961 .peer_found = peer_found,
4962 .peer_lost = peer_lost,
4963 .peer_changed = peer_changed,
4964 .peer_request = peer_request,
4965 #if defined TIZEN_EXT
4966 .system_power_off = system_power_off,
4967 .network_merged = network_merged,
4968 .assoc_failed = assoc_failed,
4971 .disconnect_reasoncode = disconnect_reasoncode,
4972 .assoc_status_code = assoc_status_code,
4973 #if defined TIZEN_EXT_WIFI_MESH
4974 .mesh_support = mesh_support,
4975 .mesh_group_started = mesh_group_started,
4976 .mesh_group_removed = mesh_group_removed,
4977 .mesh_peer_connected = mesh_peer_connected,
4978 .mesh_peer_disconnected = mesh_peer_disconnected,
4983 static int tech_probe(struct connman_technology *technology)
4985 wifi_technology = technology;
4990 static void tech_remove(struct connman_technology *technology)
4992 wifi_technology = NULL;
4995 static GSupplicantSSID *ssid_ap_init(const char *ssid,
4996 const char *passphrase)
4998 GSupplicantSSID *ap;
5000 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5004 ap->mode = G_SUPPLICANT_MODE_MASTER;
5005 #if defined TIZEN_EXT
5006 ap->ssid = (void *) ssid;
5010 ap->ssid_len = strlen(ssid);
5014 if (!passphrase || strlen(passphrase) == 0) {
5015 ap->security = G_SUPPLICANT_SECURITY_NONE;
5016 ap->passphrase = NULL;
5018 ap->security = G_SUPPLICANT_SECURITY_PSK;
5019 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5020 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5021 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5022 ap->passphrase = passphrase;
5028 static void ap_start_callback(int result, GSupplicantInterface *interface,
5031 struct wifi_tethering_info *info = user_data;
5033 DBG("result %d index %d bridge %s",
5034 result, info->wifi->index, info->wifi->bridge);
5036 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5037 connman_inet_remove_from_bridge(info->wifi->index,
5038 info->wifi->bridge);
5040 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5041 connman_technology_tethering_notify(info->technology, false);
5042 g_free(info->wifi->tethering_param->ssid);
5043 g_free(info->wifi->tethering_param);
5044 info->wifi->tethering_param = NULL;
5048 g_free(info->ifname);
5052 static void ap_create_callback(int result,
5053 GSupplicantInterface *interface,
5056 struct wifi_tethering_info *info = user_data;
5058 DBG("result %d ifname %s", result,
5059 g_supplicant_interface_get_ifname(interface));
5061 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5062 connman_inet_remove_from_bridge(info->wifi->index,
5063 info->wifi->bridge);
5065 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5066 connman_technology_tethering_notify(info->technology, false);
5067 g_free(info->wifi->tethering_param->ssid);
5068 g_free(info->wifi->tethering_param);
5069 info->wifi->tethering_param = NULL;
5073 g_free(info->ifname);
5079 info->wifi->interface = interface;
5080 g_supplicant_interface_set_data(interface, info->wifi);
5082 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5083 connman_error("Failed to set interface ap_scan property");
5085 g_supplicant_interface_connect(interface, info->ssid,
5086 ap_start_callback, info);
5089 static void sta_remove_callback(int result,
5090 GSupplicantInterface *interface,
5093 struct wifi_tethering_info *info = user_data;
5094 const char *driver = connman_option_get_string("wifi");
5096 DBG("ifname %s result %d ", info->ifname, result);
5098 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5099 info->wifi->tethering = false;
5100 connman_technology_tethering_notify(info->technology, false);
5102 g_free(info->ifname);
5106 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5107 g_free(info->wifi->tethering_param->ssid);
5108 g_free(info->wifi->tethering_param);
5109 info->wifi->tethering_param = NULL;
5114 info->wifi->interface = NULL;
5116 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5121 static int enable_wifi_tethering(struct connman_technology *technology,
5122 const char *bridge, const char *identifier,
5123 const char *passphrase, bool available)
5126 GSupplicantInterface *interface;
5127 struct wifi_data *wifi;
5128 struct wifi_tethering_info *info;
5133 for (list = iface_list; list; list = list->next) {
5136 DBG("wifi %p network %p pending_network %p", wifi,
5137 wifi->network, wifi->pending_network);
5139 interface = wifi->interface;
5144 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5147 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5149 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5150 DBG("%s does not support AP mode (detected)", ifname);
5154 mode = g_supplicant_interface_get_mode(interface);
5155 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5156 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5157 DBG("%s does not support AP mode (capability)", ifname);
5161 if (wifi->network && available)
5164 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5168 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5169 if (!wifi->tethering_param) {
5175 info->technology = technology;
5176 info->wifi->bridge = bridge;
5177 info->ssid = ssid_ap_init(identifier, passphrase);
5181 info->ifname = g_strdup(ifname);
5185 wifi->tethering_param->technology = technology;
5186 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5187 if (!wifi->tethering_param->ssid)
5190 info->wifi->tethering = true;
5191 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5193 berr = connman_technology_tethering_notify(technology, true);
5197 err = g_supplicant_interface_remove(interface,
5198 sta_remove_callback,
5201 DBG("tethering wifi %p ifname %s", wifi, ifname);
5206 g_free(info->ifname);
5209 g_free(wifi->tethering_param);
5210 wifi->tethering_param = NULL;
5213 * Remove bridge if it was correctly created but remove
5214 * operation failed. Instead, if bridge creation failed then
5215 * break out and do not try again on another interface,
5216 * bridge set-up does not depend on it.
5219 connman_technology_tethering_notify(technology, false);
5227 static int tech_set_tethering(struct connman_technology *technology,
5228 const char *identifier, const char *passphrase,
5229 const char *bridge, bool enabled)
5232 struct wifi_data *wifi;
5238 for (list = iface_list; list; list = list->next) {
5241 if (wifi->tethering) {
5242 wifi->tethering = false;
5244 connman_inet_remove_from_bridge(wifi->index,
5246 wifi->bridged = false;
5250 connman_technology_tethering_notify(technology, false);
5255 DBG("trying tethering for available devices");
5256 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5260 DBG("trying tethering for any device");
5261 err = enable_wifi_tethering(technology, bridge, identifier,
5268 static void regdom_callback(int result, const char *alpha2, void *user_data)
5272 if (!wifi_technology)
5278 connman_technology_regdom_notify(wifi_technology, alpha2);
5281 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5283 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5286 static struct connman_technology_driver tech_driver = {
5288 .type = CONNMAN_SERVICE_TYPE_WIFI,
5289 .probe = tech_probe,
5290 .remove = tech_remove,
5291 .set_tethering = tech_set_tethering,
5292 .set_regdom = tech_set_regdom,
5295 static int wifi_init(void)
5299 err = connman_network_driver_register(&network_driver);
5303 err = g_supplicant_register(&callbacks);
5305 connman_network_driver_unregister(&network_driver);
5309 err = connman_technology_driver_register(&tech_driver);
5311 g_supplicant_unregister(&callbacks);
5312 connman_network_driver_unregister(&network_driver);
5319 static void wifi_exit(void)
5323 connman_technology_driver_unregister(&tech_driver);
5325 g_supplicant_unregister(&callbacks);
5327 connman_network_driver_unregister(&network_driver);
5330 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5331 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)