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 if (!automaxspeed_timeout) {
3539 DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
3543 struct connman_network *network = data;
3544 int ret = network_signalpoll(network);
3547 DBG("Fail to get max speed !!");
3548 automaxspeed_timeout = 0;
3556 static struct connman_network_driver network_driver = {
3558 .type = CONNMAN_NETWORK_TYPE_WIFI,
3559 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3560 .probe = network_probe,
3561 .remove = network_remove,
3562 .connect = network_connect,
3563 .disconnect = network_disconnect,
3566 static void interface_added(GSupplicantInterface *interface)
3568 const char *ifname = g_supplicant_interface_get_ifname(interface);
3569 const char *driver = g_supplicant_interface_get_driver(interface);
3570 #if defined TIZEN_EXT
3571 bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
3574 struct wifi_data *wifi;
3576 wifi = g_supplicant_interface_get_data(interface);
3578 wifi = get_pending_wifi_data(ifname);
3582 wifi->interface = interface;
3583 g_supplicant_interface_set_data(interface, wifi);
3584 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3585 wifi->p2p_device = true;
3588 DBG("ifname %s driver %s wifi %p tethering %d",
3589 ifname, driver, wifi, wifi->tethering);
3591 if (!wifi->device) {
3592 connman_error("WiFi device not set");
3596 connman_device_set_powered(wifi->device, true);
3597 #if defined TIZEN_EXT
3598 connman_techonology_wifi_set_5ghz_supported(wifi_technology, is_5_0_ghz_supported);
3602 static bool is_idle(struct wifi_data *wifi)
3604 DBG("state %d", wifi->state);
3606 switch (wifi->state) {
3607 case G_SUPPLICANT_STATE_UNKNOWN:
3608 case G_SUPPLICANT_STATE_DISABLED:
3609 case G_SUPPLICANT_STATE_DISCONNECTED:
3610 case G_SUPPLICANT_STATE_INACTIVE:
3611 case G_SUPPLICANT_STATE_SCANNING:
3614 case G_SUPPLICANT_STATE_AUTHENTICATING:
3615 case G_SUPPLICANT_STATE_ASSOCIATING:
3616 case G_SUPPLICANT_STATE_ASSOCIATED:
3617 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3618 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3619 case G_SUPPLICANT_STATE_COMPLETED:
3626 static bool is_idle_wps(GSupplicantInterface *interface,
3627 struct wifi_data *wifi)
3629 /* First, let's check if WPS processing did not went wrong */
3630 if (g_supplicant_interface_get_wps_state(interface) ==
3631 G_SUPPLICANT_WPS_STATE_FAIL)
3634 /* Unlike normal connection, being associated while processing wps
3635 * actually means that we are idling. */
3636 switch (wifi->state) {
3637 case G_SUPPLICANT_STATE_UNKNOWN:
3638 case G_SUPPLICANT_STATE_DISABLED:
3639 case G_SUPPLICANT_STATE_DISCONNECTED:
3640 case G_SUPPLICANT_STATE_INACTIVE:
3641 case G_SUPPLICANT_STATE_SCANNING:
3642 case G_SUPPLICANT_STATE_ASSOCIATED:
3644 case G_SUPPLICANT_STATE_AUTHENTICATING:
3645 case G_SUPPLICANT_STATE_ASSOCIATING:
3646 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3647 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3648 case G_SUPPLICANT_STATE_COMPLETED:
3655 static bool handle_wps_completion(GSupplicantInterface *interface,
3656 struct connman_network *network,
3657 struct connman_device *device,
3658 struct wifi_data *wifi)
3662 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3664 const unsigned char *ssid, *wps_ssid;
3665 unsigned int ssid_len, wps_ssid_len;
3666 const char *wps_key;
3668 /* Checking if we got associated with requested
3670 ssid = connman_network_get_blob(network, "WiFi.SSID",
3673 wps_ssid = g_supplicant_interface_get_wps_ssid(
3674 interface, &wps_ssid_len);
3676 if (!wps_ssid || wps_ssid_len != ssid_len ||
3677 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3678 connman_network_set_associating(network, false);
3679 #if defined TIZEN_EXT
3680 g_supplicant_interface_disconnect(wifi->interface,
3681 disconnect_callback, wifi->network);
3683 connman_network_set_bool(network, "WiFi.UseWPS", false);
3684 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3686 g_supplicant_interface_disconnect(wifi->interface,
3687 disconnect_callback, wifi);
3692 wps_key = g_supplicant_interface_get_wps_key(interface);
3693 #if defined TIZEN_EXT
3694 /* Check the passphrase and encrypt it
3697 gchar *passphrase = g_strdup(wps_key);
3699 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3701 if (check_passphrase_ext(network, passphrase) < 0) {
3702 DBG("[WPS] Invalid passphrase");
3707 ret = send_encryption_request(passphrase, network);
3712 DBG("[WPS] Encryption request succeeded");
3714 DBG("[WPS] Encryption request failed %d", ret);
3717 connman_network_set_string(network, "WiFi.Passphrase",
3720 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3727 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3728 struct wifi_data *wifi)
3730 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3731 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3732 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3733 wifi->load_shaping_retries ++;
3736 wifi->load_shaping_retries = 0;
3740 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3741 struct connman_network *network,
3742 struct wifi_data *wifi)
3744 #if defined TIZEN_EXT
3745 const char *security;
3746 struct connman_service *service;
3748 if (wifi->connected)
3751 security = connman_network_get_string(network, "WiFi.Security");
3753 if (security && g_str_equal(security, "ieee8021x") == true &&
3754 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3756 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3761 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3764 struct connman_service *service;
3766 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3769 if (wifi->connected)
3773 service = connman_service_lookup_from_network(network);
3779 if (connman_service_get_favorite(service)) {
3780 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3785 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3790 #if defined TIZEN_EXT
3791 static bool handle_wifi_assoc_retry(struct connman_network *network,
3792 struct wifi_data *wifi)
3794 const char *security;
3796 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3797 connman_network_get_connecting(network) != true) {
3798 wifi->assoc_retry_count = 0;
3802 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3803 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3804 wifi->assoc_retry_count = 0;
3808 security = connman_network_get_string(network, "WiFi.Security");
3809 if (security && g_str_equal(security, "ieee8021x") == true &&
3810 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3811 wifi->assoc_retry_count = 0;
3815 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3816 wifi->assoc_retry_count = 0;
3818 /* Honestly it's not an invalid-key error,
3819 * however QA team recommends that the invalid-key error
3820 * might be better to display for user experience.
3822 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3831 static void interface_state(GSupplicantInterface *interface)
3833 struct connman_network *network;
3834 struct connman_device *device;
3835 struct wifi_data *wifi;
3836 GSupplicantState state = g_supplicant_interface_get_state(interface);
3840 wifi = g_supplicant_interface_get_data(interface);
3842 DBG("wifi %p interface state %d", wifi, state);
3847 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3848 if (wifi->tethering_param) {
3849 g_free(wifi->tethering_param->ssid);
3850 g_free(wifi->tethering_param);
3851 wifi->tethering_param = NULL;
3855 device = wifi->device;
3859 if (g_supplicant_interface_get_ready(interface) &&
3860 !wifi->interface_ready) {
3861 wifi->interface_ready = true;
3862 finalize_interface_creation(wifi);
3865 network = wifi->network;
3870 case G_SUPPLICANT_STATE_SCANNING:
3871 if (wifi->connected)
3872 connman_network_set_connected(network, false);
3876 case G_SUPPLICANT_STATE_AUTHENTICATING:
3877 case G_SUPPLICANT_STATE_ASSOCIATING:
3878 #if defined TIZEN_EXT
3879 reset_autoscan(device);
3881 stop_autoscan(device);
3884 if (!wifi->connected)
3885 connman_network_set_associating(network, true);
3889 case G_SUPPLICANT_STATE_COMPLETED:
3890 #if defined TIZEN_EXT
3891 /* though it should be already reset: */
3892 reset_autoscan(device);
3894 wifi->assoc_retry_count = 0;
3896 wifi->scan_pending_network = NULL;
3898 /* should be cleared scanning flag */
3899 bool scanning = connman_device_get_scanning(device);
3901 connman_device_set_scanning(device,
3902 CONNMAN_SERVICE_TYPE_WIFI, false);
3903 connman_device_unref(device);
3906 if (!automaxspeed_timeout) {
3907 DBG("Going to start signalpoll timer!!");
3908 int ret = network_signalpoll(network);
3910 DBG("Fail to get max speed !!");
3912 automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, network);
3915 /* though it should be already stopped: */
3916 stop_autoscan(device);
3919 if (!handle_wps_completion(interface, network, device, wifi))
3922 connman_network_set_connected(network, true);
3924 wifi->disconnect_code = 0;
3925 wifi->assoc_code = 0;
3926 wifi->load_shaping_retries = 0;
3929 case G_SUPPLICANT_STATE_DISCONNECTED:
3930 #if defined TIZEN_EXT
3931 connman_network_set_maxspeed(network, 0);
3933 if (automaxspeed_timeout != 0) {
3934 g_source_remove(automaxspeed_timeout);
3935 automaxspeed_timeout = 0;
3936 DBG("Remove signalpoll timer!!");
3940 * If we're in one of the idle modes, we have
3941 * not started association yet and thus setting
3942 * those ones to FALSE could cancel an association
3945 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3947 if (is_idle_wps(interface, wifi))
3953 if (handle_assoc_status_code(interface, wifi))
3956 /* If previous state was 4way-handshake, then
3957 * it's either: psk was incorrect and thus we retry
3958 * or if we reach the maximum retries we declare the
3960 if (handle_4way_handshake_failure(interface,
3964 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3965 switch (wifi->disconnect_code) {
3966 case 1: /* Unspecified reason */
3967 /* Let's assume it's because we got blocked */
3969 case 6: /* Class 2 frame received from nonauthenticated STA */
3970 connman_network_set_error(network,
3971 CONNMAN_NETWORK_ERROR_BLOCKED);
3978 #if defined TIZEN_EXT
3979 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3980 * Retry association until its retry count is expired */
3981 if (handle_wifi_assoc_retry(network, wifi) == true) {
3982 throw_wifi_scan(wifi->device, scan_callback);
3983 wifi->scan_pending_network = wifi->network;
3987 if(wifi->disconnect_code > 0){
3988 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3989 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3993 connman_network_set_connected(network, false);
3994 connman_network_set_associating(network, false);
3995 wifi->disconnecting = false;
3997 start_autoscan(device);
4001 case G_SUPPLICANT_STATE_INACTIVE:
4002 #if defined TIZEN_EXT
4003 if (handle_wps_completion(interface, network, device, wifi) == false)
4006 connman_network_set_associating(network, false);
4007 start_autoscan(device);
4011 case G_SUPPLICANT_STATE_UNKNOWN:
4012 case G_SUPPLICANT_STATE_DISABLED:
4013 case G_SUPPLICANT_STATE_ASSOCIATED:
4014 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4015 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4019 old_connected = wifi->connected;
4020 wifi->state = state;
4022 /* Saving wpa_s state policy:
4023 * If connected and if the state changes are roaming related:
4024 * --> We stay connected
4026 * --> We are connected
4028 * --> We are not connected
4031 case G_SUPPLICANT_STATE_AUTHENTICATING:
4032 case G_SUPPLICANT_STATE_ASSOCIATING:
4033 case G_SUPPLICANT_STATE_ASSOCIATED:
4034 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4035 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4036 if (wifi->connected)
4037 connman_warn("Probably roaming right now!"
4038 " Staying connected...");
4040 case G_SUPPLICANT_STATE_SCANNING:
4041 wifi->connected = false;
4044 start_autoscan(device);
4046 case G_SUPPLICANT_STATE_COMPLETED:
4047 wifi->connected = true;
4050 wifi->connected = false;
4057 static void interface_removed(GSupplicantInterface *interface)
4059 const char *ifname = g_supplicant_interface_get_ifname(interface);
4060 struct wifi_data *wifi;
4062 DBG("ifname %s", ifname);
4064 wifi = g_supplicant_interface_get_data(interface);
4066 #if defined TIZEN_EXT_WIFI_MESH
4067 if (wifi && wifi->mesh_interface) {
4068 DBG("Notify mesh interface remove");
4069 connman_mesh_notify_interface_remove(true);
4070 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
4071 g_free(mesh_info->parent_ifname);
4072 g_free(mesh_info->ifname);
4073 g_free(mesh_info->identifier);
4075 wifi->mesh_interface = false;
4076 wifi->mesh_info = NULL;
4082 wifi->interface = NULL;
4084 if (wifi && wifi->tethering)
4087 if (!wifi || !wifi->device) {
4088 DBG("wifi interface already removed");
4092 connman_device_set_powered(wifi->device, false);
4094 check_p2p_technology();
4095 #if defined TIZEN_EXT_WIFI_MESH
4096 check_mesh_technology();
4100 static void set_device_type(const char *type, char dev_type[17])
4102 const char *oui = "0050F204";
4103 const char *category = "0001";
4104 const char *sub_category = "0000";
4106 if (!g_strcmp0(type, "handset")) {
4108 sub_category = "0005";
4109 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4110 sub_category = "0001";
4111 else if (!g_strcmp0(type, "server"))
4112 sub_category = "0002";
4113 else if (!g_strcmp0(type, "laptop"))
4114 sub_category = "0005";
4115 else if (!g_strcmp0(type, "desktop"))
4116 sub_category = "0006";
4117 else if (!g_strcmp0(type, "tablet"))
4118 sub_category = "0009";
4119 else if (!g_strcmp0(type, "watch"))
4122 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4125 static void p2p_support(GSupplicantInterface *interface)
4127 char dev_type[17] = {};
4128 const char *hostname;
4135 if (!g_supplicant_interface_has_p2p(interface))
4138 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4139 DBG("Could not register P2P technology driver");
4143 hostname = connman_utsname_get_hostname();
4145 hostname = "ConnMan";
4147 set_device_type(connman_machine_get_type(), dev_type);
4148 g_supplicant_interface_set_p2p_device_config(interface,
4149 hostname, dev_type);
4150 connman_peer_driver_register(&peer_driver);
4153 static void scan_started(GSupplicantInterface *interface)
4158 static void scan_finished(GSupplicantInterface *interface)
4160 #if defined TIZEN_EXT
4161 struct wifi_data *wifi;
4162 bool is_associating = false;
4163 static bool is_scanning = true;
4168 #if defined TIZEN_EXT
4169 wifi = g_supplicant_interface_get_data(interface);
4170 if (wifi && wifi->scan_pending_network) {
4171 network_connect(wifi->scan_pending_network);
4172 wifi->scan_pending_network = NULL;
4175 //service state - associating
4176 if(!wifi || !wifi->network)
4179 is_associating = connman_network_get_associating(wifi->network);
4180 if(is_associating && is_scanning){
4181 is_scanning = false;
4182 DBG("send scan for connecting");
4183 throw_wifi_scan(wifi->device, scan_callback);
4194 static void ap_create_fail(GSupplicantInterface *interface)
4196 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4199 if ((wifi->tethering) && (wifi->tethering_param)) {
4200 DBG("%s create AP fail \n",
4201 g_supplicant_interface_get_ifname(wifi->interface));
4203 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4204 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4205 wifi->tethering = false;
4207 ret = tech_set_tethering(wifi->tethering_param->technology,
4208 wifi->tethering_param->ssid->ssid,
4209 wifi->tethering_param->ssid->passphrase,
4210 wifi->bridge, true);
4212 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4213 connman_technology_tethering_notify(wifi_technology,false);
4216 g_free(wifi->tethering_param->ssid);
4217 g_free(wifi->tethering_param);
4218 wifi->tethering_param = NULL;
4224 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4226 unsigned char strength;
4228 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4230 #if !defined TIZEN_EXT
4237 #if defined TIZEN_EXT_WIFI_MESH
4238 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4240 GSupplicantInterface *interface;
4241 struct wifi_data *wifi;
4242 const char *name, *security;
4243 struct connman_mesh *connman_mesh;
4244 struct wifi_mesh_info *mesh_info;
4245 const unsigned char *bssid;
4246 const char *identifier;
4251 interface = g_supplicant_network_get_interface(supplicant_network);
4252 wifi = g_supplicant_interface_get_data(interface);
4253 if (!wifi || !wifi->mesh_interface) {
4254 DBG("Virtual Mesh interface not created");
4258 bssid = g_supplicant_network_get_bssid(supplicant_network);
4259 address = g_malloc0(19);
4260 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4261 bssid[2], bssid[3], bssid[4], bssid[5]);
4263 identifier = g_supplicant_network_get_identifier(supplicant_network);
4264 name = g_supplicant_network_get_name(supplicant_network);
4265 security = g_supplicant_network_get_security(supplicant_network);
4266 frequency = g_supplicant_network_get_frequency(supplicant_network);
4268 mesh_info = wifi->mesh_info;
4269 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4273 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4275 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4276 connman_mesh_set_name(connman_mesh, name);
4277 connman_mesh_set_security(connman_mesh, security);
4278 connman_mesh_set_frequency(connman_mesh, frequency);
4279 connman_mesh_set_address(connman_mesh, address);
4280 connman_mesh_set_index(connman_mesh, mesh_info->index);
4281 connman_mesh_set_strength(connman_mesh,
4282 calculate_strength(supplicant_network));
4283 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4285 ret = connman_mesh_register(connman_mesh);
4286 if (ret == -EALREADY)
4287 DBG("Mesh Peer is already registered");
4293 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4295 GSupplicantInterface *interface;
4296 struct wifi_data *wifi;
4297 struct connman_mesh *connman_mesh;
4298 struct wifi_mesh_info *mesh_info;
4299 const char *identifier;
4301 interface = g_supplicant_network_get_interface(supplicant_network);
4302 wifi = g_supplicant_interface_get_data(interface);
4303 if (!wifi || !wifi->mesh_interface) {
4304 DBG("Virtual Mesh interface not created");
4308 identifier = g_supplicant_network_get_identifier(supplicant_network);
4310 DBG("Failed to get Mesh Peer identifier");
4314 mesh_info = wifi->mesh_info;
4315 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4317 /* Do not unregister connected mesh peer */
4318 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4319 DBG("Mesh Peer %s is connected", identifier);
4322 DBG("Mesh Peer identifier %s removed", identifier);
4323 connman_mesh_unregister(connman_mesh);
4328 static void network_added(GSupplicantNetwork *supplicant_network)
4330 struct connman_network *network;
4331 GSupplicantInterface *interface;
4332 struct wifi_data *wifi;
4333 const char *name, *identifier, *security, *group, *mode;
4334 const unsigned char *ssid;
4335 unsigned int ssid_len;
4339 bool wps_advertizing;
4341 #if defined TIZEN_EXT
4342 GSList *vsie_list = NULL;
4343 const unsigned char *country_code;
4344 ieee80211_modes_e phy_mode;
4347 mode = g_supplicant_network_get_mode(supplicant_network);
4348 identifier = g_supplicant_network_get_identifier(supplicant_network);
4350 DBG("%s", identifier);
4352 if (!g_strcmp0(mode, "adhoc"))
4355 #if defined TIZEN_EXT_WIFI_MESH
4356 if (!g_strcmp0(mode, "mesh")) {
4357 mesh_peer_added(supplicant_network);
4362 interface = g_supplicant_network_get_interface(supplicant_network);
4363 wifi = g_supplicant_interface_get_data(interface);
4364 name = g_supplicant_network_get_name(supplicant_network);
4365 security = g_supplicant_network_get_security(supplicant_network);
4366 group = g_supplicant_network_get_identifier(supplicant_network);
4367 wps = g_supplicant_network_get_wps(supplicant_network);
4368 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4369 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4370 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4371 supplicant_network);
4376 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4378 network = connman_device_get_network(wifi->device, identifier);
4381 network = connman_network_create(identifier,
4382 CONNMAN_NETWORK_TYPE_WIFI);
4386 connman_network_set_index(network, wifi->index);
4388 if (connman_device_add_network(wifi->device, network) < 0) {
4389 connman_network_unref(network);
4393 wifi->networks = g_slist_prepend(wifi->networks, network);
4396 if (name && name[0] != '\0')
4397 connman_network_set_name(network, name);
4399 connman_network_set_blob(network, "WiFi.SSID",
4401 #if defined TIZEN_EXT
4402 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4404 connman_network_set_vsie_list(network, vsie_list);
4406 DBG("vsie_list is NULL");
4407 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4408 connman_network_set_countrycode(network, country_code);
4409 phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
4410 connman_network_set_phy_mode(network, phy_mode);
4412 connman_network_set_string(network, "WiFi.Security", security);
4413 connman_network_set_strength(network,
4414 calculate_strength(supplicant_network));
4415 connman_network_set_bool(network, "WiFi.WPS", wps);
4418 /* Is AP advertizing for WPS association?
4419 * If so, we decide to use WPS by default */
4420 if (wps_ready && wps_pbc &&
4422 #if !defined TIZEN_EXT
4423 connman_network_set_bool(network, "WiFi.UseWPS", true);
4425 DBG("wps is activating by ap but ignore it.");
4430 connman_network_set_frequency(network,
4431 g_supplicant_network_get_frequency(supplicant_network));
4432 #if defined TIZEN_EXT
4433 connman_network_set_bssid(network,
4434 g_supplicant_network_get_bssid(supplicant_network));
4435 connman_network_set_maxrate(network,
4436 g_supplicant_network_get_maxrate(supplicant_network));
4437 connman_network_set_enc_mode(network,
4438 g_supplicant_network_get_enc_mode(supplicant_network));
4439 connman_network_set_rsn_mode(network,
4440 g_supplicant_network_get_rsn_mode(supplicant_network));
4441 connman_network_set_keymgmt(network,
4442 g_supplicant_network_get_keymgmt(supplicant_network));
4443 connman_network_set_bool(network, "WiFi.HS20AP",
4444 g_supplicant_network_is_hs20AP(supplicant_network));
4445 connman_network_set_bssid_list(network,
4446 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4448 connman_network_set_available(network, true);
4449 connman_network_set_string(network, "WiFi.Mode", mode);
4451 #if defined TIZEN_EXT
4456 connman_network_set_group(network, group);
4458 #if defined TIZEN_EXT
4459 if (wifi_first_scan == true)
4460 found_with_first_scan = true;
4463 if (wifi->hidden && ssid) {
4464 #if defined TIZEN_EXT
4465 if (network_security(wifi->hidden->security) ==
4466 network_security(security) &&
4468 if (!g_strcmp0(wifi->hidden->security, security) &&
4470 wifi->hidden->ssid_len == ssid_len &&
4471 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4472 connman_network_connect_hidden(network,
4473 wifi->hidden->identity,
4474 wifi->hidden->passphrase,
4475 wifi->hidden->user_data);
4476 wifi->hidden->user_data = NULL;
4477 hidden_free(wifi->hidden);
4478 wifi->hidden = NULL;
4483 static void network_removed(GSupplicantNetwork *network)
4485 GSupplicantInterface *interface;
4486 struct wifi_data *wifi;
4487 const char *name, *identifier;
4488 struct connman_network *connman_network;
4490 #if defined TIZEN_EXT_WIFI_MESH
4492 mode = g_supplicant_network_get_mode(network);
4493 if (!g_strcmp0(mode, "mesh")) {
4494 mesh_peer_removed(network);
4499 interface = g_supplicant_network_get_interface(network);
4500 wifi = g_supplicant_interface_get_data(interface);
4501 identifier = g_supplicant_network_get_identifier(network);
4502 name = g_supplicant_network_get_name(network);
4504 DBG("name %s", name);
4509 connman_network = connman_device_get_network(wifi->device, identifier);
4510 if (!connman_network)
4513 #if defined TIZEN_EXT
4514 if (connman_network == wifi->scan_pending_network)
4515 wifi->scan_pending_network = NULL;
4517 if (connman_network == wifi->pending_network)
4518 wifi->pending_network = NULL;
4520 if(connman_network_get_connecting(connman_network) == true){
4521 connman_network_set_connected(connman_network, false);
4525 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4527 connman_device_remove_network(wifi->device, connman_network);
4528 connman_network_unref(connman_network);
4531 static void network_changed(GSupplicantNetwork *network, const char *property)
4533 GSupplicantInterface *interface;
4534 struct wifi_data *wifi;
4535 const char *name, *identifier;
4536 struct connman_network *connman_network;
4538 #if defined TIZEN_EXT
4539 const unsigned char *bssid;
4540 unsigned int maxrate;
4543 const unsigned char *country_code;
4544 ieee80211_modes_e phy_mode;
4548 interface = g_supplicant_network_get_interface(network);
4549 wifi = g_supplicant_interface_get_data(interface);
4550 identifier = g_supplicant_network_get_identifier(network);
4551 name = g_supplicant_network_get_name(network);
4553 DBG("name %s", name);
4558 connman_network = connman_device_get_network(wifi->device, identifier);
4559 if (!connman_network)
4562 if (g_str_equal(property, "Signal")) {
4563 connman_network_set_strength(connman_network,
4564 calculate_strength(network));
4565 connman_network_update(connman_network);
4568 #if defined TIZEN_EXT
4569 bssid = g_supplicant_network_get_bssid(network);
4570 maxrate = g_supplicant_network_get_maxrate(network);
4571 frequency = g_supplicant_network_get_frequency(network);
4572 wps = g_supplicant_network_get_wps(network);
4573 phy_mode = g_supplicant_network_get_phy_mode(network);
4575 connman_network_set_bssid(connman_network, bssid);
4576 connman_network_set_maxrate(connman_network, maxrate);
4577 connman_network_set_frequency(connman_network, frequency);
4578 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4579 country_code = g_supplicant_network_get_countrycode(network);
4580 connman_network_set_countrycode(connman_network, country_code);
4581 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4582 connman_network_set_bssid_list(connman_network, bssid_list);
4583 connman_network_set_phy_mode(connman_network, phy_mode);
4587 static void network_associated(GSupplicantNetwork *network)
4589 GSupplicantInterface *interface;
4590 struct wifi_data *wifi;
4591 struct connman_network *connman_network;
4592 const char *identifier;
4596 interface = g_supplicant_network_get_interface(network);
4600 wifi = g_supplicant_interface_get_data(interface);
4604 identifier = g_supplicant_network_get_identifier(network);
4606 connman_network = connman_device_get_network(wifi->device, identifier);
4607 if (!connman_network)
4610 if (wifi->network) {
4611 if (wifi->network == connman_network)
4615 * This should never happen, we got associated with
4616 * a network different than the one we were expecting.
4618 DBG("Associated to %p while expecting %p",
4619 connman_network, wifi->network);
4621 connman_network_set_associating(wifi->network, false);
4624 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4626 wifi->network = connman_network_ref(connman_network);
4630 * Interface state changes callback (interface_state) is always
4631 * called before network_associated callback thus we need to call
4632 * interface_state again in order to process the new state now that
4633 * we have the network properly set.
4635 interface_state(interface);
4638 static void apply_peer_services(GSupplicantPeer *peer,
4639 struct connman_peer *connman_peer)
4641 const unsigned char *data;
4646 connman_peer_reset_services(connman_peer);
4648 data = g_supplicant_peer_get_widi_ies(peer, &length);
4650 connman_peer_add_service(connman_peer,
4651 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4655 static void add_station(const char *mac)
4657 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4661 static void remove_station(const char *mac)
4663 connman_technology_tethering_remove_station(mac);
4666 static void peer_found(GSupplicantPeer *peer)
4668 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4669 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4670 struct connman_peer *connman_peer;
4671 const char *identifier, *name;
4673 #if defined TIZEN_EXT
4677 identifier = g_supplicant_peer_get_identifier(peer);
4678 name = g_supplicant_peer_get_name(peer);
4680 DBG("ident: %s", identifier);
4682 connman_peer = connman_peer_get(wifi->device, identifier);
4686 connman_peer = connman_peer_create(identifier);
4687 connman_peer_set_name(connman_peer, name);
4688 connman_peer_set_device(connman_peer, wifi->device);
4689 apply_peer_services(peer, connman_peer);
4691 ret = connman_peer_register(connman_peer);
4692 if (ret < 0 && ret != -EALREADY)
4693 connman_peer_unref(connman_peer);
4695 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4698 static void peer_lost(GSupplicantPeer *peer)
4700 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4701 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4702 struct connman_peer *connman_peer;
4703 const char *identifier;
4708 identifier = g_supplicant_peer_get_identifier(peer);
4710 DBG("ident: %s", identifier);
4712 connman_peer = connman_peer_get(wifi->device, identifier);
4714 if (wifi->p2p_connecting &&
4715 wifi->pending_peer == connman_peer) {
4716 peer_connect_timeout(wifi);
4718 connman_peer_unregister(connman_peer);
4719 connman_peer_unref(connman_peer);
4722 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4725 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4727 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4728 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4729 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4730 struct connman_peer *connman_peer;
4731 const char *identifier;
4733 identifier = g_supplicant_peer_get_identifier(peer);
4735 DBG("ident: %s", identifier);
4740 connman_peer = connman_peer_get(wifi->device, identifier);
4745 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4746 apply_peer_services(peer, connman_peer);
4747 connman_peer_services_changed(connman_peer);
4749 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4750 if (!g_supplicant_peer_is_in_a_group(peer))
4751 p_state = CONNMAN_PEER_STATE_IDLE;
4753 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4755 case G_SUPPLICANT_PEER_GROUP_STARTED:
4757 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4758 p_state = CONNMAN_PEER_STATE_IDLE;
4760 case G_SUPPLICANT_PEER_GROUP_JOINED:
4761 connman_peer_set_iface_address(connman_peer,
4762 g_supplicant_peer_get_iface_address(peer));
4764 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4765 p_state = CONNMAN_PEER_STATE_IDLE;
4767 case G_SUPPLICANT_PEER_GROUP_FAILED:
4768 if (g_supplicant_peer_has_requested_connection(peer))
4769 p_state = CONNMAN_PEER_STATE_IDLE;
4771 p_state = CONNMAN_PEER_STATE_FAILURE;
4775 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4776 p_state == CONNMAN_PEER_STATE_FAILURE) {
4777 if (wifi->p2p_connecting
4778 && connman_peer == wifi->pending_peer)
4779 peer_cancel_timeout(wifi);
4781 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4784 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4787 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4788 GSupplicantInterface *g_iface;
4789 struct wifi_data *g_wifi;
4791 g_iface = g_supplicant_peer_get_group_interface(peer);
4795 g_wifi = g_supplicant_interface_get_data(g_iface);
4799 connman_peer_set_as_master(connman_peer,
4800 !g_supplicant_peer_is_client(peer));
4801 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4804 * If wpa_supplicant didn't create a dedicated p2p-group
4805 * interface then mark this interface as p2p_device to avoid
4806 * scan and auto-scan are launched on it while P2P is connected.
4808 if (!g_list_find(p2p_iface_list, g_wifi))
4809 wifi->p2p_device = true;
4812 connman_peer_set_state(connman_peer, p_state);
4815 static void peer_request(GSupplicantPeer *peer)
4817 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4818 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4819 struct connman_peer *connman_peer;
4820 const char *identifier;
4822 #if defined TIZEN_EXT
4827 identifier = g_supplicant_peer_get_identifier(peer);
4829 DBG("ident: %s", identifier);
4831 connman_peer = connman_peer_get(wifi->device, identifier);
4835 connman_peer_request_connection(connman_peer);
4838 #if defined TIZEN_EXT
4839 static void system_power_off(void)
4842 struct wifi_data *wifi;
4843 struct connman_service *service;
4844 struct connman_ipconfig *ipconfig_ipv4;
4846 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4847 for (list = iface_list; list; list = list->next) {
4850 if (wifi->network != NULL) {
4851 service = connman_service_lookup_from_network(wifi->network);
4852 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4853 __connman_dhcp_stop(ipconfig_ipv4);
4859 static void network_merged(GSupplicantNetwork *network)
4861 GSupplicantInterface *interface;
4862 GSupplicantState state;
4863 struct wifi_data *wifi;
4864 const char *identifier;
4865 struct connman_network *connman_network;
4869 interface = g_supplicant_network_get_interface(network);
4873 state = g_supplicant_interface_get_state(interface);
4874 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4877 wifi = g_supplicant_interface_get_data(interface);
4881 identifier = g_supplicant_network_get_identifier(network);
4883 connman_network = connman_device_get_network(wifi->device, identifier);
4884 if (!connman_network)
4887 DBG("merged identifier %s", identifier);
4889 if (wifi->connected == FALSE) {
4891 case G_SUPPLICANT_STATE_AUTHENTICATING:
4892 case G_SUPPLICANT_STATE_ASSOCIATING:
4893 case G_SUPPLICANT_STATE_ASSOCIATED:
4894 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4895 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4896 connman_network_set_associating(connman_network, TRUE);
4898 case G_SUPPLICANT_STATE_COMPLETED:
4899 connman_network_set_connected(connman_network, TRUE);
4902 DBG("Not handled the state : %d", state);
4907 ishs20AP = g_supplicant_network_is_hs20AP(network);
4910 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
4911 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
4912 connman_network_set_string(connman_network, "WiFi.EAP",
4914 connman_network_set_string(connman_network, "WiFi.Identity",
4915 g_supplicant_network_get_identity(network));
4916 connman_network_set_string(connman_network, "WiFi.Phase2",
4917 g_supplicant_network_get_phase2(network));
4922 wifi->network = connman_network;
4925 static void assoc_failed(void *user_data)
4927 struct connman_network *network = user_data;
4928 connman_network_set_associating(network, false);
4932 static void debug(const char *str)
4934 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
4935 connman_debug("%s", str);
4938 static void disconnect_reasoncode(GSupplicantInterface *interface,
4941 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4944 wifi->disconnect_code = reasoncode;
4948 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
4950 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4953 wifi->assoc_code = status_code;
4957 static const GSupplicantCallbacks callbacks = {
4958 .system_ready = system_ready,
4959 .system_killed = system_killed,
4960 .interface_added = interface_added,
4961 .interface_state = interface_state,
4962 .interface_removed = interface_removed,
4963 .p2p_support = p2p_support,
4964 .scan_started = scan_started,
4965 .scan_finished = scan_finished,
4966 .ap_create_fail = ap_create_fail,
4967 .network_added = network_added,
4968 .network_removed = network_removed,
4969 .network_changed = network_changed,
4970 .network_associated = network_associated,
4971 .add_station = add_station,
4972 .remove_station = remove_station,
4973 .peer_found = peer_found,
4974 .peer_lost = peer_lost,
4975 .peer_changed = peer_changed,
4976 .peer_request = peer_request,
4977 #if defined TIZEN_EXT
4978 .system_power_off = system_power_off,
4979 .network_merged = network_merged,
4980 .assoc_failed = assoc_failed,
4983 .disconnect_reasoncode = disconnect_reasoncode,
4984 .assoc_status_code = assoc_status_code,
4985 #if defined TIZEN_EXT_WIFI_MESH
4986 .mesh_support = mesh_support,
4987 .mesh_group_started = mesh_group_started,
4988 .mesh_group_removed = mesh_group_removed,
4989 .mesh_peer_connected = mesh_peer_connected,
4990 .mesh_peer_disconnected = mesh_peer_disconnected,
4995 static int tech_probe(struct connman_technology *technology)
4997 wifi_technology = technology;
5002 static void tech_remove(struct connman_technology *technology)
5004 wifi_technology = NULL;
5007 static GSupplicantSSID *ssid_ap_init(const char *ssid,
5008 const char *passphrase)
5010 GSupplicantSSID *ap;
5012 ap = g_try_malloc0(sizeof(GSupplicantSSID));
5016 ap->mode = G_SUPPLICANT_MODE_MASTER;
5017 #if defined TIZEN_EXT
5018 ap->ssid = (void *) ssid;
5022 ap->ssid_len = strlen(ssid);
5026 if (!passphrase || strlen(passphrase) == 0) {
5027 ap->security = G_SUPPLICANT_SECURITY_NONE;
5028 ap->passphrase = NULL;
5030 ap->security = G_SUPPLICANT_SECURITY_PSK;
5031 ap->protocol = G_SUPPLICANT_PROTO_RSN;
5032 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
5033 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
5034 ap->passphrase = passphrase;
5040 static void ap_start_callback(int result, GSupplicantInterface *interface,
5043 struct wifi_tethering_info *info = user_data;
5045 DBG("result %d index %d bridge %s",
5046 result, info->wifi->index, info->wifi->bridge);
5048 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5049 connman_inet_remove_from_bridge(info->wifi->index,
5050 info->wifi->bridge);
5052 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5053 connman_technology_tethering_notify(info->technology, false);
5054 g_free(info->wifi->tethering_param->ssid);
5055 g_free(info->wifi->tethering_param);
5056 info->wifi->tethering_param = NULL;
5060 g_free(info->ifname);
5064 static void ap_create_callback(int result,
5065 GSupplicantInterface *interface,
5068 struct wifi_tethering_info *info = user_data;
5070 DBG("result %d ifname %s", result,
5071 g_supplicant_interface_get_ifname(interface));
5073 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5074 connman_inet_remove_from_bridge(info->wifi->index,
5075 info->wifi->bridge);
5077 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5078 connman_technology_tethering_notify(info->technology, false);
5079 g_free(info->wifi->tethering_param->ssid);
5080 g_free(info->wifi->tethering_param);
5081 info->wifi->tethering_param = NULL;
5085 g_free(info->ifname);
5091 info->wifi->interface = interface;
5092 g_supplicant_interface_set_data(interface, info->wifi);
5094 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5095 connman_error("Failed to set interface ap_scan property");
5097 g_supplicant_interface_connect(interface, info->ssid,
5098 ap_start_callback, info);
5101 static void sta_remove_callback(int result,
5102 GSupplicantInterface *interface,
5105 struct wifi_tethering_info *info = user_data;
5106 const char *driver = connman_option_get_string("wifi");
5108 DBG("ifname %s result %d ", info->ifname, result);
5110 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5111 info->wifi->tethering = false;
5112 connman_technology_tethering_notify(info->technology, false);
5114 g_free(info->ifname);
5118 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5119 g_free(info->wifi->tethering_param->ssid);
5120 g_free(info->wifi->tethering_param);
5121 info->wifi->tethering_param = NULL;
5126 info->wifi->interface = NULL;
5128 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5133 static int enable_wifi_tethering(struct connman_technology *technology,
5134 const char *bridge, const char *identifier,
5135 const char *passphrase, bool available)
5138 GSupplicantInterface *interface;
5139 struct wifi_data *wifi;
5140 struct wifi_tethering_info *info;
5145 for (list = iface_list; list; list = list->next) {
5148 DBG("wifi %p network %p pending_network %p", wifi,
5149 wifi->network, wifi->pending_network);
5151 interface = wifi->interface;
5156 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5159 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5161 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5162 DBG("%s does not support AP mode (detected)", ifname);
5166 mode = g_supplicant_interface_get_mode(interface);
5167 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5168 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5169 DBG("%s does not support AP mode (capability)", ifname);
5173 if (wifi->network && available)
5176 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5180 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5181 if (!wifi->tethering_param) {
5187 info->technology = technology;
5188 info->wifi->bridge = bridge;
5189 info->ssid = ssid_ap_init(identifier, passphrase);
5193 info->ifname = g_strdup(ifname);
5197 wifi->tethering_param->technology = technology;
5198 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5199 if (!wifi->tethering_param->ssid)
5202 info->wifi->tethering = true;
5203 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5205 berr = connman_technology_tethering_notify(technology, true);
5209 err = g_supplicant_interface_remove(interface,
5210 sta_remove_callback,
5213 DBG("tethering wifi %p ifname %s", wifi, ifname);
5218 g_free(info->ifname);
5221 g_free(wifi->tethering_param);
5222 wifi->tethering_param = NULL;
5225 * Remove bridge if it was correctly created but remove
5226 * operation failed. Instead, if bridge creation failed then
5227 * break out and do not try again on another interface,
5228 * bridge set-up does not depend on it.
5231 connman_technology_tethering_notify(technology, false);
5239 static int tech_set_tethering(struct connman_technology *technology,
5240 const char *identifier, const char *passphrase,
5241 const char *bridge, bool enabled)
5244 struct wifi_data *wifi;
5250 for (list = iface_list; list; list = list->next) {
5253 if (wifi->tethering) {
5254 wifi->tethering = false;
5256 connman_inet_remove_from_bridge(wifi->index,
5258 wifi->bridged = false;
5262 connman_technology_tethering_notify(technology, false);
5267 DBG("trying tethering for available devices");
5268 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5272 DBG("trying tethering for any device");
5273 err = enable_wifi_tethering(technology, bridge, identifier,
5280 static void regdom_callback(int result, const char *alpha2, void *user_data)
5284 if (!wifi_technology)
5290 connman_technology_regdom_notify(wifi_technology, alpha2);
5293 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5295 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5298 static struct connman_technology_driver tech_driver = {
5300 .type = CONNMAN_SERVICE_TYPE_WIFI,
5301 .probe = tech_probe,
5302 .remove = tech_remove,
5303 .set_tethering = tech_set_tethering,
5304 .set_regdom = tech_set_regdom,
5307 static int wifi_init(void)
5311 err = connman_network_driver_register(&network_driver);
5315 err = g_supplicant_register(&callbacks);
5317 connman_network_driver_unregister(&network_driver);
5321 err = connman_technology_driver_register(&tech_driver);
5323 g_supplicant_unregister(&callbacks);
5324 connman_network_driver_unregister(&network_driver);
5331 static void wifi_exit(void)
5335 connman_technology_driver_unregister(&tech_driver);
5337 g_supplicant_unregister(&callbacks);
5339 connman_network_driver_unregister(&network_driver);
5342 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5343 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)