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);
3191 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3193 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3196 ssid->scan_ssid = 1;
3197 security = connman_network_get_string(network, "WiFi.Security");
3198 ssid->security = network_security(security);
3199 ssid->passphrase = connman_network_get_string(network,
3201 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3204 * If our private key password is unset,
3205 * we use the supplied passphrase. That is needed
3206 * for PEAP where 2 passphrases (identity and client
3207 * cert may have to be provided.
3209 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3210 connman_network_set_string(network,
3211 "WiFi.PrivateKeyPassphrase",
3213 /* We must have an identity for both PEAP and TLS */
3214 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3216 /* Use agent provided identity as a fallback */
3217 if (!ssid->identity || strlen(ssid->identity) == 0)
3218 ssid->identity = connman_network_get_string(network,
3219 "WiFi.AgentIdentity");
3221 ssid->anonymous_identity = connman_network_get_string(network,
3222 "WiFi.AnonymousIdentity");
3223 ssid->ca_cert_path = connman_network_get_string(network,
3225 ssid->subject_match = connman_network_get_string(network,
3226 "WiFi.SubjectMatch");
3227 ssid->altsubject_match = connman_network_get_string(network,
3228 "WiFi.AltSubjectMatch");
3229 ssid->domain_suffix_match = connman_network_get_string(network,
3230 "WiFi.DomainSuffixMatch");
3231 ssid->domain_match = connman_network_get_string(network,
3232 "WiFi.DomainMatch");
3233 ssid->client_cert_path = connman_network_get_string(network,
3234 "WiFi.ClientCertFile");
3235 ssid->private_key_path = connman_network_get_string(network,
3236 "WiFi.PrivateKeyFile");
3237 ssid->private_key_passphrase = connman_network_get_string(network,
3238 "WiFi.PrivateKeyPassphrase");
3239 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3241 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3242 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3244 #if defined TIZEN_EXT
3245 ssid->bssid = connman_network_get_bssid(network);
3247 ssid->eap_keymgmt = network_eap_keymgmt(
3248 connman_network_get_string(network, "WiFi.KeymgmtType"));
3249 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3251 if(g_strcmp0(ssid->eap, "fast") == 0)
3252 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3254 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3255 ssid->bssid_for_connect_len = 6;
3256 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3257 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3258 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3259 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3260 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3262 ssid->freq = connman_network_get_frequency(network);
3266 if (connman_setting_get_bool("BackgroundScanning"))
3267 ssid->bgscan = BGSCAN_DEFAULT;
3270 static int network_connect(struct connman_network *network)
3272 struct connman_device *device = connman_network_get_device(network);
3273 struct wifi_data *wifi;
3274 GSupplicantInterface *interface;
3275 GSupplicantSSID *ssid;
3277 DBG("network %p", network);
3282 wifi = connman_device_get_data(device);
3286 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3290 interface = wifi->interface;
3292 ssid_init(ssid, network);
3294 if (wifi->disconnecting) {
3295 wifi->pending_network = network;
3296 #if defined TIZEN_EXT
3301 wifi->network = connman_network_ref(network);
3303 #if defined TIZEN_EXT
3304 wifi->scan_pending_network = NULL;
3307 return g_supplicant_interface_connect(interface, ssid,
3308 connect_callback, network);
3311 return -EINPROGRESS;
3314 static void disconnect_callback(int result, GSupplicantInterface *interface,
3317 #if defined TIZEN_EXT
3319 struct wifi_data *wifi;
3320 struct connman_network *network = user_data;
3322 DBG("network %p result %d", network, result);
3324 for (list = iface_list; list; list = list->next) {
3327 if (wifi->network == NULL && wifi->disconnecting == true)
3328 wifi->disconnecting = false;
3330 if (wifi->network == network)
3334 /* wifi_data may be invalid because wifi is already disabled */
3339 struct wifi_data *wifi = user_data;
3342 DBG("result %d supplicant interface %p wifi %p",
3343 result, interface, wifi);
3345 if (result == -ECONNABORTED) {
3346 DBG("wifi interface no longer available");
3350 if (wifi->network) {
3351 connman_network_set_connected(wifi->network, false);
3352 wifi->network = NULL;
3355 wifi->disconnecting = false;
3356 wifi->connected = false;
3358 if (wifi->pending_network) {
3359 network_connect(wifi->pending_network);
3360 wifi->pending_network = NULL;
3363 start_autoscan(wifi->device);
3366 static int network_disconnect(struct connman_network *network)
3368 struct connman_device *device = connman_network_get_device(network);
3369 struct wifi_data *wifi;
3371 #if defined TIZEN_EXT
3372 struct connman_service *service;
3375 DBG("network %p", network);
3377 wifi = connman_device_get_data(device);
3378 if (!wifi || !wifi->interface)
3381 #if defined TIZEN_EXT
3382 if (connman_network_get_associating(network) == true) {
3383 connman_network_clear_associating(network);
3384 connman_network_set_bool(network, "WiFi.UseWPS", false);
3386 service = connman_service_lookup_from_network(network);
3388 if (service != NULL &&
3389 (__connman_service_is_connected_state(service,
3390 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3391 __connman_service_is_connected_state(service,
3392 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3393 (connman_service_get_favorite(service) == false))
3394 __connman_service_set_passphrase(service, NULL);
3397 if (wifi->pending_network == network)
3398 wifi->pending_network = NULL;
3400 if (wifi->scan_pending_network == network)
3401 wifi->scan_pending_network = NULL;
3404 connman_network_set_associating(network, false);
3406 if (wifi->disconnecting)
3409 wifi->disconnecting = true;
3411 #if defined TIZEN_EXT
3412 err = g_supplicant_interface_disconnect(wifi->interface,
3413 disconnect_callback, network);
3415 err = g_supplicant_interface_disconnect(wifi->interface,
3416 disconnect_callback, wifi);
3420 wifi->disconnecting = false;
3425 static struct connman_network_driver network_driver = {
3427 .type = CONNMAN_NETWORK_TYPE_WIFI,
3428 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3429 .probe = network_probe,
3430 .remove = network_remove,
3431 .connect = network_connect,
3432 .disconnect = network_disconnect,
3435 static void interface_added(GSupplicantInterface *interface)
3437 const char *ifname = g_supplicant_interface_get_ifname(interface);
3438 const char *driver = g_supplicant_interface_get_driver(interface);
3439 struct wifi_data *wifi;
3441 wifi = g_supplicant_interface_get_data(interface);
3443 wifi = get_pending_wifi_data(ifname);
3447 wifi->interface = interface;
3448 g_supplicant_interface_set_data(interface, wifi);
3449 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3450 wifi->p2p_device = true;
3453 DBG("ifname %s driver %s wifi %p tethering %d",
3454 ifname, driver, wifi, wifi->tethering);
3456 if (!wifi->device) {
3457 connman_error("WiFi device not set");
3461 connman_device_set_powered(wifi->device, true);
3464 static bool is_idle(struct wifi_data *wifi)
3466 DBG("state %d", wifi->state);
3468 switch (wifi->state) {
3469 case G_SUPPLICANT_STATE_UNKNOWN:
3470 case G_SUPPLICANT_STATE_DISABLED:
3471 case G_SUPPLICANT_STATE_DISCONNECTED:
3472 case G_SUPPLICANT_STATE_INACTIVE:
3473 case G_SUPPLICANT_STATE_SCANNING:
3476 case G_SUPPLICANT_STATE_AUTHENTICATING:
3477 case G_SUPPLICANT_STATE_ASSOCIATING:
3478 case G_SUPPLICANT_STATE_ASSOCIATED:
3479 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3480 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3481 case G_SUPPLICANT_STATE_COMPLETED:
3488 static bool is_idle_wps(GSupplicantInterface *interface,
3489 struct wifi_data *wifi)
3491 /* First, let's check if WPS processing did not went wrong */
3492 if (g_supplicant_interface_get_wps_state(interface) ==
3493 G_SUPPLICANT_WPS_STATE_FAIL)
3496 /* Unlike normal connection, being associated while processing wps
3497 * actually means that we are idling. */
3498 switch (wifi->state) {
3499 case G_SUPPLICANT_STATE_UNKNOWN:
3500 case G_SUPPLICANT_STATE_DISABLED:
3501 case G_SUPPLICANT_STATE_DISCONNECTED:
3502 case G_SUPPLICANT_STATE_INACTIVE:
3503 case G_SUPPLICANT_STATE_SCANNING:
3504 case G_SUPPLICANT_STATE_ASSOCIATED:
3506 case G_SUPPLICANT_STATE_AUTHENTICATING:
3507 case G_SUPPLICANT_STATE_ASSOCIATING:
3508 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3509 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3510 case G_SUPPLICANT_STATE_COMPLETED:
3517 static bool handle_wps_completion(GSupplicantInterface *interface,
3518 struct connman_network *network,
3519 struct connman_device *device,
3520 struct wifi_data *wifi)
3524 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3526 const unsigned char *ssid, *wps_ssid;
3527 unsigned int ssid_len, wps_ssid_len;
3528 const char *wps_key;
3530 /* Checking if we got associated with requested
3532 ssid = connman_network_get_blob(network, "WiFi.SSID",
3535 wps_ssid = g_supplicant_interface_get_wps_ssid(
3536 interface, &wps_ssid_len);
3538 if (!wps_ssid || wps_ssid_len != ssid_len ||
3539 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3540 connman_network_set_associating(network, false);
3541 #if defined TIZEN_EXT
3542 g_supplicant_interface_disconnect(wifi->interface,
3543 disconnect_callback, wifi->network);
3545 connman_network_set_bool(network, "WiFi.UseWPS", false);
3546 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3548 g_supplicant_interface_disconnect(wifi->interface,
3549 disconnect_callback, wifi);
3554 wps_key = g_supplicant_interface_get_wps_key(interface);
3555 #if defined TIZEN_EXT
3556 /* Check the passphrase and encrypt it
3559 gchar *passphrase = g_strdup(wps_key);
3561 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3563 if (check_passphrase_ext(network, passphrase) < 0) {
3564 DBG("[WPS] Invalid passphrase");
3569 ret = send_encryption_request(passphrase, network);
3574 DBG("[WPS] Encryption request succeeded");
3576 DBG("[WPS] Encryption request failed %d", ret);
3579 connman_network_set_string(network, "WiFi.Passphrase",
3582 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3589 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3590 struct wifi_data *wifi)
3592 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3593 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3594 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3595 wifi->load_shaping_retries ++;
3598 wifi->load_shaping_retries = 0;
3602 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3603 struct connman_network *network,
3604 struct wifi_data *wifi)
3606 #if defined TIZEN_EXT
3607 const char *security;
3608 struct connman_service *service;
3610 if (wifi->connected)
3613 security = connman_network_get_string(network, "WiFi.Security");
3615 if (security && g_str_equal(security, "ieee8021x") == true &&
3616 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3618 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3623 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3626 struct connman_service *service;
3628 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3631 if (wifi->connected)
3635 service = connman_service_lookup_from_network(network);
3641 if (connman_service_get_favorite(service)) {
3642 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3647 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3652 #if defined TIZEN_EXT
3653 static bool handle_wifi_assoc_retry(struct connman_network *network,
3654 struct wifi_data *wifi)
3656 const char *security;
3658 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3659 connman_network_get_connecting(network) != true) {
3660 wifi->assoc_retry_count = 0;
3664 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3665 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3666 wifi->assoc_retry_count = 0;
3670 security = connman_network_get_string(network, "WiFi.Security");
3671 if (security && g_str_equal(security, "ieee8021x") == true &&
3672 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3673 wifi->assoc_retry_count = 0;
3677 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3678 wifi->assoc_retry_count = 0;
3680 /* Honestly it's not an invalid-key error,
3681 * however QA team recommends that the invalid-key error
3682 * might be better to display for user experience.
3684 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3693 static void interface_state(GSupplicantInterface *interface)
3695 struct connman_network *network;
3696 struct connman_device *device;
3697 struct wifi_data *wifi;
3698 GSupplicantState state = g_supplicant_interface_get_state(interface);
3702 wifi = g_supplicant_interface_get_data(interface);
3704 DBG("wifi %p interface state %d", wifi, state);
3709 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3710 if (wifi->tethering_param) {
3711 g_free(wifi->tethering_param->ssid);
3712 g_free(wifi->tethering_param);
3713 wifi->tethering_param = NULL;
3717 device = wifi->device;
3721 if (g_supplicant_interface_get_ready(interface) &&
3722 !wifi->interface_ready) {
3723 wifi->interface_ready = true;
3724 finalize_interface_creation(wifi);
3727 network = wifi->network;
3732 case G_SUPPLICANT_STATE_SCANNING:
3733 if (wifi->connected)
3734 connman_network_set_connected(network, false);
3738 case G_SUPPLICANT_STATE_AUTHENTICATING:
3739 case G_SUPPLICANT_STATE_ASSOCIATING:
3740 #if defined TIZEN_EXT
3741 reset_autoscan(device);
3743 stop_autoscan(device);
3746 if (!wifi->connected)
3747 connman_network_set_associating(network, true);
3751 case G_SUPPLICANT_STATE_COMPLETED:
3752 #if defined TIZEN_EXT
3753 /* though it should be already reset: */
3754 reset_autoscan(device);
3756 wifi->assoc_retry_count = 0;
3758 wifi->scan_pending_network = NULL;
3760 /* should be cleared scanning flag */
3761 bool scanning = connman_device_get_scanning(device);
3763 connman_device_set_scanning(device,
3764 CONNMAN_SERVICE_TYPE_WIFI, false);
3765 connman_device_unref(device);
3768 /* though it should be already stopped: */
3769 stop_autoscan(device);
3772 if (!handle_wps_completion(interface, network, device, wifi))
3775 connman_network_set_connected(network, true);
3777 wifi->disconnect_code = 0;
3778 wifi->assoc_code = 0;
3779 wifi->load_shaping_retries = 0;
3782 case G_SUPPLICANT_STATE_DISCONNECTED:
3784 * If we're in one of the idle modes, we have
3785 * not started association yet and thus setting
3786 * those ones to FALSE could cancel an association
3789 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3791 if (is_idle_wps(interface, wifi))
3797 if (handle_assoc_status_code(interface, wifi))
3800 /* If previous state was 4way-handshake, then
3801 * it's either: psk was incorrect and thus we retry
3802 * or if we reach the maximum retries we declare the
3804 if (handle_4way_handshake_failure(interface,
3808 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3809 switch (wifi->disconnect_code) {
3810 case 1: /* Unspecified reason */
3811 /* Let's assume it's because we got blocked */
3813 case 6: /* Class 2 frame received from nonauthenticated STA */
3814 connman_network_set_error(network,
3815 CONNMAN_NETWORK_ERROR_BLOCKED);
3822 #if defined TIZEN_EXT
3823 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3824 * Retry association until its retry count is expired */
3825 if (handle_wifi_assoc_retry(network, wifi) == true) {
3826 throw_wifi_scan(wifi->device, scan_callback);
3827 wifi->scan_pending_network = wifi->network;
3831 if(wifi->disconnect_code > 0){
3832 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3833 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3837 connman_network_set_connected(network, false);
3838 connman_network_set_associating(network, false);
3839 wifi->disconnecting = false;
3841 start_autoscan(device);
3845 case G_SUPPLICANT_STATE_INACTIVE:
3846 #if defined TIZEN_EXT
3847 if (handle_wps_completion(interface, network, device, wifi) == false)
3850 connman_network_set_associating(network, false);
3851 start_autoscan(device);
3855 case G_SUPPLICANT_STATE_UNKNOWN:
3856 case G_SUPPLICANT_STATE_DISABLED:
3857 case G_SUPPLICANT_STATE_ASSOCIATED:
3858 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3859 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3863 old_connected = wifi->connected;
3864 wifi->state = state;
3866 /* Saving wpa_s state policy:
3867 * If connected and if the state changes are roaming related:
3868 * --> We stay connected
3870 * --> We are connected
3872 * --> We are not connected
3875 case G_SUPPLICANT_STATE_AUTHENTICATING:
3876 case G_SUPPLICANT_STATE_ASSOCIATING:
3877 case G_SUPPLICANT_STATE_ASSOCIATED:
3878 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3879 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3880 if (wifi->connected)
3881 connman_warn("Probably roaming right now!"
3882 " Staying connected...");
3884 case G_SUPPLICANT_STATE_SCANNING:
3885 wifi->connected = false;
3888 start_autoscan(device);
3890 case G_SUPPLICANT_STATE_COMPLETED:
3891 wifi->connected = true;
3894 wifi->connected = false;
3901 static void interface_removed(GSupplicantInterface *interface)
3903 const char *ifname = g_supplicant_interface_get_ifname(interface);
3904 struct wifi_data *wifi;
3906 DBG("ifname %s", ifname);
3908 wifi = g_supplicant_interface_get_data(interface);
3910 #if defined TIZEN_EXT_WIFI_MESH
3911 if (wifi && wifi->mesh_interface) {
3912 DBG("Notify mesh interface remove");
3913 connman_mesh_notify_interface_remove(true);
3914 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
3915 g_free(mesh_info->parent_ifname);
3916 g_free(mesh_info->ifname);
3917 g_free(mesh_info->identifier);
3919 wifi->mesh_interface = false;
3920 wifi->mesh_info = NULL;
3926 wifi->interface = NULL;
3928 if (wifi && wifi->tethering)
3931 if (!wifi || !wifi->device) {
3932 DBG("wifi interface already removed");
3936 connman_device_set_powered(wifi->device, false);
3938 check_p2p_technology();
3939 #if defined TIZEN_EXT_WIFI_MESH
3940 check_mesh_technology();
3944 static void set_device_type(const char *type, char dev_type[17])
3946 const char *oui = "0050F204";
3947 const char *category = "0001";
3948 const char *sub_category = "0000";
3950 if (!g_strcmp0(type, "handset")) {
3952 sub_category = "0005";
3953 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
3954 sub_category = "0001";
3955 else if (!g_strcmp0(type, "server"))
3956 sub_category = "0002";
3957 else if (!g_strcmp0(type, "laptop"))
3958 sub_category = "0005";
3959 else if (!g_strcmp0(type, "desktop"))
3960 sub_category = "0006";
3961 else if (!g_strcmp0(type, "tablet"))
3962 sub_category = "0009";
3963 else if (!g_strcmp0(type, "watch"))
3966 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
3969 static void p2p_support(GSupplicantInterface *interface)
3971 char dev_type[17] = {};
3972 const char *hostname;
3979 if (!g_supplicant_interface_has_p2p(interface))
3982 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3983 DBG("Could not register P2P technology driver");
3987 hostname = connman_utsname_get_hostname();
3989 hostname = "ConnMan";
3991 set_device_type(connman_machine_get_type(), dev_type);
3992 g_supplicant_interface_set_p2p_device_config(interface,
3993 hostname, dev_type);
3994 connman_peer_driver_register(&peer_driver);
3997 static void scan_started(GSupplicantInterface *interface)
4002 static void scan_finished(GSupplicantInterface *interface)
4004 #if defined TIZEN_EXT
4005 struct wifi_data *wifi;
4006 bool is_associating = false;
4007 static bool is_scanning = true;
4012 #if defined TIZEN_EXT
4013 wifi = g_supplicant_interface_get_data(interface);
4014 if (wifi && wifi->scan_pending_network) {
4015 network_connect(wifi->scan_pending_network);
4016 wifi->scan_pending_network = NULL;
4019 //service state - associating
4020 if(!wifi || !wifi->network)
4023 is_associating = connman_network_get_associating(wifi->network);
4024 if(is_associating && is_scanning){
4025 is_scanning = false;
4026 DBG("send scan for connecting");
4027 throw_wifi_scan(wifi->device, scan_callback);
4038 static void ap_create_fail(GSupplicantInterface *interface)
4040 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4043 if ((wifi->tethering) && (wifi->tethering_param)) {
4044 DBG("%s create AP fail \n",
4045 g_supplicant_interface_get_ifname(wifi->interface));
4047 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4048 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4049 wifi->tethering = false;
4051 ret = tech_set_tethering(wifi->tethering_param->technology,
4052 wifi->tethering_param->ssid->ssid,
4053 wifi->tethering_param->ssid->passphrase,
4054 wifi->bridge, true);
4056 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4057 connman_technology_tethering_notify(wifi_technology,false);
4060 g_free(wifi->tethering_param->ssid);
4061 g_free(wifi->tethering_param);
4062 wifi->tethering_param = NULL;
4068 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4070 unsigned char strength;
4072 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4074 #if !defined TIZEN_EXT
4081 #if defined TIZEN_EXT_WIFI_MESH
4082 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4084 GSupplicantInterface *interface;
4085 struct wifi_data *wifi;
4086 const char *name, *security;
4087 struct connman_mesh *connman_mesh;
4088 struct wifi_mesh_info *mesh_info;
4089 const unsigned char *bssid;
4090 const char *identifier;
4095 interface = g_supplicant_network_get_interface(supplicant_network);
4096 wifi = g_supplicant_interface_get_data(interface);
4097 if (!wifi || !wifi->mesh_interface) {
4098 DBG("Virtual Mesh interface not created");
4102 bssid = g_supplicant_network_get_bssid(supplicant_network);
4103 address = g_malloc0(19);
4104 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4105 bssid[2], bssid[3], bssid[4], bssid[5]);
4107 identifier = g_supplicant_network_get_identifier(supplicant_network);
4108 name = g_supplicant_network_get_name(supplicant_network);
4109 security = g_supplicant_network_get_security(supplicant_network);
4110 frequency = g_supplicant_network_get_frequency(supplicant_network);
4112 mesh_info = wifi->mesh_info;
4113 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4117 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4119 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4120 connman_mesh_set_name(connman_mesh, name);
4121 connman_mesh_set_security(connman_mesh, security);
4122 connman_mesh_set_frequency(connman_mesh, frequency);
4123 connman_mesh_set_address(connman_mesh, address);
4124 connman_mesh_set_index(connman_mesh, mesh_info->index);
4125 connman_mesh_set_strength(connman_mesh,
4126 calculate_strength(supplicant_network));
4127 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4129 ret = connman_mesh_register(connman_mesh);
4130 if (ret == -EALREADY)
4131 DBG("Mesh Peer is already registered");
4137 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4139 GSupplicantInterface *interface;
4140 struct wifi_data *wifi;
4141 struct connman_mesh *connman_mesh;
4142 struct wifi_mesh_info *mesh_info;
4143 const char *identifier;
4145 interface = g_supplicant_network_get_interface(supplicant_network);
4146 wifi = g_supplicant_interface_get_data(interface);
4147 if (!wifi || !wifi->mesh_interface) {
4148 DBG("Virtual Mesh interface not created");
4152 identifier = g_supplicant_network_get_identifier(supplicant_network);
4154 DBG("Failed to get Mesh Peer identifier");
4158 mesh_info = wifi->mesh_info;
4159 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4161 /* Do not unregister connected mesh peer */
4162 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4163 DBG("Mesh Peer %s is connected", identifier);
4166 DBG("Mesh Peer identifier %s removed", identifier);
4167 connman_mesh_unregister(connman_mesh);
4172 static void network_added(GSupplicantNetwork *supplicant_network)
4174 struct connman_network *network;
4175 GSupplicantInterface *interface;
4176 struct wifi_data *wifi;
4177 const char *name, *identifier, *security, *group, *mode;
4178 const unsigned char *ssid;
4179 unsigned int ssid_len;
4183 bool wps_advertizing;
4185 #if defined TIZEN_EXT
4186 GSList *vsie_list = NULL;
4187 const unsigned char *country_code;
4190 mode = g_supplicant_network_get_mode(supplicant_network);
4191 identifier = g_supplicant_network_get_identifier(supplicant_network);
4193 DBG("%s", identifier);
4195 if (!g_strcmp0(mode, "adhoc"))
4198 #if defined TIZEN_EXT_WIFI_MESH
4199 if (!g_strcmp0(mode, "mesh")) {
4200 mesh_peer_added(supplicant_network);
4205 interface = g_supplicant_network_get_interface(supplicant_network);
4206 wifi = g_supplicant_interface_get_data(interface);
4207 name = g_supplicant_network_get_name(supplicant_network);
4208 security = g_supplicant_network_get_security(supplicant_network);
4209 group = g_supplicant_network_get_identifier(supplicant_network);
4210 wps = g_supplicant_network_get_wps(supplicant_network);
4211 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4212 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4213 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4214 supplicant_network);
4219 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4221 network = connman_device_get_network(wifi->device, identifier);
4224 network = connman_network_create(identifier,
4225 CONNMAN_NETWORK_TYPE_WIFI);
4229 connman_network_set_index(network, wifi->index);
4231 if (connman_device_add_network(wifi->device, network) < 0) {
4232 connman_network_unref(network);
4236 wifi->networks = g_slist_prepend(wifi->networks, network);
4239 if (name && name[0] != '\0')
4240 connman_network_set_name(network, name);
4242 connman_network_set_blob(network, "WiFi.SSID",
4244 #if defined TIZEN_EXT
4245 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4247 connman_network_set_vsie_list(network, vsie_list);
4249 DBG("vsie_list is NULL");
4250 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4251 connman_network_set_countrycode(network, country_code);
4253 connman_network_set_string(network, "WiFi.Security", security);
4254 connman_network_set_strength(network,
4255 calculate_strength(supplicant_network));
4256 connman_network_set_bool(network, "WiFi.WPS", wps);
4259 /* Is AP advertizing for WPS association?
4260 * If so, we decide to use WPS by default */
4261 if (wps_ready && wps_pbc &&
4263 #if !defined TIZEN_EXT
4264 connman_network_set_bool(network, "WiFi.UseWPS", true);
4266 DBG("wps is activating by ap but ignore it.");
4271 connman_network_set_frequency(network,
4272 g_supplicant_network_get_frequency(supplicant_network));
4273 #if defined TIZEN_EXT
4274 connman_network_set_bssid(network,
4275 g_supplicant_network_get_bssid(supplicant_network));
4276 connman_network_set_maxrate(network,
4277 g_supplicant_network_get_maxrate(supplicant_network));
4278 connman_network_set_enc_mode(network,
4279 g_supplicant_network_get_enc_mode(supplicant_network));
4280 connman_network_set_rsn_mode(network,
4281 g_supplicant_network_get_rsn_mode(supplicant_network));
4282 connman_network_set_keymgmt(network,
4283 g_supplicant_network_get_keymgmt(supplicant_network));
4284 connman_network_set_bool(network, "WiFi.HS20AP",
4285 g_supplicant_network_is_hs20AP(supplicant_network));
4286 connman_network_set_bssid_list(network,
4287 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4289 connman_network_set_available(network, true);
4290 connman_network_set_string(network, "WiFi.Mode", mode);
4292 #if defined TIZEN_EXT
4297 connman_network_set_group(network, group);
4299 #if defined TIZEN_EXT
4300 if (wifi_first_scan == true)
4301 found_with_first_scan = true;
4304 if (wifi->hidden && ssid) {
4305 #if defined TIZEN_EXT
4306 if (network_security(wifi->hidden->security) ==
4307 network_security(security) &&
4309 if (!g_strcmp0(wifi->hidden->security, security) &&
4311 wifi->hidden->ssid_len == ssid_len &&
4312 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4313 connman_network_connect_hidden(network,
4314 wifi->hidden->identity,
4315 wifi->hidden->passphrase,
4316 wifi->hidden->user_data);
4317 wifi->hidden->user_data = NULL;
4318 hidden_free(wifi->hidden);
4319 wifi->hidden = NULL;
4324 static void network_removed(GSupplicantNetwork *network)
4326 GSupplicantInterface *interface;
4327 struct wifi_data *wifi;
4328 const char *name, *identifier;
4329 struct connman_network *connman_network;
4331 #if defined TIZEN_EXT_WIFI_MESH
4333 mode = g_supplicant_network_get_mode(network);
4334 if (!g_strcmp0(mode, "mesh")) {
4335 mesh_peer_removed(network);
4340 interface = g_supplicant_network_get_interface(network);
4341 wifi = g_supplicant_interface_get_data(interface);
4342 identifier = g_supplicant_network_get_identifier(network);
4343 name = g_supplicant_network_get_name(network);
4345 DBG("name %s", name);
4350 connman_network = connman_device_get_network(wifi->device, identifier);
4351 if (!connman_network)
4354 #if defined TIZEN_EXT
4355 if (connman_network == wifi->scan_pending_network)
4356 wifi->scan_pending_network = NULL;
4358 if (connman_network == wifi->pending_network)
4359 wifi->pending_network = NULL;
4361 if(connman_network_get_connecting(connman_network) == true){
4362 connman_network_set_connected(connman_network, false);
4366 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4368 connman_device_remove_network(wifi->device, connman_network);
4369 connman_network_unref(connman_network);
4372 static void network_changed(GSupplicantNetwork *network, const char *property)
4374 GSupplicantInterface *interface;
4375 struct wifi_data *wifi;
4376 const char *name, *identifier;
4377 struct connman_network *connman_network;
4379 #if defined TIZEN_EXT
4380 const unsigned char *bssid;
4381 unsigned int maxrate;
4384 const unsigned char *country_code;
4388 interface = g_supplicant_network_get_interface(network);
4389 wifi = g_supplicant_interface_get_data(interface);
4390 identifier = g_supplicant_network_get_identifier(network);
4391 name = g_supplicant_network_get_name(network);
4393 DBG("name %s", name);
4398 connman_network = connman_device_get_network(wifi->device, identifier);
4399 if (!connman_network)
4402 if (g_str_equal(property, "Signal")) {
4403 connman_network_set_strength(connman_network,
4404 calculate_strength(network));
4405 connman_network_update(connman_network);
4408 #if defined TIZEN_EXT
4409 bssid = g_supplicant_network_get_bssid(network);
4410 maxrate = g_supplicant_network_get_maxrate(network);
4411 frequency = g_supplicant_network_get_frequency(network);
4412 wps = g_supplicant_network_get_wps(network);
4414 connman_network_set_bssid(connman_network, bssid);
4415 connman_network_set_maxrate(connman_network, maxrate);
4416 connman_network_set_frequency(connman_network, frequency);
4417 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4418 country_code = g_supplicant_network_get_countrycode(network);
4419 connman_network_set_countrycode(connman_network, country_code);
4420 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4421 connman_network_set_bssid_list(connman_network, bssid_list);
4425 static void network_associated(GSupplicantNetwork *network)
4427 GSupplicantInterface *interface;
4428 struct wifi_data *wifi;
4429 struct connman_network *connman_network;
4430 const char *identifier;
4434 interface = g_supplicant_network_get_interface(network);
4438 wifi = g_supplicant_interface_get_data(interface);
4442 identifier = g_supplicant_network_get_identifier(network);
4444 connman_network = connman_device_get_network(wifi->device, identifier);
4445 if (!connman_network)
4448 if (wifi->network) {
4449 if (wifi->network == connman_network)
4453 * This should never happen, we got associated with
4454 * a network different than the one we were expecting.
4456 DBG("Associated to %p while expecting %p",
4457 connman_network, wifi->network);
4459 connman_network_set_associating(wifi->network, false);
4462 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4464 wifi->network = connman_network_ref(connman_network);
4468 * Interface state changes callback (interface_state) is always
4469 * called before network_associated callback thus we need to call
4470 * interface_state again in order to process the new state now that
4471 * we have the network properly set.
4473 interface_state(interface);
4476 static void apply_peer_services(GSupplicantPeer *peer,
4477 struct connman_peer *connman_peer)
4479 const unsigned char *data;
4484 connman_peer_reset_services(connman_peer);
4486 data = g_supplicant_peer_get_widi_ies(peer, &length);
4488 connman_peer_add_service(connman_peer,
4489 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4493 static void add_station(const char *mac)
4495 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4499 static void remove_station(const char *mac)
4501 connman_technology_tethering_remove_station(mac);
4504 static void peer_found(GSupplicantPeer *peer)
4506 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4507 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4508 struct connman_peer *connman_peer;
4509 const char *identifier, *name;
4511 #if defined TIZEN_EXT
4515 identifier = g_supplicant_peer_get_identifier(peer);
4516 name = g_supplicant_peer_get_name(peer);
4518 DBG("ident: %s", identifier);
4520 connman_peer = connman_peer_get(wifi->device, identifier);
4524 connman_peer = connman_peer_create(identifier);
4525 connman_peer_set_name(connman_peer, name);
4526 connman_peer_set_device(connman_peer, wifi->device);
4527 apply_peer_services(peer, connman_peer);
4529 ret = connman_peer_register(connman_peer);
4530 if (ret < 0 && ret != -EALREADY)
4531 connman_peer_unref(connman_peer);
4533 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4536 static void peer_lost(GSupplicantPeer *peer)
4538 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4539 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4540 struct connman_peer *connman_peer;
4541 const char *identifier;
4546 identifier = g_supplicant_peer_get_identifier(peer);
4548 DBG("ident: %s", identifier);
4550 connman_peer = connman_peer_get(wifi->device, identifier);
4552 if (wifi->p2p_connecting &&
4553 wifi->pending_peer == connman_peer) {
4554 peer_connect_timeout(wifi);
4556 connman_peer_unregister(connman_peer);
4557 connman_peer_unref(connman_peer);
4560 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4563 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4565 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4566 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4567 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4568 struct connman_peer *connman_peer;
4569 const char *identifier;
4571 identifier = g_supplicant_peer_get_identifier(peer);
4573 DBG("ident: %s", identifier);
4578 connman_peer = connman_peer_get(wifi->device, identifier);
4583 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4584 apply_peer_services(peer, connman_peer);
4585 connman_peer_services_changed(connman_peer);
4587 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4588 if (!g_supplicant_peer_is_in_a_group(peer))
4589 p_state = CONNMAN_PEER_STATE_IDLE;
4591 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4593 case G_SUPPLICANT_PEER_GROUP_STARTED:
4595 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4596 p_state = CONNMAN_PEER_STATE_IDLE;
4598 case G_SUPPLICANT_PEER_GROUP_JOINED:
4599 connman_peer_set_iface_address(connman_peer,
4600 g_supplicant_peer_get_iface_address(peer));
4602 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4603 p_state = CONNMAN_PEER_STATE_IDLE;
4605 case G_SUPPLICANT_PEER_GROUP_FAILED:
4606 if (g_supplicant_peer_has_requested_connection(peer))
4607 p_state = CONNMAN_PEER_STATE_IDLE;
4609 p_state = CONNMAN_PEER_STATE_FAILURE;
4613 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4614 p_state == CONNMAN_PEER_STATE_FAILURE) {
4615 if (wifi->p2p_connecting
4616 && connman_peer == wifi->pending_peer)
4617 peer_cancel_timeout(wifi);
4619 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4622 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4625 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4626 GSupplicantInterface *g_iface;
4627 struct wifi_data *g_wifi;
4629 g_iface = g_supplicant_peer_get_group_interface(peer);
4633 g_wifi = g_supplicant_interface_get_data(g_iface);
4637 connman_peer_set_as_master(connman_peer,
4638 !g_supplicant_peer_is_client(peer));
4639 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4642 * If wpa_supplicant didn't create a dedicated p2p-group
4643 * interface then mark this interface as p2p_device to avoid
4644 * scan and auto-scan are launched on it while P2P is connected.
4646 if (!g_list_find(p2p_iface_list, g_wifi))
4647 wifi->p2p_device = true;
4650 connman_peer_set_state(connman_peer, p_state);
4653 static void peer_request(GSupplicantPeer *peer)
4655 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4656 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4657 struct connman_peer *connman_peer;
4658 const char *identifier;
4660 #if defined TIZEN_EXT
4665 identifier = g_supplicant_peer_get_identifier(peer);
4667 DBG("ident: %s", identifier);
4669 connman_peer = connman_peer_get(wifi->device, identifier);
4673 connman_peer_request_connection(connman_peer);
4676 #if defined TIZEN_EXT
4677 static void system_power_off(void)
4680 struct wifi_data *wifi;
4681 struct connman_service *service;
4682 struct connman_ipconfig *ipconfig_ipv4;
4684 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4685 for (list = iface_list; list; list = list->next) {
4688 if (wifi->network != NULL) {
4689 service = connman_service_lookup_from_network(wifi->network);
4690 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4691 __connman_dhcp_stop(ipconfig_ipv4);
4697 static void network_merged(GSupplicantNetwork *network)
4699 GSupplicantInterface *interface;
4700 GSupplicantState state;
4701 struct wifi_data *wifi;
4702 const char *identifier;
4703 struct connman_network *connman_network;
4707 interface = g_supplicant_network_get_interface(network);
4711 state = g_supplicant_interface_get_state(interface);
4712 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4715 wifi = g_supplicant_interface_get_data(interface);
4719 identifier = g_supplicant_network_get_identifier(network);
4721 connman_network = connman_device_get_network(wifi->device, identifier);
4722 if (!connman_network)
4725 DBG("merged identifier %s", identifier);
4727 if (wifi->connected == FALSE) {
4729 case G_SUPPLICANT_STATE_AUTHENTICATING:
4730 case G_SUPPLICANT_STATE_ASSOCIATING:
4731 case G_SUPPLICANT_STATE_ASSOCIATED:
4732 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4733 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4734 connman_network_set_associating(connman_network, TRUE);
4736 case G_SUPPLICANT_STATE_COMPLETED:
4737 connman_network_set_connected(connman_network, TRUE);
4740 DBG("Not handled the state : %d", state);
4745 ishs20AP = g_supplicant_network_is_hs20AP(network);
4748 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
4749 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
4750 connman_network_set_string(connman_network, "WiFi.EAP",
4752 connman_network_set_string(connman_network, "WiFi.Identity",
4753 g_supplicant_network_get_identity(network));
4754 connman_network_set_string(connman_network, "WiFi.Phase2",
4755 g_supplicant_network_get_phase2(network));
4760 wifi->network = connman_network;
4763 static void assoc_failed(void *user_data)
4765 struct connman_network *network = user_data;
4766 connman_network_set_associating(network, false);
4770 static void debug(const char *str)
4772 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
4773 connman_debug("%s", str);
4776 static void disconnect_reasoncode(GSupplicantInterface *interface,
4779 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4782 wifi->disconnect_code = reasoncode;
4786 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
4788 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4791 wifi->assoc_code = status_code;
4795 static const GSupplicantCallbacks callbacks = {
4796 .system_ready = system_ready,
4797 .system_killed = system_killed,
4798 .interface_added = interface_added,
4799 .interface_state = interface_state,
4800 .interface_removed = interface_removed,
4801 .p2p_support = p2p_support,
4802 .scan_started = scan_started,
4803 .scan_finished = scan_finished,
4804 .ap_create_fail = ap_create_fail,
4805 .network_added = network_added,
4806 .network_removed = network_removed,
4807 .network_changed = network_changed,
4808 .network_associated = network_associated,
4809 .add_station = add_station,
4810 .remove_station = remove_station,
4811 .peer_found = peer_found,
4812 .peer_lost = peer_lost,
4813 .peer_changed = peer_changed,
4814 .peer_request = peer_request,
4815 #if defined TIZEN_EXT
4816 .system_power_off = system_power_off,
4817 .network_merged = network_merged,
4818 .assoc_failed = assoc_failed,
4821 .disconnect_reasoncode = disconnect_reasoncode,
4822 .assoc_status_code = assoc_status_code,
4823 #if defined TIZEN_EXT_WIFI_MESH
4824 .mesh_support = mesh_support,
4825 .mesh_group_started = mesh_group_started,
4826 .mesh_group_removed = mesh_group_removed,
4827 .mesh_peer_connected = mesh_peer_connected,
4828 .mesh_peer_disconnected = mesh_peer_disconnected,
4833 static int tech_probe(struct connman_technology *technology)
4835 wifi_technology = technology;
4840 static void tech_remove(struct connman_technology *technology)
4842 wifi_technology = NULL;
4845 static GSupplicantSSID *ssid_ap_init(const char *ssid,
4846 const char *passphrase)
4848 GSupplicantSSID *ap;
4850 ap = g_try_malloc0(sizeof(GSupplicantSSID));
4854 ap->mode = G_SUPPLICANT_MODE_MASTER;
4855 #if defined TIZEN_EXT
4856 ap->ssid = (void *) ssid;
4860 ap->ssid_len = strlen(ssid);
4864 if (!passphrase || strlen(passphrase) == 0) {
4865 ap->security = G_SUPPLICANT_SECURITY_NONE;
4866 ap->passphrase = NULL;
4868 ap->security = G_SUPPLICANT_SECURITY_PSK;
4869 ap->protocol = G_SUPPLICANT_PROTO_RSN;
4870 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
4871 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
4872 ap->passphrase = passphrase;
4878 static void ap_start_callback(int result, GSupplicantInterface *interface,
4881 struct wifi_tethering_info *info = user_data;
4883 DBG("result %d index %d bridge %s",
4884 result, info->wifi->index, info->wifi->bridge);
4886 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4887 connman_inet_remove_from_bridge(info->wifi->index,
4888 info->wifi->bridge);
4890 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4891 connman_technology_tethering_notify(info->technology, false);
4892 g_free(info->wifi->tethering_param->ssid);
4893 g_free(info->wifi->tethering_param);
4894 info->wifi->tethering_param = NULL;
4898 g_free(info->ifname);
4902 static void ap_create_callback(int result,
4903 GSupplicantInterface *interface,
4906 struct wifi_tethering_info *info = user_data;
4908 DBG("result %d ifname %s", result,
4909 g_supplicant_interface_get_ifname(interface));
4911 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4912 connman_inet_remove_from_bridge(info->wifi->index,
4913 info->wifi->bridge);
4915 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4916 connman_technology_tethering_notify(info->technology, false);
4917 g_free(info->wifi->tethering_param->ssid);
4918 g_free(info->wifi->tethering_param);
4919 info->wifi->tethering_param = NULL;
4923 g_free(info->ifname);
4929 info->wifi->interface = interface;
4930 g_supplicant_interface_set_data(interface, info->wifi);
4932 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
4933 connman_error("Failed to set interface ap_scan property");
4935 g_supplicant_interface_connect(interface, info->ssid,
4936 ap_start_callback, info);
4939 static void sta_remove_callback(int result,
4940 GSupplicantInterface *interface,
4943 struct wifi_tethering_info *info = user_data;
4944 const char *driver = connman_option_get_string("wifi");
4946 DBG("ifname %s result %d ", info->ifname, result);
4948 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4949 info->wifi->tethering = false;
4950 connman_technology_tethering_notify(info->technology, false);
4952 g_free(info->ifname);
4956 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4957 g_free(info->wifi->tethering_param->ssid);
4958 g_free(info->wifi->tethering_param);
4959 info->wifi->tethering_param = NULL;
4964 info->wifi->interface = NULL;
4966 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
4971 static int enable_wifi_tethering(struct connman_technology *technology,
4972 const char *bridge, const char *identifier,
4973 const char *passphrase, bool available)
4976 GSupplicantInterface *interface;
4977 struct wifi_data *wifi;
4978 struct wifi_tethering_info *info;
4983 for (list = iface_list; list; list = list->next) {
4986 DBG("wifi %p network %p pending_network %p", wifi,
4987 wifi->network, wifi->pending_network);
4989 interface = wifi->interface;
4994 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
4997 ifname = g_supplicant_interface_get_ifname(wifi->interface);
4999 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5000 DBG("%s does not support AP mode (detected)", ifname);
5004 mode = g_supplicant_interface_get_mode(interface);
5005 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5006 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5007 DBG("%s does not support AP mode (capability)", ifname);
5011 if (wifi->network && available)
5014 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5018 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5019 if (!wifi->tethering_param) {
5025 info->technology = technology;
5026 info->wifi->bridge = bridge;
5027 info->ssid = ssid_ap_init(identifier, passphrase);
5031 info->ifname = g_strdup(ifname);
5035 wifi->tethering_param->technology = technology;
5036 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5037 if (!wifi->tethering_param->ssid)
5040 info->wifi->tethering = true;
5041 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5043 berr = connman_technology_tethering_notify(technology, true);
5047 err = g_supplicant_interface_remove(interface,
5048 sta_remove_callback,
5051 DBG("tethering wifi %p ifname %s", wifi, ifname);
5056 g_free(info->ifname);
5059 g_free(wifi->tethering_param);
5060 wifi->tethering_param = NULL;
5063 * Remove bridge if it was correctly created but remove
5064 * operation failed. Instead, if bridge creation failed then
5065 * break out and do not try again on another interface,
5066 * bridge set-up does not depend on it.
5069 connman_technology_tethering_notify(technology, false);
5077 static int tech_set_tethering(struct connman_technology *technology,
5078 const char *identifier, const char *passphrase,
5079 const char *bridge, bool enabled)
5082 struct wifi_data *wifi;
5088 for (list = iface_list; list; list = list->next) {
5091 if (wifi->tethering) {
5092 wifi->tethering = false;
5094 connman_inet_remove_from_bridge(wifi->index,
5096 wifi->bridged = false;
5100 connman_technology_tethering_notify(technology, false);
5105 DBG("trying tethering for available devices");
5106 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5110 DBG("trying tethering for any device");
5111 err = enable_wifi_tethering(technology, bridge, identifier,
5118 static void regdom_callback(int result, const char *alpha2, void *user_data)
5122 if (!wifi_technology)
5128 connman_technology_regdom_notify(wifi_technology, alpha2);
5131 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5133 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5136 static struct connman_technology_driver tech_driver = {
5138 .type = CONNMAN_SERVICE_TYPE_WIFI,
5139 .probe = tech_probe,
5140 .remove = tech_remove,
5141 .set_tethering = tech_set_tethering,
5142 .set_regdom = tech_set_regdom,
5145 static int wifi_init(void)
5149 err = connman_network_driver_register(&network_driver);
5153 err = g_supplicant_register(&callbacks);
5155 connman_network_driver_unregister(&network_driver);
5159 err = connman_technology_driver_register(&tech_driver);
5161 g_supplicant_unregister(&callbacks);
5162 connman_network_driver_unregister(&network_driver);
5169 static void wifi_exit(void)
5173 connman_technology_driver_unregister(&tech_driver);
5175 g_supplicant_unregister(&callbacks);
5177 connman_network_driver_unregister(&network_driver);
5180 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5181 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)