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 signalpoll_callback(int result, int maxspeed, void *user_data)
3434 struct connman_network *network = user_data;
3437 DBG("Failed to get maxspeed from signalpoll !");
3441 DBG("maxspeed = %d", maxspeed);
3443 connman_network_set_maxspeed(network, maxspeed);
3446 static int network_signalpoll(struct connman_network *network)
3448 struct connman_device *device = connman_network_get_device(network);
3449 struct wifi_data *wifi;
3450 GSupplicantInterface *interface;
3452 DBG("network %p", network);
3453 wifi = connman_device_get_data(device);
3458 interface = wifi->interface;
3460 return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
3463 static gboolean autosignalpoll_timeout(gpointer data)
3465 struct connman_network *network = data;
3468 automaxspeed_timeout = 0;
3469 ret = network_signalpoll(network);
3472 DBG("Fail to get max speed !!");
3476 automaxspeed_timeout = g_timeout_add_seconds(30, autosignalpoll_timeout, network);
3482 static struct connman_network_driver network_driver = {
3484 .type = CONNMAN_NETWORK_TYPE_WIFI,
3485 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3486 .probe = network_probe,
3487 .remove = network_remove,
3488 .connect = network_connect,
3489 .disconnect = network_disconnect,
3492 static void interface_added(GSupplicantInterface *interface)
3494 const char *ifname = g_supplicant_interface_get_ifname(interface);
3495 const char *driver = g_supplicant_interface_get_driver(interface);
3496 struct wifi_data *wifi;
3498 wifi = g_supplicant_interface_get_data(interface);
3500 wifi = get_pending_wifi_data(ifname);
3504 wifi->interface = interface;
3505 g_supplicant_interface_set_data(interface, wifi);
3506 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3507 wifi->p2p_device = true;
3510 DBG("ifname %s driver %s wifi %p tethering %d",
3511 ifname, driver, wifi, wifi->tethering);
3513 if (!wifi->device) {
3514 connman_error("WiFi device not set");
3518 connman_device_set_powered(wifi->device, true);
3521 static bool is_idle(struct wifi_data *wifi)
3523 DBG("state %d", wifi->state);
3525 switch (wifi->state) {
3526 case G_SUPPLICANT_STATE_UNKNOWN:
3527 case G_SUPPLICANT_STATE_DISABLED:
3528 case G_SUPPLICANT_STATE_DISCONNECTED:
3529 case G_SUPPLICANT_STATE_INACTIVE:
3530 case G_SUPPLICANT_STATE_SCANNING:
3533 case G_SUPPLICANT_STATE_AUTHENTICATING:
3534 case G_SUPPLICANT_STATE_ASSOCIATING:
3535 case G_SUPPLICANT_STATE_ASSOCIATED:
3536 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3537 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3538 case G_SUPPLICANT_STATE_COMPLETED:
3545 static bool is_idle_wps(GSupplicantInterface *interface,
3546 struct wifi_data *wifi)
3548 /* First, let's check if WPS processing did not went wrong */
3549 if (g_supplicant_interface_get_wps_state(interface) ==
3550 G_SUPPLICANT_WPS_STATE_FAIL)
3553 /* Unlike normal connection, being associated while processing wps
3554 * actually means that we are idling. */
3555 switch (wifi->state) {
3556 case G_SUPPLICANT_STATE_UNKNOWN:
3557 case G_SUPPLICANT_STATE_DISABLED:
3558 case G_SUPPLICANT_STATE_DISCONNECTED:
3559 case G_SUPPLICANT_STATE_INACTIVE:
3560 case G_SUPPLICANT_STATE_SCANNING:
3561 case G_SUPPLICANT_STATE_ASSOCIATED:
3563 case G_SUPPLICANT_STATE_AUTHENTICATING:
3564 case G_SUPPLICANT_STATE_ASSOCIATING:
3565 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3566 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3567 case G_SUPPLICANT_STATE_COMPLETED:
3574 static bool handle_wps_completion(GSupplicantInterface *interface,
3575 struct connman_network *network,
3576 struct connman_device *device,
3577 struct wifi_data *wifi)
3581 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3583 const unsigned char *ssid, *wps_ssid;
3584 unsigned int ssid_len, wps_ssid_len;
3585 const char *wps_key;
3587 /* Checking if we got associated with requested
3589 ssid = connman_network_get_blob(network, "WiFi.SSID",
3592 wps_ssid = g_supplicant_interface_get_wps_ssid(
3593 interface, &wps_ssid_len);
3595 if (!wps_ssid || wps_ssid_len != ssid_len ||
3596 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3597 connman_network_set_associating(network, false);
3598 #if defined TIZEN_EXT
3599 g_supplicant_interface_disconnect(wifi->interface,
3600 disconnect_callback, wifi->network);
3602 connman_network_set_bool(network, "WiFi.UseWPS", false);
3603 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3605 g_supplicant_interface_disconnect(wifi->interface,
3606 disconnect_callback, wifi);
3611 wps_key = g_supplicant_interface_get_wps_key(interface);
3612 #if defined TIZEN_EXT
3613 /* Check the passphrase and encrypt it
3616 gchar *passphrase = g_strdup(wps_key);
3618 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3620 if (check_passphrase_ext(network, passphrase) < 0) {
3621 DBG("[WPS] Invalid passphrase");
3626 ret = send_encryption_request(passphrase, network);
3631 DBG("[WPS] Encryption request succeeded");
3633 DBG("[WPS] Encryption request failed %d", ret);
3636 connman_network_set_string(network, "WiFi.Passphrase",
3639 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3646 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3647 struct wifi_data *wifi)
3649 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3650 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3651 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3652 wifi->load_shaping_retries ++;
3655 wifi->load_shaping_retries = 0;
3659 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3660 struct connman_network *network,
3661 struct wifi_data *wifi)
3663 #if defined TIZEN_EXT
3664 const char *security;
3665 struct connman_service *service;
3667 if (wifi->connected)
3670 security = connman_network_get_string(network, "WiFi.Security");
3672 if (security && g_str_equal(security, "ieee8021x") == true &&
3673 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3675 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3680 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3683 struct connman_service *service;
3685 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3688 if (wifi->connected)
3692 service = connman_service_lookup_from_network(network);
3698 if (connman_service_get_favorite(service)) {
3699 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3704 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3709 #if defined TIZEN_EXT
3710 static bool handle_wifi_assoc_retry(struct connman_network *network,
3711 struct wifi_data *wifi)
3713 const char *security;
3715 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3716 connman_network_get_connecting(network) != true) {
3717 wifi->assoc_retry_count = 0;
3721 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3722 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3723 wifi->assoc_retry_count = 0;
3727 security = connman_network_get_string(network, "WiFi.Security");
3728 if (security && g_str_equal(security, "ieee8021x") == true &&
3729 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3730 wifi->assoc_retry_count = 0;
3734 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3735 wifi->assoc_retry_count = 0;
3737 /* Honestly it's not an invalid-key error,
3738 * however QA team recommends that the invalid-key error
3739 * might be better to display for user experience.
3741 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3750 static void interface_state(GSupplicantInterface *interface)
3752 struct connman_network *network;
3753 struct connman_device *device;
3754 struct wifi_data *wifi;
3755 GSupplicantState state = g_supplicant_interface_get_state(interface);
3759 wifi = g_supplicant_interface_get_data(interface);
3761 DBG("wifi %p interface state %d", wifi, state);
3766 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3767 if (wifi->tethering_param) {
3768 g_free(wifi->tethering_param->ssid);
3769 g_free(wifi->tethering_param);
3770 wifi->tethering_param = NULL;
3774 device = wifi->device;
3778 if (g_supplicant_interface_get_ready(interface) &&
3779 !wifi->interface_ready) {
3780 wifi->interface_ready = true;
3781 finalize_interface_creation(wifi);
3784 network = wifi->network;
3789 case G_SUPPLICANT_STATE_SCANNING:
3790 if (wifi->connected)
3791 connman_network_set_connected(network, false);
3795 case G_SUPPLICANT_STATE_AUTHENTICATING:
3796 case G_SUPPLICANT_STATE_ASSOCIATING:
3797 #if defined TIZEN_EXT
3798 reset_autoscan(device);
3800 stop_autoscan(device);
3803 if (!wifi->connected)
3804 connman_network_set_associating(network, true);
3808 case G_SUPPLICANT_STATE_COMPLETED:
3809 #if defined TIZEN_EXT
3810 /* though it should be already reset: */
3811 reset_autoscan(device);
3813 wifi->assoc_retry_count = 0;
3815 wifi->scan_pending_network = NULL;
3817 /* should be cleared scanning flag */
3818 bool scanning = connman_device_get_scanning(device);
3820 connman_device_set_scanning(device,
3821 CONNMAN_SERVICE_TYPE_WIFI, false);
3822 connman_device_unref(device);
3825 if (!automaxspeed_timeout) {
3826 DBG("Going to start signalpoll timer!!");
3827 autosignalpoll_timeout(network);
3830 /* though it should be already stopped: */
3831 stop_autoscan(device);
3834 if (!handle_wps_completion(interface, network, device, wifi))
3837 connman_network_set_connected(network, true);
3839 wifi->disconnect_code = 0;
3840 wifi->assoc_code = 0;
3841 wifi->load_shaping_retries = 0;
3844 case G_SUPPLICANT_STATE_DISCONNECTED:
3845 #if defined TIZEN_EXT
3846 connman_network_set_maxspeed(network, 0);
3848 if (automaxspeed_timeout != 0) {
3849 g_source_remove(automaxspeed_timeout);
3850 automaxspeed_timeout = 0;
3851 DBG("Remove signalpoll timer!!");
3855 * If we're in one of the idle modes, we have
3856 * not started association yet and thus setting
3857 * those ones to FALSE could cancel an association
3860 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3862 if (is_idle_wps(interface, wifi))
3868 if (handle_assoc_status_code(interface, wifi))
3871 /* If previous state was 4way-handshake, then
3872 * it's either: psk was incorrect and thus we retry
3873 * or if we reach the maximum retries we declare the
3875 if (handle_4way_handshake_failure(interface,
3879 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3880 switch (wifi->disconnect_code) {
3881 case 1: /* Unspecified reason */
3882 /* Let's assume it's because we got blocked */
3884 case 6: /* Class 2 frame received from nonauthenticated STA */
3885 connman_network_set_error(network,
3886 CONNMAN_NETWORK_ERROR_BLOCKED);
3893 #if defined TIZEN_EXT
3894 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3895 * Retry association until its retry count is expired */
3896 if (handle_wifi_assoc_retry(network, wifi) == true) {
3897 throw_wifi_scan(wifi->device, scan_callback);
3898 wifi->scan_pending_network = wifi->network;
3902 if(wifi->disconnect_code > 0){
3903 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3904 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3908 connman_network_set_connected(network, false);
3909 connman_network_set_associating(network, false);
3910 wifi->disconnecting = false;
3912 start_autoscan(device);
3916 case G_SUPPLICANT_STATE_INACTIVE:
3917 #if defined TIZEN_EXT
3918 if (handle_wps_completion(interface, network, device, wifi) == false)
3921 connman_network_set_associating(network, false);
3922 start_autoscan(device);
3926 case G_SUPPLICANT_STATE_UNKNOWN:
3927 case G_SUPPLICANT_STATE_DISABLED:
3928 case G_SUPPLICANT_STATE_ASSOCIATED:
3929 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3930 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3934 old_connected = wifi->connected;
3935 wifi->state = state;
3937 /* Saving wpa_s state policy:
3938 * If connected and if the state changes are roaming related:
3939 * --> We stay connected
3941 * --> We are connected
3943 * --> We are not connected
3946 case G_SUPPLICANT_STATE_AUTHENTICATING:
3947 case G_SUPPLICANT_STATE_ASSOCIATING:
3948 case G_SUPPLICANT_STATE_ASSOCIATED:
3949 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3950 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3951 if (wifi->connected)
3952 connman_warn("Probably roaming right now!"
3953 " Staying connected...");
3955 case G_SUPPLICANT_STATE_SCANNING:
3956 wifi->connected = false;
3959 start_autoscan(device);
3961 case G_SUPPLICANT_STATE_COMPLETED:
3962 wifi->connected = true;
3965 wifi->connected = false;
3972 static void interface_removed(GSupplicantInterface *interface)
3974 const char *ifname = g_supplicant_interface_get_ifname(interface);
3975 struct wifi_data *wifi;
3977 DBG("ifname %s", ifname);
3979 wifi = g_supplicant_interface_get_data(interface);
3981 #if defined TIZEN_EXT_WIFI_MESH
3982 if (wifi && wifi->mesh_interface) {
3983 DBG("Notify mesh interface remove");
3984 connman_mesh_notify_interface_remove(true);
3985 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
3986 g_free(mesh_info->parent_ifname);
3987 g_free(mesh_info->ifname);
3988 g_free(mesh_info->identifier);
3990 wifi->mesh_interface = false;
3991 wifi->mesh_info = NULL;
3997 wifi->interface = NULL;
3999 if (wifi && wifi->tethering)
4002 if (!wifi || !wifi->device) {
4003 DBG("wifi interface already removed");
4007 connman_device_set_powered(wifi->device, false);
4009 check_p2p_technology();
4010 #if defined TIZEN_EXT_WIFI_MESH
4011 check_mesh_technology();
4015 static void set_device_type(const char *type, char dev_type[17])
4017 const char *oui = "0050F204";
4018 const char *category = "0001";
4019 const char *sub_category = "0000";
4021 if (!g_strcmp0(type, "handset")) {
4023 sub_category = "0005";
4024 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
4025 sub_category = "0001";
4026 else if (!g_strcmp0(type, "server"))
4027 sub_category = "0002";
4028 else if (!g_strcmp0(type, "laptop"))
4029 sub_category = "0005";
4030 else if (!g_strcmp0(type, "desktop"))
4031 sub_category = "0006";
4032 else if (!g_strcmp0(type, "tablet"))
4033 sub_category = "0009";
4034 else if (!g_strcmp0(type, "watch"))
4037 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
4040 static void p2p_support(GSupplicantInterface *interface)
4042 char dev_type[17] = {};
4043 const char *hostname;
4050 if (!g_supplicant_interface_has_p2p(interface))
4053 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
4054 DBG("Could not register P2P technology driver");
4058 hostname = connman_utsname_get_hostname();
4060 hostname = "ConnMan";
4062 set_device_type(connman_machine_get_type(), dev_type);
4063 g_supplicant_interface_set_p2p_device_config(interface,
4064 hostname, dev_type);
4065 connman_peer_driver_register(&peer_driver);
4068 static void scan_started(GSupplicantInterface *interface)
4073 static void scan_finished(GSupplicantInterface *interface)
4075 #if defined TIZEN_EXT
4076 struct wifi_data *wifi;
4077 bool is_associating = false;
4078 static bool is_scanning = true;
4083 #if defined TIZEN_EXT
4084 wifi = g_supplicant_interface_get_data(interface);
4085 if (wifi && wifi->scan_pending_network) {
4086 network_connect(wifi->scan_pending_network);
4087 wifi->scan_pending_network = NULL;
4090 //service state - associating
4091 if(!wifi || !wifi->network)
4094 is_associating = connman_network_get_associating(wifi->network);
4095 if(is_associating && is_scanning){
4096 is_scanning = false;
4097 DBG("send scan for connecting");
4098 throw_wifi_scan(wifi->device, scan_callback);
4109 static void ap_create_fail(GSupplicantInterface *interface)
4111 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4114 if ((wifi->tethering) && (wifi->tethering_param)) {
4115 DBG("%s create AP fail \n",
4116 g_supplicant_interface_get_ifname(wifi->interface));
4118 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4119 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4120 wifi->tethering = false;
4122 ret = tech_set_tethering(wifi->tethering_param->technology,
4123 wifi->tethering_param->ssid->ssid,
4124 wifi->tethering_param->ssid->passphrase,
4125 wifi->bridge, true);
4127 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4128 connman_technology_tethering_notify(wifi_technology,false);
4131 g_free(wifi->tethering_param->ssid);
4132 g_free(wifi->tethering_param);
4133 wifi->tethering_param = NULL;
4139 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4141 unsigned char strength;
4143 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4145 #if !defined TIZEN_EXT
4152 #if defined TIZEN_EXT_WIFI_MESH
4153 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4155 GSupplicantInterface *interface;
4156 struct wifi_data *wifi;
4157 const char *name, *security;
4158 struct connman_mesh *connman_mesh;
4159 struct wifi_mesh_info *mesh_info;
4160 const unsigned char *bssid;
4161 const char *identifier;
4166 interface = g_supplicant_network_get_interface(supplicant_network);
4167 wifi = g_supplicant_interface_get_data(interface);
4168 if (!wifi || !wifi->mesh_interface) {
4169 DBG("Virtual Mesh interface not created");
4173 bssid = g_supplicant_network_get_bssid(supplicant_network);
4174 address = g_malloc0(19);
4175 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4176 bssid[2], bssid[3], bssid[4], bssid[5]);
4178 identifier = g_supplicant_network_get_identifier(supplicant_network);
4179 name = g_supplicant_network_get_name(supplicant_network);
4180 security = g_supplicant_network_get_security(supplicant_network);
4181 frequency = g_supplicant_network_get_frequency(supplicant_network);
4183 mesh_info = wifi->mesh_info;
4184 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4188 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4190 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4191 connman_mesh_set_name(connman_mesh, name);
4192 connman_mesh_set_security(connman_mesh, security);
4193 connman_mesh_set_frequency(connman_mesh, frequency);
4194 connman_mesh_set_address(connman_mesh, address);
4195 connman_mesh_set_index(connman_mesh, mesh_info->index);
4196 connman_mesh_set_strength(connman_mesh,
4197 calculate_strength(supplicant_network));
4198 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4200 ret = connman_mesh_register(connman_mesh);
4201 if (ret == -EALREADY)
4202 DBG("Mesh Peer is already registered");
4208 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4210 GSupplicantInterface *interface;
4211 struct wifi_data *wifi;
4212 struct connman_mesh *connman_mesh;
4213 struct wifi_mesh_info *mesh_info;
4214 const char *identifier;
4216 interface = g_supplicant_network_get_interface(supplicant_network);
4217 wifi = g_supplicant_interface_get_data(interface);
4218 if (!wifi || !wifi->mesh_interface) {
4219 DBG("Virtual Mesh interface not created");
4223 identifier = g_supplicant_network_get_identifier(supplicant_network);
4225 DBG("Failed to get Mesh Peer identifier");
4229 mesh_info = wifi->mesh_info;
4230 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4232 /* Do not unregister connected mesh peer */
4233 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4234 DBG("Mesh Peer %s is connected", identifier);
4237 DBG("Mesh Peer identifier %s removed", identifier);
4238 connman_mesh_unregister(connman_mesh);
4243 static void network_added(GSupplicantNetwork *supplicant_network)
4245 struct connman_network *network;
4246 GSupplicantInterface *interface;
4247 struct wifi_data *wifi;
4248 const char *name, *identifier, *security, *group, *mode;
4249 const unsigned char *ssid;
4250 unsigned int ssid_len;
4254 bool wps_advertizing;
4256 #if defined TIZEN_EXT
4257 GSList *vsie_list = NULL;
4258 const unsigned char *country_code;
4261 mode = g_supplicant_network_get_mode(supplicant_network);
4262 identifier = g_supplicant_network_get_identifier(supplicant_network);
4264 DBG("%s", identifier);
4266 if (!g_strcmp0(mode, "adhoc"))
4269 #if defined TIZEN_EXT_WIFI_MESH
4270 if (!g_strcmp0(mode, "mesh")) {
4271 mesh_peer_added(supplicant_network);
4276 interface = g_supplicant_network_get_interface(supplicant_network);
4277 wifi = g_supplicant_interface_get_data(interface);
4278 name = g_supplicant_network_get_name(supplicant_network);
4279 security = g_supplicant_network_get_security(supplicant_network);
4280 group = g_supplicant_network_get_identifier(supplicant_network);
4281 wps = g_supplicant_network_get_wps(supplicant_network);
4282 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4283 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4284 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4285 supplicant_network);
4290 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4292 network = connman_device_get_network(wifi->device, identifier);
4295 network = connman_network_create(identifier,
4296 CONNMAN_NETWORK_TYPE_WIFI);
4300 connman_network_set_index(network, wifi->index);
4302 if (connman_device_add_network(wifi->device, network) < 0) {
4303 connman_network_unref(network);
4307 wifi->networks = g_slist_prepend(wifi->networks, network);
4310 if (name && name[0] != '\0')
4311 connman_network_set_name(network, name);
4313 connman_network_set_blob(network, "WiFi.SSID",
4315 #if defined TIZEN_EXT
4316 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4318 connman_network_set_vsie_list(network, vsie_list);
4320 DBG("vsie_list is NULL");
4321 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4322 connman_network_set_countrycode(network, country_code);
4324 connman_network_set_string(network, "WiFi.Security", security);
4325 connman_network_set_strength(network,
4326 calculate_strength(supplicant_network));
4327 connman_network_set_bool(network, "WiFi.WPS", wps);
4330 /* Is AP advertizing for WPS association?
4331 * If so, we decide to use WPS by default */
4332 if (wps_ready && wps_pbc &&
4334 #if !defined TIZEN_EXT
4335 connman_network_set_bool(network, "WiFi.UseWPS", true);
4337 DBG("wps is activating by ap but ignore it.");
4342 connman_network_set_frequency(network,
4343 g_supplicant_network_get_frequency(supplicant_network));
4344 #if defined TIZEN_EXT
4345 connman_network_set_bssid(network,
4346 g_supplicant_network_get_bssid(supplicant_network));
4347 connman_network_set_maxrate(network,
4348 g_supplicant_network_get_maxrate(supplicant_network));
4349 connman_network_set_enc_mode(network,
4350 g_supplicant_network_get_enc_mode(supplicant_network));
4351 connman_network_set_rsn_mode(network,
4352 g_supplicant_network_get_rsn_mode(supplicant_network));
4353 connman_network_set_keymgmt(network,
4354 g_supplicant_network_get_keymgmt(supplicant_network));
4355 connman_network_set_bool(network, "WiFi.HS20AP",
4356 g_supplicant_network_is_hs20AP(supplicant_network));
4357 connman_network_set_bssid_list(network,
4358 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4360 connman_network_set_available(network, true);
4361 connman_network_set_string(network, "WiFi.Mode", mode);
4363 #if defined TIZEN_EXT
4368 connman_network_set_group(network, group);
4370 #if defined TIZEN_EXT
4371 if (wifi_first_scan == true)
4372 found_with_first_scan = true;
4375 if (wifi->hidden && ssid) {
4376 #if defined TIZEN_EXT
4377 if (network_security(wifi->hidden->security) ==
4378 network_security(security) &&
4380 if (!g_strcmp0(wifi->hidden->security, security) &&
4382 wifi->hidden->ssid_len == ssid_len &&
4383 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4384 connman_network_connect_hidden(network,
4385 wifi->hidden->identity,
4386 wifi->hidden->passphrase,
4387 wifi->hidden->user_data);
4388 wifi->hidden->user_data = NULL;
4389 hidden_free(wifi->hidden);
4390 wifi->hidden = NULL;
4395 static void network_removed(GSupplicantNetwork *network)
4397 GSupplicantInterface *interface;
4398 struct wifi_data *wifi;
4399 const char *name, *identifier;
4400 struct connman_network *connman_network;
4402 #if defined TIZEN_EXT_WIFI_MESH
4404 mode = g_supplicant_network_get_mode(network);
4405 if (!g_strcmp0(mode, "mesh")) {
4406 mesh_peer_removed(network);
4411 interface = g_supplicant_network_get_interface(network);
4412 wifi = g_supplicant_interface_get_data(interface);
4413 identifier = g_supplicant_network_get_identifier(network);
4414 name = g_supplicant_network_get_name(network);
4416 DBG("name %s", name);
4421 connman_network = connman_device_get_network(wifi->device, identifier);
4422 if (!connman_network)
4425 #if defined TIZEN_EXT
4426 if (connman_network == wifi->scan_pending_network)
4427 wifi->scan_pending_network = NULL;
4429 if (connman_network == wifi->pending_network)
4430 wifi->pending_network = NULL;
4432 if(connman_network_get_connecting(connman_network) == true){
4433 connman_network_set_connected(connman_network, false);
4437 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4439 connman_device_remove_network(wifi->device, connman_network);
4440 connman_network_unref(connman_network);
4443 static void network_changed(GSupplicantNetwork *network, const char *property)
4445 GSupplicantInterface *interface;
4446 struct wifi_data *wifi;
4447 const char *name, *identifier;
4448 struct connman_network *connman_network;
4450 #if defined TIZEN_EXT
4451 const unsigned char *bssid;
4452 unsigned int maxrate;
4455 const unsigned char *country_code;
4459 interface = g_supplicant_network_get_interface(network);
4460 wifi = g_supplicant_interface_get_data(interface);
4461 identifier = g_supplicant_network_get_identifier(network);
4462 name = g_supplicant_network_get_name(network);
4464 DBG("name %s", name);
4469 connman_network = connman_device_get_network(wifi->device, identifier);
4470 if (!connman_network)
4473 if (g_str_equal(property, "Signal")) {
4474 connman_network_set_strength(connman_network,
4475 calculate_strength(network));
4476 connman_network_update(connman_network);
4479 #if defined TIZEN_EXT
4480 bssid = g_supplicant_network_get_bssid(network);
4481 maxrate = g_supplicant_network_get_maxrate(network);
4482 frequency = g_supplicant_network_get_frequency(network);
4483 wps = g_supplicant_network_get_wps(network);
4485 connman_network_set_bssid(connman_network, bssid);
4486 connman_network_set_maxrate(connman_network, maxrate);
4487 connman_network_set_frequency(connman_network, frequency);
4488 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4489 country_code = g_supplicant_network_get_countrycode(network);
4490 connman_network_set_countrycode(connman_network, country_code);
4491 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4492 connman_network_set_bssid_list(connman_network, bssid_list);
4496 static void network_associated(GSupplicantNetwork *network)
4498 GSupplicantInterface *interface;
4499 struct wifi_data *wifi;
4500 struct connman_network *connman_network;
4501 const char *identifier;
4505 interface = g_supplicant_network_get_interface(network);
4509 wifi = g_supplicant_interface_get_data(interface);
4513 identifier = g_supplicant_network_get_identifier(network);
4515 connman_network = connman_device_get_network(wifi->device, identifier);
4516 if (!connman_network)
4519 if (wifi->network) {
4520 if (wifi->network == connman_network)
4524 * This should never happen, we got associated with
4525 * a network different than the one we were expecting.
4527 DBG("Associated to %p while expecting %p",
4528 connman_network, wifi->network);
4530 connman_network_set_associating(wifi->network, false);
4533 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4535 wifi->network = connman_network_ref(connman_network);
4539 * Interface state changes callback (interface_state) is always
4540 * called before network_associated callback thus we need to call
4541 * interface_state again in order to process the new state now that
4542 * we have the network properly set.
4544 interface_state(interface);
4547 static void apply_peer_services(GSupplicantPeer *peer,
4548 struct connman_peer *connman_peer)
4550 const unsigned char *data;
4555 connman_peer_reset_services(connman_peer);
4557 data = g_supplicant_peer_get_widi_ies(peer, &length);
4559 connman_peer_add_service(connman_peer,
4560 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4564 static void add_station(const char *mac)
4566 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4570 static void remove_station(const char *mac)
4572 connman_technology_tethering_remove_station(mac);
4575 static void peer_found(GSupplicantPeer *peer)
4577 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4578 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4579 struct connman_peer *connman_peer;
4580 const char *identifier, *name;
4582 #if defined TIZEN_EXT
4586 identifier = g_supplicant_peer_get_identifier(peer);
4587 name = g_supplicant_peer_get_name(peer);
4589 DBG("ident: %s", identifier);
4591 connman_peer = connman_peer_get(wifi->device, identifier);
4595 connman_peer = connman_peer_create(identifier);
4596 connman_peer_set_name(connman_peer, name);
4597 connman_peer_set_device(connman_peer, wifi->device);
4598 apply_peer_services(peer, connman_peer);
4600 ret = connman_peer_register(connman_peer);
4601 if (ret < 0 && ret != -EALREADY)
4602 connman_peer_unref(connman_peer);
4604 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4607 static void peer_lost(GSupplicantPeer *peer)
4609 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4610 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4611 struct connman_peer *connman_peer;
4612 const char *identifier;
4617 identifier = g_supplicant_peer_get_identifier(peer);
4619 DBG("ident: %s", identifier);
4621 connman_peer = connman_peer_get(wifi->device, identifier);
4623 if (wifi->p2p_connecting &&
4624 wifi->pending_peer == connman_peer) {
4625 peer_connect_timeout(wifi);
4627 connman_peer_unregister(connman_peer);
4628 connman_peer_unref(connman_peer);
4631 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4634 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4636 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4637 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4638 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4639 struct connman_peer *connman_peer;
4640 const char *identifier;
4642 identifier = g_supplicant_peer_get_identifier(peer);
4644 DBG("ident: %s", identifier);
4649 connman_peer = connman_peer_get(wifi->device, identifier);
4654 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4655 apply_peer_services(peer, connman_peer);
4656 connman_peer_services_changed(connman_peer);
4658 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4659 if (!g_supplicant_peer_is_in_a_group(peer))
4660 p_state = CONNMAN_PEER_STATE_IDLE;
4662 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4664 case G_SUPPLICANT_PEER_GROUP_STARTED:
4666 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4667 p_state = CONNMAN_PEER_STATE_IDLE;
4669 case G_SUPPLICANT_PEER_GROUP_JOINED:
4670 connman_peer_set_iface_address(connman_peer,
4671 g_supplicant_peer_get_iface_address(peer));
4673 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4674 p_state = CONNMAN_PEER_STATE_IDLE;
4676 case G_SUPPLICANT_PEER_GROUP_FAILED:
4677 if (g_supplicant_peer_has_requested_connection(peer))
4678 p_state = CONNMAN_PEER_STATE_IDLE;
4680 p_state = CONNMAN_PEER_STATE_FAILURE;
4684 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4685 p_state == CONNMAN_PEER_STATE_FAILURE) {
4686 if (wifi->p2p_connecting
4687 && connman_peer == wifi->pending_peer)
4688 peer_cancel_timeout(wifi);
4690 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4693 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4696 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4697 GSupplicantInterface *g_iface;
4698 struct wifi_data *g_wifi;
4700 g_iface = g_supplicant_peer_get_group_interface(peer);
4704 g_wifi = g_supplicant_interface_get_data(g_iface);
4708 connman_peer_set_as_master(connman_peer,
4709 !g_supplicant_peer_is_client(peer));
4710 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4713 * If wpa_supplicant didn't create a dedicated p2p-group
4714 * interface then mark this interface as p2p_device to avoid
4715 * scan and auto-scan are launched on it while P2P is connected.
4717 if (!g_list_find(p2p_iface_list, g_wifi))
4718 wifi->p2p_device = true;
4721 connman_peer_set_state(connman_peer, p_state);
4724 static void peer_request(GSupplicantPeer *peer)
4726 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4727 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4728 struct connman_peer *connman_peer;
4729 const char *identifier;
4731 #if defined TIZEN_EXT
4736 identifier = g_supplicant_peer_get_identifier(peer);
4738 DBG("ident: %s", identifier);
4740 connman_peer = connman_peer_get(wifi->device, identifier);
4744 connman_peer_request_connection(connman_peer);
4747 #if defined TIZEN_EXT
4748 static void system_power_off(void)
4751 struct wifi_data *wifi;
4752 struct connman_service *service;
4753 struct connman_ipconfig *ipconfig_ipv4;
4755 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4756 for (list = iface_list; list; list = list->next) {
4759 if (wifi->network != NULL) {
4760 service = connman_service_lookup_from_network(wifi->network);
4761 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4762 __connman_dhcp_stop(ipconfig_ipv4);
4768 static void network_merged(GSupplicantNetwork *network)
4770 GSupplicantInterface *interface;
4771 GSupplicantState state;
4772 struct wifi_data *wifi;
4773 const char *identifier;
4774 struct connman_network *connman_network;
4778 interface = g_supplicant_network_get_interface(network);
4782 state = g_supplicant_interface_get_state(interface);
4783 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4786 wifi = g_supplicant_interface_get_data(interface);
4790 identifier = g_supplicant_network_get_identifier(network);
4792 connman_network = connman_device_get_network(wifi->device, identifier);
4793 if (!connman_network)
4796 DBG("merged identifier %s", identifier);
4798 if (wifi->connected == FALSE) {
4800 case G_SUPPLICANT_STATE_AUTHENTICATING:
4801 case G_SUPPLICANT_STATE_ASSOCIATING:
4802 case G_SUPPLICANT_STATE_ASSOCIATED:
4803 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4804 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4805 connman_network_set_associating(connman_network, TRUE);
4807 case G_SUPPLICANT_STATE_COMPLETED:
4808 connman_network_set_connected(connman_network, TRUE);
4811 DBG("Not handled the state : %d", state);
4816 ishs20AP = g_supplicant_network_is_hs20AP(network);
4819 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
4820 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
4821 connman_network_set_string(connman_network, "WiFi.EAP",
4823 connman_network_set_string(connman_network, "WiFi.Identity",
4824 g_supplicant_network_get_identity(network));
4825 connman_network_set_string(connman_network, "WiFi.Phase2",
4826 g_supplicant_network_get_phase2(network));
4831 wifi->network = connman_network;
4834 static void assoc_failed(void *user_data)
4836 struct connman_network *network = user_data;
4837 connman_network_set_associating(network, false);
4841 static void debug(const char *str)
4843 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
4844 connman_debug("%s", str);
4847 static void disconnect_reasoncode(GSupplicantInterface *interface,
4850 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4853 wifi->disconnect_code = reasoncode;
4857 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
4859 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4862 wifi->assoc_code = status_code;
4866 static const GSupplicantCallbacks callbacks = {
4867 .system_ready = system_ready,
4868 .system_killed = system_killed,
4869 .interface_added = interface_added,
4870 .interface_state = interface_state,
4871 .interface_removed = interface_removed,
4872 .p2p_support = p2p_support,
4873 .scan_started = scan_started,
4874 .scan_finished = scan_finished,
4875 .ap_create_fail = ap_create_fail,
4876 .network_added = network_added,
4877 .network_removed = network_removed,
4878 .network_changed = network_changed,
4879 .network_associated = network_associated,
4880 .add_station = add_station,
4881 .remove_station = remove_station,
4882 .peer_found = peer_found,
4883 .peer_lost = peer_lost,
4884 .peer_changed = peer_changed,
4885 .peer_request = peer_request,
4886 #if defined TIZEN_EXT
4887 .system_power_off = system_power_off,
4888 .network_merged = network_merged,
4889 .assoc_failed = assoc_failed,
4892 .disconnect_reasoncode = disconnect_reasoncode,
4893 .assoc_status_code = assoc_status_code,
4894 #if defined TIZEN_EXT_WIFI_MESH
4895 .mesh_support = mesh_support,
4896 .mesh_group_started = mesh_group_started,
4897 .mesh_group_removed = mesh_group_removed,
4898 .mesh_peer_connected = mesh_peer_connected,
4899 .mesh_peer_disconnected = mesh_peer_disconnected,
4904 static int tech_probe(struct connman_technology *technology)
4906 wifi_technology = technology;
4911 static void tech_remove(struct connman_technology *technology)
4913 wifi_technology = NULL;
4916 static GSupplicantSSID *ssid_ap_init(const char *ssid,
4917 const char *passphrase)
4919 GSupplicantSSID *ap;
4921 ap = g_try_malloc0(sizeof(GSupplicantSSID));
4925 ap->mode = G_SUPPLICANT_MODE_MASTER;
4926 #if defined TIZEN_EXT
4927 ap->ssid = (void *) ssid;
4931 ap->ssid_len = strlen(ssid);
4935 if (!passphrase || strlen(passphrase) == 0) {
4936 ap->security = G_SUPPLICANT_SECURITY_NONE;
4937 ap->passphrase = NULL;
4939 ap->security = G_SUPPLICANT_SECURITY_PSK;
4940 ap->protocol = G_SUPPLICANT_PROTO_RSN;
4941 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
4942 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
4943 ap->passphrase = passphrase;
4949 static void ap_start_callback(int result, GSupplicantInterface *interface,
4952 struct wifi_tethering_info *info = user_data;
4954 DBG("result %d index %d bridge %s",
4955 result, info->wifi->index, info->wifi->bridge);
4957 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4958 connman_inet_remove_from_bridge(info->wifi->index,
4959 info->wifi->bridge);
4961 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4962 connman_technology_tethering_notify(info->technology, false);
4963 g_free(info->wifi->tethering_param->ssid);
4964 g_free(info->wifi->tethering_param);
4965 info->wifi->tethering_param = NULL;
4969 g_free(info->ifname);
4973 static void ap_create_callback(int result,
4974 GSupplicantInterface *interface,
4977 struct wifi_tethering_info *info = user_data;
4979 DBG("result %d ifname %s", result,
4980 g_supplicant_interface_get_ifname(interface));
4982 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4983 connman_inet_remove_from_bridge(info->wifi->index,
4984 info->wifi->bridge);
4986 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4987 connman_technology_tethering_notify(info->technology, false);
4988 g_free(info->wifi->tethering_param->ssid);
4989 g_free(info->wifi->tethering_param);
4990 info->wifi->tethering_param = NULL;
4994 g_free(info->ifname);
5000 info->wifi->interface = interface;
5001 g_supplicant_interface_set_data(interface, info->wifi);
5003 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
5004 connman_error("Failed to set interface ap_scan property");
5006 g_supplicant_interface_connect(interface, info->ssid,
5007 ap_start_callback, info);
5010 static void sta_remove_callback(int result,
5011 GSupplicantInterface *interface,
5014 struct wifi_tethering_info *info = user_data;
5015 const char *driver = connman_option_get_string("wifi");
5017 DBG("ifname %s result %d ", info->ifname, result);
5019 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
5020 info->wifi->tethering = false;
5021 connman_technology_tethering_notify(info->technology, false);
5023 g_free(info->ifname);
5027 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
5028 g_free(info->wifi->tethering_param->ssid);
5029 g_free(info->wifi->tethering_param);
5030 info->wifi->tethering_param = NULL;
5035 info->wifi->interface = NULL;
5037 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
5042 static int enable_wifi_tethering(struct connman_technology *technology,
5043 const char *bridge, const char *identifier,
5044 const char *passphrase, bool available)
5047 GSupplicantInterface *interface;
5048 struct wifi_data *wifi;
5049 struct wifi_tethering_info *info;
5054 for (list = iface_list; list; list = list->next) {
5057 DBG("wifi %p network %p pending_network %p", wifi,
5058 wifi->network, wifi->pending_network);
5060 interface = wifi->interface;
5065 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5068 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5070 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5071 DBG("%s does not support AP mode (detected)", ifname);
5075 mode = g_supplicant_interface_get_mode(interface);
5076 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5077 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5078 DBG("%s does not support AP mode (capability)", ifname);
5082 if (wifi->network && available)
5085 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5089 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5090 if (!wifi->tethering_param) {
5096 info->technology = technology;
5097 info->wifi->bridge = bridge;
5098 info->ssid = ssid_ap_init(identifier, passphrase);
5102 info->ifname = g_strdup(ifname);
5106 wifi->tethering_param->technology = technology;
5107 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5108 if (!wifi->tethering_param->ssid)
5111 info->wifi->tethering = true;
5112 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5114 berr = connman_technology_tethering_notify(technology, true);
5118 err = g_supplicant_interface_remove(interface,
5119 sta_remove_callback,
5122 DBG("tethering wifi %p ifname %s", wifi, ifname);
5127 g_free(info->ifname);
5130 g_free(wifi->tethering_param);
5131 wifi->tethering_param = NULL;
5134 * Remove bridge if it was correctly created but remove
5135 * operation failed. Instead, if bridge creation failed then
5136 * break out and do not try again on another interface,
5137 * bridge set-up does not depend on it.
5140 connman_technology_tethering_notify(technology, false);
5148 static int tech_set_tethering(struct connman_technology *technology,
5149 const char *identifier, const char *passphrase,
5150 const char *bridge, bool enabled)
5153 struct wifi_data *wifi;
5159 for (list = iface_list; list; list = list->next) {
5162 if (wifi->tethering) {
5163 wifi->tethering = false;
5165 connman_inet_remove_from_bridge(wifi->index,
5167 wifi->bridged = false;
5171 connman_technology_tethering_notify(technology, false);
5176 DBG("trying tethering for available devices");
5177 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5181 DBG("trying tethering for any device");
5182 err = enable_wifi_tethering(technology, bridge, identifier,
5189 static void regdom_callback(int result, const char *alpha2, void *user_data)
5193 if (!wifi_technology)
5199 connman_technology_regdom_notify(wifi_technology, alpha2);
5202 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5204 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5207 static struct connman_technology_driver tech_driver = {
5209 .type = CONNMAN_SERVICE_TYPE_WIFI,
5210 .probe = tech_probe,
5211 .remove = tech_remove,
5212 .set_tethering = tech_set_tethering,
5213 .set_regdom = tech_set_regdom,
5216 static int wifi_init(void)
5220 err = connman_network_driver_register(&network_driver);
5224 err = g_supplicant_register(&callbacks);
5226 connman_network_driver_unregister(&network_driver);
5230 err = connman_technology_driver_register(&tech_driver);
5232 g_supplicant_unregister(&callbacks);
5233 connman_network_driver_unregister(&network_driver);
5240 static void wifi_exit(void)
5244 connman_technology_driver_unregister(&tech_driver);
5246 g_supplicant_unregister(&callbacks);
5248 connman_network_driver_unregister(&network_driver);
5251 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5252 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)