5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <linux/if_arp.h>
34 #include <linux/wireless.h>
35 #include <net/ethernet.h>
38 #define IFF_LOWER_UP 0x10000
41 #include <dbus/dbus.h>
44 #define CONNMAN_API_SUBJECT_TO_CHANGE
45 #include <connman/plugin.h>
46 #include <connman/inet.h>
47 #include <connman/device.h>
48 #include <connman/rtnl.h>
49 #include <connman/technology.h>
50 #include <connman/service.h>
51 #include <connman/peer.h>
52 #include <connman/log.h>
53 #include <connman/option.h>
54 #include <connman/storage.h>
55 #include <include/setting.h>
56 #include <connman/provision.h>
57 #include <connman/utsname.h>
58 #include <connman/machine.h>
60 #include <gsupplicant/gsupplicant.h>
62 #define CLEANUP_TIMEOUT 8 /* in seconds */
63 #define INACTIVE_TIMEOUT 12 /* in seconds */
64 #define FAVORITE_MAXIMUM_RETRIES 2
66 #define BGSCAN_DEFAULT "simple:30:-45:300"
67 #define AUTOSCAN_DEFAULT "exponential:3:300"
69 #define P2P_FIND_TIMEOUT 30
70 #define P2P_CONNECTION_TIMEOUT 100
71 #define P2P_LISTEN_PERIOD 500
72 #define P2P_LISTEN_INTERVAL 2000
74 #define ASSOC_STATUS_NO_CLIENT 17
75 #define LOAD_SHAPING_MAX_RETRIES 3
78 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
81 static struct connman_technology *wifi_technology = NULL;
82 static struct connman_technology *p2p_technology = NULL;
84 enum wifi_ap_capability{
86 WIFI_AP_SUPPORTED = 1,
87 WIFI_AP_NOT_SUPPORTED = 2,
90 struct hidden_params {
92 unsigned int ssid_len;
94 char *anonymous_identity;
96 char *altsubject_match;
97 char *domain_suffix_match;
101 GSupplicantScanParams *scan_params;
106 * Used for autoscan "emulation".
107 * Should be removed when wpa_s autoscan support will be by default.
109 struct autoscan_params {
113 unsigned int timeout;
116 struct wifi_tethering_info {
117 struct wifi_data *wifi;
118 struct connman_technology *technology;
120 GSupplicantSSID *ssid;
125 struct connman_device *device;
126 struct connman_network *network;
127 struct connman_network *pending_network;
129 GSupplicantInterface *interface;
130 GSupplicantState state;
134 enum wifi_ap_capability ap_supported;
136 bool interface_ready;
142 int load_shaping_retries;
143 struct hidden_params *hidden;
144 bool postpone_hidden;
145 struct wifi_tethering_info *tethering_param;
147 * autoscan "emulation".
149 struct autoscan_params *autoscan;
151 GSupplicantScanParams *scan_params;
152 unsigned int p2p_find_timeout;
153 unsigned int p2p_connection_timeout;
154 struct connman_peer *pending_peer;
159 #if defined TIZEN_EXT
160 int assoc_retry_count;
161 struct connman_network *scan_pending_network;
162 bool allow_full_scan;
166 #if defined TIZEN_EXT_WIFI_MESH
168 struct wifi_mesh_info *mesh_info;
172 #if defined TIZEN_EXT
176 #define TIZEN_ASSOC_RETRY_COUNT 4
178 static gboolean wifi_first_scan = false;
179 static gboolean found_with_first_scan = false;
180 static gboolean is_wifi_notifier_registered = false;
184 static GList *iface_list = NULL;
186 static GList *pending_wifi_device = NULL;
187 static GList *p2p_iface_list = NULL;
188 bool wfd_service_registered = false;
190 static void start_autoscan(struct connman_device *device);
192 static int tech_set_tethering(struct connman_technology *technology,
193 const char *identifier, const char *passphrase,
194 const char *bridge, bool enabled);
196 #if defined TIZEN_EXT
197 #define NETCONFIG_SERVICE "net.netconfig"
198 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
199 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
201 struct enc_method_call_data {
202 DBusConnection *connection;
203 struct connman_network *network;
206 static struct enc_method_call_data encrypt_request_data;
208 static void encryption_request_reply(DBusPendingCall *call,
213 DBusMessageIter args;
215 struct connman_service *service;
216 gchar* encrypted_value = NULL;
217 struct connman_network *network = encrypt_request_data.network;
221 reply = dbus_pending_call_steal_reply(call);
223 dbus_error_init(&error);
224 if (dbus_set_error_from_message(&error, reply)) {
225 DBG("send_encryption_request() %s %s", error.name, error.message);
226 dbus_error_free(&error);
230 if (dbus_message_iter_init(reply, &args) == FALSE)
233 dbus_message_iter_get_basic(&args, &out_data);
235 encrypted_value = g_strdup((const gchar *)out_data);
236 service = connman_service_lookup_from_network(network);
239 DBG("encryption result: no service");
243 if (connman_service_get_favorite(service)) {
244 __connman_service_set_passphrase(service, encrypted_value);
245 __connman_service_save(service);
247 connman_network_set_string(network, "WiFi.Passphrase",
250 DBG("encryption result: succeeded");
253 dbus_message_unref(reply);
254 dbus_pending_call_unref(call);
255 dbus_connection_unref(encrypt_request_data.connection);
256 g_free(encrypted_value);
258 encrypt_request_data.connection = NULL;
259 encrypt_request_data.network = NULL;
262 static int send_encryption_request(const char *passphrase,
263 struct connman_network *network)
265 DBusConnection *connection = NULL;
266 DBusMessage *msg = NULL;
267 DBusPendingCall *call;
270 DBG("Invalid parameter");
274 connection = connman_dbus_get_connection();
276 DBG("dbus connection does not exist");
280 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
281 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
283 dbus_connection_unref(connection);
287 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
290 if (!dbus_connection_send_with_reply(connection, msg,
291 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
292 dbus_message_unref(msg);
293 dbus_connection_unref(connection);
298 dbus_message_unref(msg);
299 dbus_connection_unref(connection);
303 encrypt_request_data.connection = connection;
304 encrypt_request_data.network = network;
306 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
307 dbus_message_unref(msg);
313 static int p2p_tech_probe(struct connman_technology *technology)
315 p2p_technology = technology;
320 static void p2p_tech_remove(struct connman_technology *technology)
322 p2p_technology = NULL;
325 static struct connman_technology_driver p2p_tech_driver = {
327 .type = CONNMAN_SERVICE_TYPE_P2P,
328 .probe = p2p_tech_probe,
329 .remove = p2p_tech_remove,
332 static bool is_p2p_connecting(void)
336 for (list = iface_list; list; list = list->next) {
337 struct wifi_data *wifi = list->data;
339 if (wifi->p2p_connecting)
346 static void add_pending_wifi_device(struct wifi_data *wifi)
348 if (g_list_find(pending_wifi_device, wifi))
351 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
354 #if defined TIZEN_EXT_WIFI_MESH
355 struct wifi_mesh_info {
356 struct wifi_data *wifi;
357 GSupplicantInterface *interface;
358 struct connman_mesh *mesh;
365 struct mesh_change_peer_status_info {
367 enum connman_mesh_peer_status peer_status;
368 mesh_change_peer_status_cb_t callback;
372 static struct connman_technology_driver mesh_tech_driver = {
374 .type = CONNMAN_SERVICE_TYPE_MESH,
377 static void mesh_interface_create_callback(int result,
378 GSupplicantInterface *interface,
381 struct wifi_mesh_info *mesh_info = user_data;
382 struct wifi_data *wifi;
383 bool success = false;
385 DBG("result %d ifname %s, mesh_info %p", result,
386 g_supplicant_interface_get_ifname(interface),
389 if (result < 0 || !mesh_info)
392 wifi = mesh_info->wifi;
394 mesh_info->interface = interface;
395 mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
396 mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
397 DBG("Mesh Interface identifier %s", mesh_info->identifier);
398 wifi->mesh_interface = true;
399 wifi->mesh_info = mesh_info;
400 g_supplicant_interface_set_data(interface, wifi);
404 connman_mesh_notify_interface_create(success);
407 static int add_mesh_interface(const char *ifname, const char *parent_ifname)
410 struct wifi_data *wifi;
411 struct wifi_mesh_info *mesh_info;
412 const char *wifi_ifname;
413 bool parent_found = false;
414 const char *driver = "nl80211";
416 for (list = iface_list; list; list = list->next) {
419 if (!g_supplicant_interface_has_mesh(wifi->interface))
422 wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
426 if (!g_strcmp0(wifi_ifname, parent_ifname)) {
433 DBG("Parent interface %s doesn't exist", parent_ifname);
437 mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
441 mesh_info->wifi = wifi;
442 mesh_info->ifname = g_strdup(ifname);
443 mesh_info->parent_ifname = g_strdup(parent_ifname);
445 g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
446 mesh_interface_create_callback, mesh_info);
450 static void mesh_interface_remove_callback(int result,
451 GSupplicantInterface *interface,
454 struct wifi_data *wifi = user_data;
455 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
456 bool success = false;
458 DBG("result %d mesh_info %p", result, mesh_info);
460 if (result < 0 || !mesh_info)
463 mesh_info->interface = NULL;
464 g_free(mesh_info->parent_ifname);
465 g_free(mesh_info->ifname);
466 g_free(mesh_info->identifier);
468 wifi->mesh_interface = false;
469 wifi->mesh_info = NULL;
473 connman_mesh_notify_interface_remove(success);
476 static int remove_mesh_interface(const char *ifname)
479 struct wifi_data *wifi;
480 struct wifi_mesh_info *mesh_info;
481 bool mesh_if_found = false;
484 for (list = iface_list; list; list = list->next) {
487 if (wifi->mesh_interface) {
488 mesh_if_found = true;
493 if (!mesh_if_found) {
494 DBG("Mesh interface %s doesn't exist", ifname);
498 mesh_info = wifi->mesh_info;
499 ret = g_supplicant_interface_remove(mesh_info->interface,
500 mesh_interface_remove_callback, wifi);
507 static void mesh_disconnect_callback(int result,
508 GSupplicantInterface *interface, void *user_data)
510 struct connman_mesh *mesh = user_data;
512 DBG("result %d interface %p mesh %p", result, interface, mesh);
515 static int mesh_peer_disconnect(struct connman_mesh *mesh)
518 struct wifi_data *wifi;
519 struct wifi_mesh_info *mesh_info;
520 bool mesh_if_found = false;
521 GSupplicantInterface *interface;
523 for (list = iface_list; list; list = list->next) {
526 if (wifi->mesh_interface) {
527 mesh_if_found = true;
532 if (!mesh_if_found) {
533 DBG("Mesh interface is not created");
537 mesh_info = wifi->mesh_info;
539 interface = mesh_info->interface;
540 return g_supplicant_interface_disconnect(interface,
541 mesh_disconnect_callback, mesh);
544 static void mesh_connect_callback(int result, GSupplicantInterface *interface,
547 struct connman_mesh *mesh = user_data;
548 DBG("mesh %p result %d", mesh, result);
551 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
553 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
556 static GSupplicantSecurity mesh_network_security(const char *security)
558 if (g_str_equal(security, "none"))
559 return G_SUPPLICANT_SECURITY_NONE;
560 else if (g_str_equal(security, "sae"))
561 return G_SUPPLICANT_SECURITY_SAE;
563 return G_SUPPLICANT_SECURITY_UNKNOWN;
566 static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
569 const char *security;
574 memset(ssid, 0, sizeof(*ssid));
575 ssid->mode = G_SUPPLICANT_MODE_MESH;
577 security = connman_mesh_get_security(mesh);
578 ssid->security = mesh_network_security(security);
580 if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
581 ssid->passphrase = connman_mesh_get_passphrase(mesh);
583 ssid->freq = connman_mesh_get_frequency(mesh);
584 name = connman_mesh_get_name(mesh);
586 ssid->ssid_len = strlen(name);
587 ssid->ssid = g_malloc0(ssid->ssid_len + 1);
588 memcpy(ssid->ssid, name, ssid->ssid_len);
593 static int mesh_peer_connect(struct connman_mesh *mesh)
596 struct wifi_data *wifi;
597 struct wifi_mesh_info *mesh_info;
598 bool mesh_if_found = false;
599 GSupplicantInterface *interface;
600 GSupplicantSSID *ssid;
602 for (list = iface_list; list; list = list->next) {
605 if (wifi->mesh_interface) {
606 mesh_if_found = true;
611 if (!mesh_if_found) {
612 DBG("Mesh interface is not created");
616 mesh_info = wifi->mesh_info;
618 interface = mesh_info->interface;
620 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
624 mesh_info->mesh = mesh;
626 mesh_ssid_init(ssid, mesh);
627 return g_supplicant_interface_connect(interface, ssid,
628 mesh_connect_callback, mesh);
631 static void mesh_peer_change_status_callback(int result,
632 GSupplicantInterface *interface,
635 struct mesh_change_peer_status_info *data = user_data;
637 DBG("result %d Peer Status %d", result, data->peer_status);
639 if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
640 /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
641 connman_mesh_remove_connected_peer(data->peer_address, 52);
645 data->callback(result, data->user_data);
647 g_free(data->peer_address);
652 static int mesh_change_peer_status(const char *peer_address,
653 enum connman_mesh_peer_status status,
654 mesh_change_peer_status_cb_t callback, void *user_data)
657 struct wifi_data *wifi;
658 struct wifi_mesh_info *mesh_info;
659 bool mesh_if_found = false;
660 GSupplicantInterface *interface;
661 struct mesh_change_peer_status_info *data;
664 for (list = iface_list; list; list = list->next) {
667 if (wifi->mesh_interface) {
668 mesh_if_found = true;
673 if (!mesh_if_found) {
674 DBG("Mesh interface is not created");
678 mesh_info = wifi->mesh_info;
680 interface = mesh_info->interface;
683 case CONNMAN_MESH_PEER_ADD:
684 method = "MeshPeerAdd";
686 case CONNMAN_MESH_PEER_REMOVE:
687 method = "MeshPeerRemove";
690 DBG("Invalid method");
694 data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
696 DBG("Memory allocation failed");
700 data->peer_address = g_strdup(peer_address);
701 data->peer_status = status;
702 data->callback = callback;
703 data->user_data = user_data;
705 return g_supplicant_interface_mesh_peer_change_status(interface,
706 mesh_peer_change_status_callback, peer_address, method,
710 static struct connman_mesh_driver mesh_driver = {
711 .add_interface = add_mesh_interface,
712 .remove_interface = remove_mesh_interface,
713 .connect = mesh_peer_connect,
714 .disconnect = mesh_peer_disconnect,
715 .change_peer_status = mesh_change_peer_status,
718 static void mesh_support(GSupplicantInterface *interface)
722 if (!g_supplicant_interface_has_mesh(interface))
725 if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
726 DBG("Could not register Mesh technology driver");
730 connman_mesh_driver_register(&mesh_driver);
733 static void check_mesh_technology(void)
735 bool mesh_exists = false;
738 for (list = iface_list; list; list = list->next) {
739 struct wifi_data *w = list->data;
742 g_supplicant_interface_has_mesh(w->interface))
747 connman_technology_driver_unregister(&mesh_tech_driver);
748 connman_mesh_driver_unregister(&mesh_driver);
752 static void mesh_group_started(GSupplicantInterface *interface)
754 struct wifi_data *wifi;
755 struct wifi_mesh_info *mesh_info;
756 struct connman_mesh *mesh;
757 const unsigned char *ssid;
758 unsigned int ssid_len;
761 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
762 memcpy(name, ssid, ssid_len);
763 name[ssid_len] = '\0';
764 DBG("name %s", name);
765 wifi = g_supplicant_interface_get_data(interface);
766 DBG("wifi %p", wifi);
771 mesh_info = wifi->mesh_info;
775 mesh = mesh_info->mesh;
779 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
782 static void mesh_group_removed(GSupplicantInterface *interface)
784 struct wifi_data *wifi;
785 struct wifi_mesh_info *mesh_info;
786 struct connman_mesh *mesh;
787 const unsigned char *ssid;
788 unsigned int ssid_len;
789 int disconnect_reason;
792 ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
793 memcpy(name, ssid, ssid_len);
794 name[ssid_len] = '\0';
795 DBG("name %s", name);
797 disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
798 DBG("Disconnect Reason %d", disconnect_reason);
800 wifi = g_supplicant_interface_get_data(interface);
801 DBG("wifi %p", wifi);
806 mesh_info = wifi->mesh_info;
810 mesh = connman_get_connected_mesh_from_name(name);
812 DBG("%s is not connected", name);
813 mesh = connman_get_connecting_mesh_from_name(name);
815 DBG("%s is not connecting", name);
820 connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
821 connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
824 static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
826 const char *peer_address;
828 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
833 DBG("Peer %s connected", peer_address);
834 connman_mesh_add_connected_peer(peer_address);
837 static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
839 const char *peer_address;
842 peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
847 reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
849 DBG("Peer %s disconnected with reason %d", peer_address, reason);
850 connman_mesh_remove_connected_peer(peer_address, reason);
854 static struct wifi_data *get_pending_wifi_data(const char *ifname)
858 for (list = pending_wifi_device; list; list = list->next) {
859 struct wifi_data *wifi;
860 const char *dev_name;
863 if (!wifi || !wifi->device)
866 dev_name = connman_device_get_string(wifi->device, "Interface");
867 if (!g_strcmp0(ifname, dev_name)) {
868 pending_wifi_device = g_list_delete_link(
869 pending_wifi_device, list);
877 static void remove_pending_wifi_device(struct wifi_data *wifi)
881 link = g_list_find(pending_wifi_device, wifi);
886 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
889 static void peer_cancel_timeout(struct wifi_data *wifi)
891 if (wifi->p2p_connection_timeout > 0)
892 g_source_remove(wifi->p2p_connection_timeout);
894 wifi->p2p_connection_timeout = 0;
895 wifi->p2p_connecting = false;
897 if (wifi->pending_peer) {
898 connman_peer_unref(wifi->pending_peer);
899 wifi->pending_peer = NULL;
903 static gboolean peer_connect_timeout(gpointer data)
905 struct wifi_data *wifi = data;
909 if (wifi->p2p_connecting) {
910 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
911 GSupplicantPeer *gs_peer =
912 g_supplicant_interface_peer_lookup(wifi->interface,
913 connman_peer_get_identifier(wifi->pending_peer));
915 if (g_supplicant_peer_has_requested_connection(gs_peer))
916 state = CONNMAN_PEER_STATE_IDLE;
918 connman_peer_set_state(wifi->pending_peer, state);
921 peer_cancel_timeout(wifi);
926 static void peer_connect_callback(int result, GSupplicantInterface *interface,
929 struct wifi_data *wifi = user_data;
930 struct connman_peer *peer = wifi->pending_peer;
932 DBG("peer %p - %d", peer, result);
938 peer_connect_timeout(wifi);
942 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
944 wifi->p2p_connection_timeout = g_timeout_add_seconds(
945 P2P_CONNECTION_TIMEOUT,
946 peer_connect_timeout, wifi);
949 static int peer_connect(struct connman_peer *peer,
950 enum connman_peer_wps_method wps_method,
953 struct connman_device *device = connman_peer_get_device(peer);
954 GSupplicantPeerParams *peer_params;
955 GSupplicantPeer *gs_peer;
956 struct wifi_data *wifi;
960 DBG("peer %p", peer);
965 wifi = connman_device_get_data(device);
966 if (!wifi || !wifi->interface)
969 if (wifi->p2p_connecting)
972 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
973 connman_peer_get_identifier(peer));
977 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
978 pin = g_supplicant_peer_is_wps_pin(gs_peer);
980 switch (wps_method) {
981 case CONNMAN_PEER_WPS_UNKNOWN:
982 if ((pbc && pin) || pin)
985 case CONNMAN_PEER_WPS_PBC:
990 case CONNMAN_PEER_WPS_PIN:
991 if (!pin || !wps_pin)
996 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
1000 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1002 peer_params->wps_pin = g_strdup(wps_pin);
1004 peer_params->master = connman_peer_service_is_master();
1006 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
1007 peer_connect_callback, wifi);
1008 if (ret == -EINPROGRESS) {
1009 wifi->pending_peer = connman_peer_ref(peer);
1010 wifi->p2p_connecting = true;
1011 } else if (ret < 0) {
1012 g_free(peer_params->path);
1013 g_free(peer_params->wps_pin);
1014 g_free(peer_params);
1020 static int peer_disconnect(struct connman_peer *peer)
1022 struct connman_device *device = connman_peer_get_device(peer);
1023 GSupplicantPeerParams peer_params = {};
1024 GSupplicantPeer *gs_peer;
1025 struct wifi_data *wifi;
1028 DBG("peer %p", peer);
1033 wifi = connman_device_get_data(device);
1037 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
1038 connman_peer_get_identifier(peer));
1042 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
1044 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
1046 g_free(peer_params.path);
1048 if (ret == -EINPROGRESS) {
1049 peer_cancel_timeout(wifi);
1050 wifi->p2p_device = false;
1056 struct peer_service_registration {
1057 peer_service_registration_cb_t callback;
1061 static bool is_service_wfd(const unsigned char *specs, int length)
1063 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
1069 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
1071 struct wifi_data *wifi = data;
1073 if (!wifi->interface ||
1074 !g_supplicant_interface_has_p2p(wifi->interface))
1077 if (!wifi->servicing) {
1078 g_supplicant_interface_p2p_listen(wifi->interface,
1079 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
1085 static void register_wfd_service_cb(int result,
1086 GSupplicantInterface *iface, void *user_data)
1088 struct peer_service_registration *reg_data = user_data;
1093 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
1095 if (reg_data && reg_data->callback) {
1096 reg_data->callback(result, reg_data->user_data);
1101 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
1102 const unsigned char *spec,
1103 int spec_length, const unsigned char *query,
1104 int query_length, int version)
1106 GSupplicantP2PServiceParams *params;
1108 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
1113 params->version = version;
1114 params->service = g_memdup(spec, spec_length);
1115 } else if (query_length > 0 && spec_length > 0) {
1116 params->query = g_memdup(query, query_length);
1117 params->query_length = query_length;
1119 params->response = g_memdup(spec, spec_length);
1120 params->response_length = spec_length;
1122 params->wfd_ies = g_memdup(spec, spec_length);
1123 params->wfd_ies_length = spec_length;
1129 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
1134 g_free(params->service);
1135 g_free(params->query);
1136 g_free(params->response);
1137 g_free(params->wfd_ies);
1142 static int peer_register_wfd_service(const unsigned char *specification,
1143 int specification_length,
1144 peer_service_registration_cb_t callback,
1147 struct peer_service_registration *reg_data = NULL;
1148 static GSupplicantP2PServiceParams *params;
1153 if (wfd_service_registered)
1156 params = fill_in_peer_service_params(specification,
1157 specification_length, NULL, 0, 0);
1161 reg_data = g_try_malloc0(sizeof(*reg_data));
1167 reg_data->callback = callback;
1168 reg_data->user_data = user_data;
1170 ret = g_supplicant_set_widi_ies(params,
1171 register_wfd_service_cb, reg_data);
1172 if (ret < 0 && ret != -EINPROGRESS)
1175 wfd_service_registered = true;
1179 free_peer_service_params(params);
1185 static void register_peer_service_cb(int result,
1186 GSupplicantInterface *iface, void *user_data)
1188 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
1189 struct peer_service_registration *reg_data = user_data;
1191 #if defined TIZEN_EXT
1199 apply_p2p_listen_on_iface(wifi, NULL);
1201 if (reg_data->callback)
1202 reg_data->callback(result, reg_data->user_data);
1207 static int peer_register_service(const unsigned char *specification,
1208 int specification_length,
1209 const unsigned char *query,
1210 int query_length, int version,
1211 peer_service_registration_cb_t callback,
1214 struct peer_service_registration *reg_data;
1215 GSupplicantP2PServiceParams *params;
1222 if (specification && !version && !query &&
1223 is_service_wfd(specification, specification_length)) {
1224 return peer_register_wfd_service(specification,
1225 specification_length, callback, user_data);
1228 reg_data = g_try_malloc0(sizeof(*reg_data));
1232 reg_data->callback = callback;
1233 reg_data->user_data = user_data;
1235 ret_f = -EOPNOTSUPP;
1237 for (list = iface_list; list; list = list->next) {
1238 struct wifi_data *wifi = list->data;
1239 GSupplicantInterface *iface = wifi->interface;
1241 if (!g_supplicant_interface_has_p2p(iface))
1244 params = fill_in_peer_service_params(specification,
1245 specification_length, query,
1246 query_length, version);
1253 ret_f = g_supplicant_interface_p2p_add_service(iface,
1254 register_peer_service_cb, params, reg_data);
1255 if (ret_f == 0 || ret_f == -EINPROGRESS)
1259 ret = g_supplicant_interface_p2p_add_service(iface,
1260 register_peer_service_cb, params, NULL);
1261 if (ret != 0 && ret != -EINPROGRESS)
1262 free_peer_service_params(params);
1265 if (ret_f != 0 && ret_f != -EINPROGRESS)
1271 static int peer_unregister_wfd_service(void)
1273 GSupplicantP2PServiceParams *params;
1276 if (!wfd_service_registered)
1279 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
1283 wfd_service_registered = false;
1285 g_supplicant_set_widi_ies(params, NULL, NULL);
1287 for (list = iface_list; list; list = list->next) {
1288 struct wifi_data *wifi = list->data;
1290 if (!g_supplicant_interface_has_p2p(wifi->interface))
1294 if (!wifi->servicing || wifi->servicing < 0) {
1295 g_supplicant_interface_p2p_listen(wifi->interface,
1297 wifi->servicing = 0;
1304 static int peer_unregister_service(const unsigned char *specification,
1305 int specification_length,
1306 const unsigned char *query,
1307 int query_length, int version)
1309 GSupplicantP2PServiceParams *params;
1314 if (specification && !version && !query &&
1315 is_service_wfd(specification, specification_length)) {
1316 ret = peer_unregister_wfd_service();
1317 if (ret != 0 && ret != -EINPROGRESS)
1322 for (list = iface_list; list; list = list->next) {
1323 struct wifi_data *wifi = list->data;
1324 GSupplicantInterface *iface = wifi->interface;
1327 goto stop_listening;
1329 if (!g_supplicant_interface_has_p2p(iface))
1332 params = fill_in_peer_service_params(specification,
1333 specification_length, query,
1334 query_length, version);
1340 ret = g_supplicant_interface_p2p_del_service(iface, params);
1341 if (ret != 0 && ret != -EINPROGRESS)
1342 free_peer_service_params(params);
1345 if (!wifi->servicing || wifi->servicing < 0) {
1346 g_supplicant_interface_p2p_listen(iface, 0, 0);
1347 wifi->servicing = 0;
1354 static struct connman_peer_driver peer_driver = {
1355 .connect = peer_connect,
1356 .disconnect = peer_disconnect,
1357 .register_service = peer_register_service,
1358 .unregister_service = peer_unregister_service,
1361 static void handle_tethering(struct wifi_data *wifi)
1363 if (!wifi->tethering)
1372 DBG("index %d bridge %s", wifi->index, wifi->bridge);
1374 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
1377 wifi->bridged = true;
1380 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
1382 struct connman_device *device = user_data;
1383 struct wifi_data *wifi = connman_device_get_data(device);
1388 DBG("index %d flags %d change %d", wifi->index, flags, change);
1390 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
1392 DBG("interface up");
1394 DBG("interface down");
1397 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1398 if (flags & IFF_LOWER_UP) {
1401 handle_tethering(wifi);
1406 wifi->flags = flags;
1409 static int wifi_probe(struct connman_device *device)
1411 struct wifi_data *wifi;
1413 DBG("device %p", device);
1415 wifi = g_try_new0(struct wifi_data, 1);
1419 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
1420 wifi->ap_supported = WIFI_AP_UNKNOWN;
1421 wifi->tethering_param = NULL;
1423 connman_device_set_data(device, wifi);
1424 wifi->device = connman_device_ref(device);
1426 wifi->index = connman_device_get_index(device);
1429 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
1430 wifi_newlink, device);
1431 if (is_p2p_connecting())
1432 add_pending_wifi_device(wifi);
1434 iface_list = g_list_append(iface_list, wifi);
1439 static void remove_networks(struct connman_device *device,
1440 struct wifi_data *wifi)
1444 for (list = wifi->networks; list; list = list->next) {
1445 struct connman_network *network = list->data;
1447 connman_device_remove_network(device, network);
1448 connman_network_unref(network);
1451 g_slist_free(wifi->networks);
1452 wifi->networks = NULL;
1455 static void remove_peers(struct wifi_data *wifi)
1459 for (list = wifi->peers; list; list = list->next) {
1460 struct connman_peer *peer = list->data;
1462 connman_peer_unregister(peer);
1463 connman_peer_unref(peer);
1466 g_slist_free(wifi->peers);
1470 static void reset_autoscan(struct connman_device *device)
1472 struct wifi_data *wifi = connman_device_get_data(device);
1473 struct autoscan_params *autoscan;
1477 if (!wifi || !wifi->autoscan)
1480 autoscan = wifi->autoscan;
1482 if (autoscan->timeout == 0 && autoscan->interval == 0)
1485 g_source_remove(autoscan->timeout);
1487 autoscan->timeout = 0;
1488 autoscan->interval = 0;
1490 connman_device_unref(device);
1493 static void stop_autoscan(struct connman_device *device)
1495 const struct wifi_data *wifi = connman_device_get_data(device);
1497 if (!wifi || !wifi->autoscan)
1500 reset_autoscan(device);
1502 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1505 static void check_p2p_technology(void)
1507 bool p2p_exists = false;
1510 for (list = iface_list; list; list = list->next) {
1511 struct wifi_data *w = list->data;
1514 g_supplicant_interface_has_p2p(w->interface))
1519 connman_technology_driver_unregister(&p2p_tech_driver);
1520 connman_peer_driver_unregister(&peer_driver);
1524 static void wifi_remove(struct connman_device *device)
1526 struct wifi_data *wifi = connman_device_get_data(device);
1528 DBG("device %p wifi %p", device, wifi);
1533 stop_autoscan(device);
1535 if (wifi->p2p_device)
1536 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1538 iface_list = g_list_remove(iface_list, wifi);
1540 check_p2p_technology();
1541 #if defined TIZEN_EXT_WIFI_MESH
1542 check_mesh_technology();
1545 remove_pending_wifi_device(wifi);
1547 if (wifi->p2p_find_timeout) {
1548 g_source_remove(wifi->p2p_find_timeout);
1549 connman_device_unref(wifi->device);
1552 if (wifi->p2p_connection_timeout)
1553 g_source_remove(wifi->p2p_connection_timeout);
1555 remove_networks(device, wifi);
1558 connman_device_set_powered(device, false);
1559 connman_device_set_data(device, NULL);
1560 connman_device_unref(wifi->device);
1561 connman_rtnl_remove_watch(wifi->watch);
1563 g_supplicant_interface_set_data(wifi->interface, NULL);
1565 g_supplicant_interface_cancel(wifi->interface);
1567 if (wifi->scan_params)
1568 g_supplicant_free_scan_params(wifi->scan_params);
1570 g_free(wifi->autoscan);
1571 g_free(wifi->identifier);
1575 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1579 for (iter = list; iter; iter = g_slist_next(iter)) {
1580 struct scan_ssid *scan_ssid = iter->data;
1582 if (ssid_len == scan_ssid->ssid_len &&
1583 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1590 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1591 int freq, GSupplicantScanParams *scan_data,
1592 int driver_max_scan_ssids, char *ssid_name)
1595 struct scan_ssid *scan_ssid;
1597 if ((driver_max_scan_ssids == 0 ||
1598 driver_max_scan_ssids > scan_data->num_ssids) &&
1599 (hex_ssid || raw_ssid)) {
1601 unsigned int j = 0, hex;
1604 size_t hex_ssid_len = strlen(hex_ssid);
1606 ssid = g_try_malloc0(hex_ssid_len / 2);
1610 for (i = 0; i < hex_ssid_len; i += 2) {
1611 sscanf(hex_ssid + i, "%02x", &hex);
1620 * If we have already added hidden AP to the list,
1621 * then do not do it again. This might happen if you have
1622 * used or are using multiple wifi cards, so in that case
1623 * you might have multiple service files for same AP.
1625 if (is_duplicate(scan_data->ssids, ssid, j)) {
1631 scan_ssid = g_try_new(struct scan_ssid, 1);
1638 memcpy(scan_ssid->ssid, ssid, j);
1639 scan_ssid->ssid_len = j;
1640 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1643 scan_data->num_ssids++;
1645 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1646 scan_data->num_ssids);
1653 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1655 if (!scan_data->freqs) {
1656 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1657 if (!scan_data->freqs) {
1658 g_slist_free_full(scan_data->ssids, g_free);
1662 scan_data->num_freqs = 1;
1663 scan_data->freqs[0] = freq;
1665 bool duplicate = false;
1667 /* Don't add duplicate entries */
1668 for (i = 0; i < scan_data->num_freqs; i++) {
1669 if (scan_data->freqs[i] == freq) {
1676 scan_data->num_freqs++;
1677 scan_data->freqs = g_try_realloc(scan_data->freqs,
1678 sizeof(uint16_t) * scan_data->num_freqs);
1679 if (!scan_data->freqs) {
1680 g_slist_free_full(scan_data->ssids, g_free);
1683 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1690 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1692 struct connman_config_entry **entries;
1698 int num_ssids = 0, add_param_failed = 0;
1700 services = connman_storage_get_services();
1701 for (i = 0; services && services[i]; i++) {
1702 if (strncmp(services[i], "wifi_", 5) != 0)
1705 keyfile = connman_storage_load_service(services[i]);
1709 value = g_key_file_get_boolean(keyfile,
1710 services[i], "Hidden", NULL);
1712 g_key_file_free(keyfile);
1716 value = g_key_file_get_boolean(keyfile,
1717 services[i], "Favorite", NULL);
1719 g_key_file_free(keyfile);
1723 #if defined TIZEN_EXT
1724 value = g_key_file_get_boolean(keyfile,
1725 services[i], "AutoConnect", NULL);
1727 g_key_file_free(keyfile);
1732 ssid = g_key_file_get_string(keyfile,
1733 services[i], "SSID", NULL);
1735 name = g_key_file_get_string(keyfile, services[i], "Name",
1738 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1746 g_key_file_free(keyfile);
1750 * Check if there are any hidden AP that needs to be provisioned.
1752 entries = connman_config_get_entries("wifi");
1753 for (i = 0; entries && entries[i]; i++) {
1756 if (!entries[i]->hidden)
1759 if (!entries[i]->ssid) {
1760 ssid = entries[i]->name;
1763 ssid = entries[i]->ssid;
1764 len = entries[i]->ssid_len;
1770 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1777 connman_config_free_entries(entries);
1779 if (add_param_failed > 0)
1780 DBG("Unable to scan %d out of %d SSIDs",
1781 add_param_failed, num_ssids);
1783 g_strfreev(services);
1788 static int get_hidden_connections_params(struct wifi_data *wifi,
1789 GSupplicantScanParams *scan_params)
1791 int driver_max_ssids, i;
1792 GSupplicantScanParams *orig_params;
1795 * Scan hidden networks so that we can autoconnect to them.
1796 * We will assume 1 as a default number of ssid to scan.
1798 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1800 if (driver_max_ssids == 0)
1801 driver_max_ssids = 1;
1803 DBG("max ssids %d", driver_max_ssids);
1805 if (!wifi->scan_params) {
1806 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1807 if (!wifi->scan_params)
1810 if (get_hidden_connections(wifi->scan_params) == 0) {
1811 g_supplicant_free_scan_params(wifi->scan_params);
1812 wifi->scan_params = NULL;
1818 orig_params = wifi->scan_params;
1820 /* Let's transfer driver_max_ssids params */
1821 for (i = 0; i < driver_max_ssids; i++) {
1822 struct scan_ssid *ssid;
1824 if (!wifi->scan_params->ssids)
1827 ssid = orig_params->ssids->data;
1828 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1829 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1833 scan_params->num_ssids = i;
1834 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1836 scan_params->freqs = g_memdup(orig_params->freqs,
1837 sizeof(uint16_t) * orig_params->num_freqs);
1838 if (!scan_params->freqs)
1841 scan_params->num_freqs = orig_params->num_freqs;
1846 orig_params->num_ssids -= scan_params->num_ssids;
1848 return scan_params->num_ssids;
1851 g_slist_free_full(scan_params->ssids, g_free);
1852 g_supplicant_free_scan_params(wifi->scan_params);
1853 wifi->scan_params = NULL;
1858 static int throw_wifi_scan(struct connman_device *device,
1859 GSupplicantInterfaceCallback callback)
1861 struct wifi_data *wifi = connman_device_get_data(device);
1867 DBG("device %p %p", device, wifi->interface);
1869 if (wifi->tethering)
1871 #if defined TIZEN_EXT
1872 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1874 if (connman_device_get_scanning(device))
1878 connman_device_ref(device);
1880 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1883 connman_device_set_scanning(device,
1884 CONNMAN_SERVICE_TYPE_WIFI, true);
1886 connman_device_unref(device);
1891 static void hidden_free(struct hidden_params *hidden)
1896 if (hidden->scan_params)
1897 g_supplicant_free_scan_params(hidden->scan_params);
1898 g_free(hidden->identity);
1899 g_free(hidden->passphrase);
1900 g_free(hidden->security);
1904 #if defined TIZEN_EXT
1905 static void service_state_changed(struct connman_service *service,
1906 enum connman_service_state state);
1908 static int network_connect(struct connman_network *network);
1910 static struct connman_notifier notifier = {
1912 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1913 .service_state_changed = service_state_changed,
1916 static void service_state_changed(struct connman_service *service,
1917 enum connman_service_state state)
1919 enum connman_service_type type;
1921 type = connman_service_get_type(service);
1922 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1925 DBG("service %p state %d", service, state);
1928 case CONNMAN_SERVICE_STATE_READY:
1929 case CONNMAN_SERVICE_STATE_ONLINE:
1930 case CONNMAN_SERVICE_STATE_FAILURE:
1931 connman_notifier_unregister(¬ifier);
1932 is_wifi_notifier_registered = FALSE;
1934 __connman_device_request_scan(type);
1943 static void scan_callback(int result, GSupplicantInterface *interface,
1946 struct connman_device *device = user_data;
1947 struct wifi_data *wifi = connman_device_get_data(device);
1950 DBG("result %d wifi %p", result, wifi);
1953 if (wifi->hidden && !wifi->postpone_hidden) {
1954 connman_network_clear_hidden(wifi->hidden->user_data);
1955 hidden_free(wifi->hidden);
1956 wifi->hidden = NULL;
1959 if (wifi->scan_params) {
1960 g_supplicant_free_scan_params(wifi->scan_params);
1961 wifi->scan_params = NULL;
1966 connman_device_reset_scanning(device);
1968 /* User is connecting to a hidden AP, let's wait for finished event */
1969 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1970 GSupplicantScanParams *scan_params;
1973 wifi->postpone_hidden = false;
1974 scan_params = wifi->hidden->scan_params;
1975 wifi->hidden->scan_params = NULL;
1977 reset_autoscan(device);
1979 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1980 scan_callback, device);
1984 /* On error, let's recall scan_callback, which will cleanup */
1985 return scan_callback(ret, interface, user_data);
1988 #if defined TIZEN_EXT
1989 if (wifi && wifi->allow_full_scan) {
1991 DBG("Trigger Full Channel Scan");
1992 wifi->allow_full_scan = FALSE;
1994 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1995 scan_callback, device);
1999 /* On error, let's recall scan_callback, which will cleanup */
2000 return scan_callback(ret, interface, user_data);
2004 scanning = connman_device_get_scanning(device);
2006 connman_device_set_scanning(device,
2007 CONNMAN_SERVICE_TYPE_WIFI, false);
2009 if (result != -ENOLINK)
2010 #if defined TIZEN_EXT
2013 start_autoscan(device);
2016 * If we are here then we were scanning; however, if we are
2017 * also mid-flight disabling the interface, then wifi_disable
2018 * has already cleared the device scanning state and
2019 * unreferenced the device, obviating the need to do it here.
2023 connman_device_unref(device);
2025 #if defined TIZEN_EXT
2026 if (wifi && wifi->scan_pending_network && result != -EIO) {
2027 network_connect(wifi->scan_pending_network);
2028 wifi->scan_pending_network = NULL;
2029 connman_network_set_connecting(wifi->network);
2032 if (is_wifi_notifier_registered != true &&
2033 wifi_first_scan == true && found_with_first_scan == true) {
2034 wifi_first_scan = false;
2035 found_with_first_scan = false;
2037 connman_notifier_register(¬ifier);
2038 is_wifi_notifier_registered = true;
2043 static void scan_callback_hidden(int result,
2044 GSupplicantInterface *interface, void *user_data)
2046 struct connman_device *device = user_data;
2047 struct wifi_data *wifi = connman_device_get_data(device);
2048 GSupplicantScanParams *scan_params;
2051 DBG("result %d wifi %p", result, wifi);
2056 /* User is trying to connect to a hidden AP */
2057 if (wifi->hidden && wifi->postpone_hidden)
2060 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2064 if (get_hidden_connections_params(wifi, scan_params) > 0) {
2065 ret = g_supplicant_interface_scan(wifi->interface,
2067 scan_callback_hidden,
2073 g_supplicant_free_scan_params(scan_params);
2076 scan_callback(result, interface, user_data);
2079 static gboolean autoscan_timeout(gpointer data)
2081 struct connman_device *device = data;
2082 struct wifi_data *wifi = connman_device_get_data(device);
2083 struct autoscan_params *autoscan;
2089 autoscan = wifi->autoscan;
2091 if (autoscan->interval <= 0) {
2092 interval = autoscan->base;
2095 interval = autoscan->interval * autoscan->base;
2097 #if defined TIZEN_EXT
2098 if (autoscan->interval >= autoscan->limit)
2100 if (interval > autoscan->limit)
2102 interval = autoscan->limit;
2104 throw_wifi_scan(wifi->device, scan_callback_hidden);
2107 DBG("interval %d", interval);
2109 autoscan->interval = interval;
2111 autoscan->timeout = g_timeout_add_seconds(interval,
2112 autoscan_timeout, device);
2117 static void start_autoscan(struct connman_device *device)
2119 struct wifi_data *wifi = connman_device_get_data(device);
2120 struct autoscan_params *autoscan;
2127 if (wifi->p2p_device)
2130 if (wifi->connected)
2133 autoscan = wifi->autoscan;
2137 if (autoscan->timeout > 0 || autoscan->interval > 0)
2140 connman_device_ref(device);
2142 autoscan_timeout(device);
2145 static struct autoscan_params *parse_autoscan_params(const char *params)
2147 struct autoscan_params *autoscan;
2152 DBG("Emulating autoscan");
2154 list_params = g_strsplit(params, ":", 0);
2155 if (list_params == 0)
2158 if (g_strv_length(list_params) < 3) {
2159 g_strfreev(list_params);
2163 base = atoi(list_params[1]);
2164 limit = atoi(list_params[2]);
2166 g_strfreev(list_params);
2168 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
2170 DBG("Could not allocate memory for autoscan");
2174 DBG("base %d - limit %d", base, limit);
2175 autoscan->base = base;
2176 autoscan->limit = limit;
2181 static void setup_autoscan(struct wifi_data *wifi)
2183 if (!wifi->autoscan)
2184 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
2186 start_autoscan(wifi->device);
2189 static void finalize_interface_creation(struct wifi_data *wifi)
2191 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
2193 if (!wifi->device) {
2194 connman_error("WiFi device not set");
2198 connman_device_set_powered(wifi->device, true);
2200 if (!connman_setting_get_bool("BackgroundScanning"))
2203 if (wifi->p2p_device)
2206 setup_autoscan(wifi);
2209 static void interface_create_callback(int result,
2210 GSupplicantInterface *interface,
2213 struct wifi_data *wifi = user_data;
2215 DBG("result %d ifname %s, wifi %p", result,
2216 g_supplicant_interface_get_ifname(interface),
2219 if (result < 0 || !wifi)
2222 wifi->interface = interface;
2223 g_supplicant_interface_set_data(interface, wifi);
2225 if (g_supplicant_interface_get_ready(interface)) {
2226 wifi->interface_ready = true;
2227 finalize_interface_creation(wifi);
2231 static int wifi_enable(struct connman_device *device)
2233 struct wifi_data *wifi = connman_device_get_data(device);
2236 const char *driver = connman_option_get_string("wifi");
2239 DBG("device %p %p", device, wifi);
2241 index = connman_device_get_index(device);
2242 if (!wifi || index < 0)
2245 if (is_p2p_connecting())
2246 return -EINPROGRESS;
2248 interface = connman_inet_ifname(index);
2249 ret = g_supplicant_interface_create(interface, driver, NULL,
2250 interface_create_callback,
2257 return -EINPROGRESS;
2260 static int wifi_disable(struct connman_device *device)
2262 struct wifi_data *wifi = connman_device_get_data(device);
2265 DBG("device %p wifi %p", device, wifi);
2270 wifi->connected = false;
2271 wifi->disconnecting = false;
2273 if (wifi->pending_network)
2274 wifi->pending_network = NULL;
2276 stop_autoscan(device);
2278 if (wifi->p2p_find_timeout) {
2279 g_source_remove(wifi->p2p_find_timeout);
2280 wifi->p2p_find_timeout = 0;
2281 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2282 connman_device_unref(wifi->device);
2285 /* In case of a user scan, device is still referenced */
2286 if (connman_device_get_scanning(device)) {
2287 connman_device_set_scanning(device,
2288 CONNMAN_SERVICE_TYPE_WIFI, false);
2289 connman_device_unref(wifi->device);
2292 remove_networks(device, wifi);
2295 #if defined TIZEN_EXT
2296 wifi->scan_pending_network = NULL;
2298 if (is_wifi_notifier_registered == true) {
2299 connman_notifier_unregister(¬ifier);
2300 is_wifi_notifier_registered = false;
2304 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
2308 return -EINPROGRESS;
2311 struct last_connected {
2317 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
2319 GTimeVal *aval = (GTimeVal *)a;
2320 GTimeVal *bval = (GTimeVal *)b;
2322 /* Note that the sort order is descending */
2323 if (aval->tv_sec < bval->tv_sec)
2326 if (aval->tv_sec > bval->tv_sec)
2332 static void free_entry(gpointer data)
2334 struct last_connected *entry = data;
2336 g_free(entry->ssid);
2340 static int get_latest_connections(int max_ssids,
2341 GSupplicantScanParams *scan_data)
2343 GSequenceIter *iter;
2344 GSequence *latest_list;
2345 struct last_connected *entry;
2354 latest_list = g_sequence_new(free_entry);
2358 services = connman_storage_get_services();
2359 for (i = 0; services && services[i]; i++) {
2360 if (strncmp(services[i], "wifi_", 5) != 0)
2363 keyfile = connman_storage_load_service(services[i]);
2367 str = g_key_file_get_string(keyfile,
2368 services[i], "Favorite", NULL);
2369 if (!str || g_strcmp0(str, "true")) {
2371 g_key_file_free(keyfile);
2376 str = g_key_file_get_string(keyfile,
2377 services[i], "AutoConnect", NULL);
2378 if (!str || g_strcmp0(str, "true")) {
2380 g_key_file_free(keyfile);
2385 str = g_key_file_get_string(keyfile,
2386 services[i], "Modified", NULL);
2388 g_key_file_free(keyfile);
2391 g_time_val_from_iso8601(str, &modified);
2394 ssid = g_key_file_get_string(keyfile,
2395 services[i], "SSID", NULL);
2397 freq = g_key_file_get_integer(keyfile, services[i],
2400 entry = g_try_new(struct last_connected, 1);
2402 g_sequence_free(latest_list);
2403 g_key_file_free(keyfile);
2409 entry->modified = modified;
2412 g_sequence_insert_sorted(latest_list, entry,
2418 g_key_file_free(keyfile);
2421 g_strfreev(services);
2423 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
2425 iter = g_sequence_get_begin_iter(latest_list);
2427 for (i = 0; i < num_ssids; i++) {
2428 entry = g_sequence_get(iter);
2430 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
2431 entry->modified.tv_sec);
2433 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
2434 max_ssids, entry->ssid);
2436 iter = g_sequence_iter_next(iter);
2439 g_sequence_free(latest_list);
2443 static int wifi_scan_simple(struct connman_device *device)
2445 reset_autoscan(device);
2447 return throw_wifi_scan(device, scan_callback_hidden);
2450 static gboolean p2p_find_stop(gpointer data)
2452 struct connman_device *device = data;
2453 struct wifi_data *wifi = connman_device_get_data(device);
2458 wifi->p2p_find_timeout = 0;
2460 g_supplicant_interface_p2p_stop_find(wifi->interface);
2463 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
2465 connman_device_unref(device);
2466 reset_autoscan(device);
2471 static void p2p_find_callback(int result, GSupplicantInterface *interface,
2474 struct connman_device *device = user_data;
2475 struct wifi_data *wifi = connman_device_get_data(device);
2477 DBG("result %d wifi %p", result, wifi);
2482 if (wifi->p2p_find_timeout) {
2483 g_source_remove(wifi->p2p_find_timeout);
2484 wifi->p2p_find_timeout = 0;
2490 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
2491 p2p_find_stop, device);
2492 if (!wifi->p2p_find_timeout)
2497 p2p_find_stop(device);
2500 static int p2p_find(struct connman_device *device)
2502 struct wifi_data *wifi;
2507 if (!p2p_technology)
2510 wifi = connman_device_get_data(device);
2512 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2515 reset_autoscan(device);
2516 connman_device_ref(device);
2518 ret = g_supplicant_interface_p2p_find(wifi->interface,
2519 p2p_find_callback, device);
2521 connman_device_unref(device);
2522 start_autoscan(device);
2524 connman_device_set_scanning(device,
2525 CONNMAN_SERVICE_TYPE_P2P, true);
2531 #if defined TIZEN_EXT
2532 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2535 struct connman_device *device = user_data;
2536 struct wifi_data *wifi = connman_device_get_data(device);
2539 DBG("result %d wifi %p", result, wifi);
2541 if (wifi && wifi->scan_params) {
2542 g_supplicant_free_scan_params(wifi->scan_params);
2543 wifi->scan_params = NULL;
2546 scanning = connman_device_get_scanning(device);
2548 connman_device_set_scanning(device,
2549 CONNMAN_SERVICE_TYPE_WIFI, false);
2550 connman_device_unref(device);
2554 static int wifi_specific_scan(enum connman_service_type type,
2555 struct connman_device *device, int scan_type,
2556 GSList *specific_scan_list, void *user_data)
2558 GSList *list = NULL;
2560 struct wifi_data *wifi = connman_device_get_data(device);
2561 GSupplicantScanParams *scan_params = NULL;
2562 struct scan_ssid *scan_ssid = NULL;
2571 if (wifi->p2p_device)
2574 if (type == CONNMAN_SERVICE_TYPE_P2P)
2575 return p2p_find(device);
2577 if (wifi->tethering)
2580 scanning = connman_device_get_scanning(device);
2584 DBG("scan_type: %d", scan_type);
2585 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2586 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2588 DBG("Failed to allocate memory.");
2592 for (list = specific_scan_list; list; list = list->next) {
2593 ssid = (char *)list->data;
2594 int ssid_len = strlen(ssid);
2596 scan_ssid = g_try_new0(struct scan_ssid, 1);
2598 DBG("Failed to allocate memory.");
2599 g_supplicant_free_scan_params(scan_params);
2603 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2604 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2605 scan_ssid->ssid_len = ssid_len;
2606 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2609 scan_params->num_ssids = count;
2611 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2613 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2615 DBG("Failed to allocate memory.");
2619 guint num_freqs = g_slist_length(specific_scan_list);
2620 DBG("num_freqs: %d", num_freqs);
2622 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2623 if (!scan_params->freqs) {
2624 DBG("Failed to allocate memory.");
2625 g_free(scan_params);
2630 for (list = specific_scan_list; list; list = list->next) {
2631 freq = (int)list->data;
2633 scan_params->freqs[count] = freq;
2634 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2637 scan_params->num_freqs = count;
2639 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2640 int freq_count, ap_count;
2641 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2643 DBG("Failed to allocate memory.");
2647 guint size = g_slist_length(specific_scan_list);
2649 scan_params->freqs = g_try_new0(uint16_t, size/2);
2650 if (!scan_params->freqs) {
2651 DBG("Failed to allocate memory.");
2652 g_free(scan_params);
2656 ap_count = freq_count = 0;
2657 for (list = specific_scan_list; list; list = list->next) {
2658 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2659 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2660 int ssid_len = strlen(ssid);
2662 scan_ssid = g_try_new0(struct scan_ssid, 1);
2664 DBG("Failed to allocate memory.");
2665 g_supplicant_free_scan_params(scan_params);
2669 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2670 /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
2671 scan_ssid->ssid_len = ssid_len;
2672 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2676 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2677 scan_params->freqs[freq_count] = freq;
2678 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2682 scan_params->num_ssids = ap_count;
2683 scan_params->num_freqs = freq_count;
2685 DBG("Invalid scan");
2689 reset_autoscan(device);
2690 connman_device_ref(device);
2692 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2693 specific_scan_callback, device);
2696 connman_device_set_scanning(device,
2697 CONNMAN_SERVICE_TYPE_WIFI, true);
2699 g_supplicant_free_scan_params(scan_params);
2700 connman_device_unref(device);
2707 #if defined TIZEN_EXT_WIFI_MESH
2708 static void mesh_scan_callback(int result, GSupplicantInterface *interface,
2711 struct connman_device *device = user_data;
2712 struct wifi_data *wifi = connman_device_get_data(device);
2715 DBG("result %d wifi %p", result, wifi);
2717 scanning = connman_device_get_scanning(device);
2719 connman_device_set_scanning(device,
2720 CONNMAN_SERVICE_TYPE_MESH, false);
2723 connman_device_unref(device);
2726 static int mesh_scan(struct connman_device *device)
2728 struct wifi_data *wifi;
2729 struct wifi_mesh_info *mesh_info;
2734 wifi = connman_device_get_data(device);
2736 if (!wifi->mesh_interface)
2739 mesh_info = wifi->mesh_info;
2740 reset_autoscan(device);
2741 connman_device_ref(device);
2743 ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
2744 mesh_scan_callback, device);
2746 connman_device_unref(device);
2748 connman_device_set_scanning(device,
2749 CONNMAN_SERVICE_TYPE_MESH, true);
2754 static void abort_scan_callback(int result, GSupplicantInterface *interface,
2757 struct connman_device *device = user_data;
2758 struct wifi_data *wifi = connman_device_get_data(device);
2760 DBG("result %d wifi %p", result, wifi);
2762 __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
2765 static int mesh_abort_scan(enum connman_service_type type,
2766 struct connman_device *device)
2768 struct wifi_data *wifi = connman_device_get_data(device);
2769 struct wifi_mesh_info *mesh_info;
2773 if (!wifi || !wifi->mesh_interface)
2776 if (type != CONNMAN_SERVICE_TYPE_MESH)
2779 mesh_info = wifi->mesh_info;
2781 scanning = connman_device_get_scanning(device);
2785 ret = g_supplicant_interface_abort_scan(mesh_info->interface,
2786 abort_scan_callback, device);
2791 static int mesh_specific_scan(enum connman_service_type type,
2792 struct connman_device *device, const char *ssid,
2793 unsigned int freq, void *user_data)
2795 struct wifi_data *wifi = connman_device_get_data(device);
2796 GSupplicantScanParams *scan_params = NULL;
2797 struct wifi_mesh_info *mesh_info;
2798 struct scan_ssid *scan_ssid;
2802 if (!wifi || !wifi->mesh_interface)
2805 if (type != CONNMAN_SERVICE_TYPE_MESH)
2808 if (wifi->p2p_device)
2811 mesh_info = wifi->mesh_info;
2813 scanning = connman_device_get_scanning(device);
2817 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2821 scan_ssid = g_try_new(struct scan_ssid, 1);
2823 g_free(scan_params);
2827 scan_ssid->ssid_len = strlen(ssid);
2828 memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
2829 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2830 scan_params->num_ssids = 1;
2832 scan_params->freqs = g_try_new(uint16_t, 1);
2833 if (!scan_params->freqs) {
2834 g_slist_free_full(scan_params->ssids, g_free);
2835 g_free(scan_params);
2839 scan_params->freqs[0] = freq;
2840 scan_params->num_freqs = 1;
2842 reset_autoscan(device);
2843 connman_device_ref(device);
2845 ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
2846 mesh_scan_callback, device);
2849 connman_device_set_scanning(device,
2850 CONNMAN_SERVICE_TYPE_MESH, true);
2852 g_supplicant_free_scan_params(scan_params);
2853 connman_device_unref(device);
2861 * Note that the hidden scan is only used when connecting to this specific
2862 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2864 static int wifi_scan(enum connman_service_type type,
2865 struct connman_device *device,
2866 const char *ssid, unsigned int ssid_len,
2867 const char *identity, const char* passphrase,
2868 const char *security, void *user_data)
2870 struct wifi_data *wifi = connman_device_get_data(device);
2871 GSupplicantScanParams *scan_params = NULL;
2872 struct scan_ssid *scan_ssid;
2873 struct hidden_params *hidden;
2875 int driver_max_ssids = 0;
2882 if (wifi->p2p_device)
2885 if (wifi->tethering)
2888 if (type == CONNMAN_SERVICE_TYPE_P2P)
2889 return p2p_find(device);
2891 #if defined TIZEN_EXT_WIFI_MESH
2892 if (type == CONNMAN_SERVICE_TYPE_MESH)
2893 return mesh_scan(device);
2896 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2898 scanning = connman_device_get_scanning(device);
2900 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2904 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2906 DBG("max ssids %d", driver_max_ssids);
2907 if (driver_max_ssids == 0)
2908 return wifi_scan_simple(device);
2912 if (scanning && wifi->hidden && wifi->postpone_hidden)
2918 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2923 scan_ssid = g_try_new(struct scan_ssid, 1);
2925 g_free(scan_params);
2929 memcpy(scan_ssid->ssid, ssid, ssid_len);
2930 scan_ssid->ssid_len = ssid_len;
2931 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2933 scan_params->num_ssids = 1;
2935 hidden = g_try_new0(struct hidden_params, 1);
2937 g_supplicant_free_scan_params(scan_params);
2942 hidden_free(wifi->hidden);
2943 wifi->hidden = NULL;
2946 memcpy(hidden->ssid, ssid, ssid_len);
2947 hidden->ssid_len = ssid_len;
2948 hidden->identity = g_strdup(identity);
2949 hidden->passphrase = g_strdup(passphrase);
2950 hidden->security = g_strdup(security);
2951 hidden->user_data = user_data;
2952 wifi->hidden = hidden;
2955 /* Let's keep this active scan for later,
2956 * when current scan will be over. */
2957 wifi->postpone_hidden = TRUE;
2958 hidden->scan_params = scan_params;
2962 } else if (wifi->connected) {
2963 g_supplicant_free_scan_params(scan_params);
2964 return wifi_scan_simple(device);
2966 ret = get_latest_connections(driver_max_ssids, scan_params);
2968 g_supplicant_free_scan_params(scan_params);
2969 return wifi_scan_simple(device);
2973 connman_device_ref(device);
2975 reset_autoscan(device);
2977 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2978 scan_callback, device);
2981 connman_device_set_scanning(device,
2982 CONNMAN_SERVICE_TYPE_WIFI, true);
2983 #if defined TIZEN_EXT
2984 /*To allow the Full Scan after ssid based scan, set the flag here
2985 It is required because Tizen does not use the ConnMan specific
2986 backgroung Scan feature.Tizen has added the BG Scan feature in
2987 net-config. To sync with up ConnMan, we need to issue the Full Scan
2988 after SSID specific scan.*/
2989 wifi->allow_full_scan = TRUE;
2992 g_supplicant_free_scan_params(scan_params);
2993 connman_device_unref(device);
2996 hidden_free(wifi->hidden);
2997 wifi->hidden = NULL;
3004 static void wifi_regdom_callback(int result,
3008 struct connman_device *device = user_data;
3010 connman_device_regdom_notify(device, result, alpha2);
3012 connman_device_unref(device);
3015 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
3017 struct wifi_data *wifi = connman_device_get_data(device);
3023 connman_device_ref(device);
3025 ret = g_supplicant_interface_set_country(wifi->interface,
3026 wifi_regdom_callback,
3029 connman_device_unref(device);
3034 static struct connman_device_driver wifi_ng_driver = {
3036 .type = CONNMAN_DEVICE_TYPE_WIFI,
3037 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
3038 .probe = wifi_probe,
3039 .remove = wifi_remove,
3040 .enable = wifi_enable,
3041 .disable = wifi_disable,
3043 .set_regdom = wifi_set_regdom,
3044 #if defined TIZEN_EXT
3045 .specific_scan = wifi_specific_scan,
3047 #if defined TIZEN_EXT_WIFI_MESH
3048 .abort_scan = mesh_abort_scan,
3049 .mesh_specific_scan = mesh_specific_scan,
3053 static void system_ready(void)
3057 if (connman_device_driver_register(&wifi_ng_driver) < 0)
3058 connman_error("Failed to register WiFi driver");
3061 static void system_killed(void)
3065 connman_device_driver_unregister(&wifi_ng_driver);
3068 static int network_probe(struct connman_network *network)
3070 DBG("network %p", network);
3075 static void network_remove(struct connman_network *network)
3077 struct connman_device *device = connman_network_get_device(network);
3078 struct wifi_data *wifi;
3080 DBG("network %p", network);
3082 wifi = connman_device_get_data(device);
3086 if (wifi->network != network)
3089 wifi->network = NULL;
3091 #if defined TIZEN_EXT
3092 wifi->disconnecting = false;
3094 if (wifi->pending_network == network)
3095 wifi->pending_network = NULL;
3097 if (wifi->scan_pending_network == network)
3098 wifi->scan_pending_network = NULL;
3102 static void connect_callback(int result, GSupplicantInterface *interface,
3105 #if defined TIZEN_EXT
3107 struct wifi_data *wifi;
3109 struct connman_network *network = user_data;
3111 DBG("network %p result %d", network, result);
3113 #if defined TIZEN_EXT
3114 set_connman_bssid(RESET_BSSID, NULL);
3116 for (list = iface_list; list; list = list->next) {
3119 if (wifi && wifi->network == network)
3123 /* wifi_data may be invalid because wifi is already disabled */
3128 if (result == -ENOKEY) {
3129 connman_network_set_error(network,
3130 CONNMAN_NETWORK_ERROR_INVALID_KEY);
3131 } else if (result < 0) {
3132 connman_network_set_error(network,
3133 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
3136 connman_network_unref(network);
3139 static GSupplicantSecurity network_security(const char *security)
3141 if (g_str_equal(security, "none"))
3142 return G_SUPPLICANT_SECURITY_NONE;
3143 else if (g_str_equal(security, "wep"))
3144 return G_SUPPLICANT_SECURITY_WEP;
3145 else if (g_str_equal(security, "psk"))
3146 return G_SUPPLICANT_SECURITY_PSK;
3147 else if (g_str_equal(security, "wpa"))
3148 return G_SUPPLICANT_SECURITY_PSK;
3149 else if (g_str_equal(security, "rsn"))
3150 return G_SUPPLICANT_SECURITY_PSK;
3151 else if (g_str_equal(security, "ieee8021x"))
3152 return G_SUPPLICANT_SECURITY_IEEE8021X;
3153 #if defined TIZEN_EXT
3154 else if (g_str_equal(security, "ft_psk") == TRUE)
3155 return G_SUPPLICANT_SECURITY_FT_PSK;
3156 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
3157 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
3160 return G_SUPPLICANT_SECURITY_UNKNOWN;
3163 #if defined TIZEN_EXT
3164 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
3166 if (security == NULL)
3167 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3169 if (g_str_equal(security, "FT") == TRUE)
3170 return G_SUPPLICANT_EAP_KEYMGMT_FT;
3171 else if (g_str_equal(security, "CCKM") == TRUE)
3172 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
3174 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
3178 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
3180 const char *security;
3181 #if defined TIZEN_EXT
3182 const void *ssid_data;
3185 memset(ssid, 0, sizeof(*ssid));
3186 ssid->mode = G_SUPPLICANT_MODE_INFRA;
3187 #if defined TIZEN_EXT
3188 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
3190 ssid->ssid = g_try_malloc0(ssid->ssid_len);
3195 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
3197 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
3200 ssid->scan_ssid = 1;
3201 security = connman_network_get_string(network, "WiFi.Security");
3202 ssid->security = network_security(security);
3203 ssid->passphrase = connman_network_get_string(network,
3205 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
3208 * If our private key password is unset,
3209 * we use the supplied passphrase. That is needed
3210 * for PEAP where 2 passphrases (identity and client
3211 * cert may have to be provided.
3213 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
3214 connman_network_set_string(network,
3215 "WiFi.PrivateKeyPassphrase",
3217 /* We must have an identity for both PEAP and TLS */
3218 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
3220 /* Use agent provided identity as a fallback */
3221 if (!ssid->identity || strlen(ssid->identity) == 0)
3222 ssid->identity = connman_network_get_string(network,
3223 "WiFi.AgentIdentity");
3225 ssid->anonymous_identity = connman_network_get_string(network,
3226 "WiFi.AnonymousIdentity");
3227 ssid->ca_cert_path = connman_network_get_string(network,
3229 ssid->subject_match = connman_network_get_string(network,
3230 "WiFi.SubjectMatch");
3231 ssid->altsubject_match = connman_network_get_string(network,
3232 "WiFi.AltSubjectMatch");
3233 ssid->domain_suffix_match = connman_network_get_string(network,
3234 "WiFi.DomainSuffixMatch");
3235 ssid->domain_match = connman_network_get_string(network,
3236 "WiFi.DomainMatch");
3237 ssid->client_cert_path = connman_network_get_string(network,
3238 "WiFi.ClientCertFile");
3239 ssid->private_key_path = connman_network_get_string(network,
3240 "WiFi.PrivateKeyFile");
3241 ssid->private_key_passphrase = connman_network_get_string(network,
3242 "WiFi.PrivateKeyPassphrase");
3243 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
3245 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
3246 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
3248 #if defined TIZEN_EXT
3249 ssid->bssid = connman_network_get_bssid(network);
3251 ssid->eap_keymgmt = network_eap_keymgmt(
3252 connman_network_get_string(network, "WiFi.KeymgmtType"));
3253 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
3255 if(g_strcmp0(ssid->eap, "fast") == 0)
3256 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
3258 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
3259 ssid->bssid_for_connect_len = 6;
3260 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
3261 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
3262 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
3263 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
3264 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
3266 ssid->freq = connman_network_get_frequency(network);
3270 if (connman_setting_get_bool("BackgroundScanning"))
3271 ssid->bgscan = BGSCAN_DEFAULT;
3274 static int network_connect(struct connman_network *network)
3276 struct connman_device *device = connman_network_get_device(network);
3277 struct wifi_data *wifi;
3278 GSupplicantInterface *interface;
3279 GSupplicantSSID *ssid;
3281 DBG("network %p", network);
3286 wifi = connman_device_get_data(device);
3290 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
3294 interface = wifi->interface;
3296 ssid_init(ssid, network);
3298 if (wifi->disconnecting) {
3299 wifi->pending_network = network;
3300 #if defined TIZEN_EXT
3305 wifi->network = connman_network_ref(network);
3307 #if defined TIZEN_EXT
3308 wifi->scan_pending_network = NULL;
3311 return g_supplicant_interface_connect(interface, ssid,
3312 connect_callback, network);
3315 return -EINPROGRESS;
3318 static void disconnect_callback(int result, GSupplicantInterface *interface,
3321 #if defined TIZEN_EXT
3323 struct wifi_data *wifi;
3324 struct connman_network *network = user_data;
3326 DBG("network %p result %d", network, result);
3328 for (list = iface_list; list; list = list->next) {
3331 if (wifi->network == NULL && wifi->disconnecting == true)
3332 wifi->disconnecting = false;
3334 if (wifi->network == network)
3338 /* wifi_data may be invalid because wifi is already disabled */
3343 struct wifi_data *wifi = user_data;
3346 DBG("result %d supplicant interface %p wifi %p",
3347 result, interface, wifi);
3349 if (result == -ECONNABORTED) {
3350 DBG("wifi interface no longer available");
3354 if (wifi->network) {
3355 connman_network_set_connected(wifi->network, false);
3356 wifi->network = NULL;
3359 wifi->disconnecting = false;
3360 wifi->connected = false;
3362 if (wifi->pending_network) {
3363 network_connect(wifi->pending_network);
3364 wifi->pending_network = NULL;
3367 start_autoscan(wifi->device);
3370 static int network_disconnect(struct connman_network *network)
3372 struct connman_device *device = connman_network_get_device(network);
3373 struct wifi_data *wifi;
3375 #if defined TIZEN_EXT
3376 struct connman_service *service;
3379 DBG("network %p", network);
3381 wifi = connman_device_get_data(device);
3382 if (!wifi || !wifi->interface)
3385 #if defined TIZEN_EXT
3386 if (connman_network_get_associating(network) == true) {
3387 connman_network_clear_associating(network);
3388 connman_network_set_bool(network, "WiFi.UseWPS", false);
3390 service = connman_service_lookup_from_network(network);
3392 if (service != NULL &&
3393 (__connman_service_is_connected_state(service,
3394 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
3395 __connman_service_is_connected_state(service,
3396 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
3397 (connman_service_get_favorite(service) == false))
3398 __connman_service_set_passphrase(service, NULL);
3401 if (wifi->pending_network == network)
3402 wifi->pending_network = NULL;
3404 if (wifi->scan_pending_network == network)
3405 wifi->scan_pending_network = NULL;
3408 connman_network_set_associating(network, false);
3410 if (wifi->disconnecting)
3413 wifi->disconnecting = true;
3415 #if defined TIZEN_EXT
3416 err = g_supplicant_interface_disconnect(wifi->interface,
3417 disconnect_callback, network);
3419 err = g_supplicant_interface_disconnect(wifi->interface,
3420 disconnect_callback, wifi);
3424 wifi->disconnecting = false;
3429 static struct connman_network_driver network_driver = {
3431 .type = CONNMAN_NETWORK_TYPE_WIFI,
3432 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
3433 .probe = network_probe,
3434 .remove = network_remove,
3435 .connect = network_connect,
3436 .disconnect = network_disconnect,
3439 static void interface_added(GSupplicantInterface *interface)
3441 const char *ifname = g_supplicant_interface_get_ifname(interface);
3442 const char *driver = g_supplicant_interface_get_driver(interface);
3443 struct wifi_data *wifi;
3445 wifi = g_supplicant_interface_get_data(interface);
3447 wifi = get_pending_wifi_data(ifname);
3451 wifi->interface = interface;
3452 g_supplicant_interface_set_data(interface, wifi);
3453 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
3454 wifi->p2p_device = true;
3457 DBG("ifname %s driver %s wifi %p tethering %d",
3458 ifname, driver, wifi, wifi->tethering);
3460 if (!wifi->device) {
3461 connman_error("WiFi device not set");
3465 connman_device_set_powered(wifi->device, true);
3468 static bool is_idle(struct wifi_data *wifi)
3470 DBG("state %d", wifi->state);
3472 switch (wifi->state) {
3473 case G_SUPPLICANT_STATE_UNKNOWN:
3474 case G_SUPPLICANT_STATE_DISABLED:
3475 case G_SUPPLICANT_STATE_DISCONNECTED:
3476 case G_SUPPLICANT_STATE_INACTIVE:
3477 case G_SUPPLICANT_STATE_SCANNING:
3480 case G_SUPPLICANT_STATE_AUTHENTICATING:
3481 case G_SUPPLICANT_STATE_ASSOCIATING:
3482 case G_SUPPLICANT_STATE_ASSOCIATED:
3483 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3484 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3485 case G_SUPPLICANT_STATE_COMPLETED:
3492 static bool is_idle_wps(GSupplicantInterface *interface,
3493 struct wifi_data *wifi)
3495 /* First, let's check if WPS processing did not went wrong */
3496 if (g_supplicant_interface_get_wps_state(interface) ==
3497 G_SUPPLICANT_WPS_STATE_FAIL)
3500 /* Unlike normal connection, being associated while processing wps
3501 * actually means that we are idling. */
3502 switch (wifi->state) {
3503 case G_SUPPLICANT_STATE_UNKNOWN:
3504 case G_SUPPLICANT_STATE_DISABLED:
3505 case G_SUPPLICANT_STATE_DISCONNECTED:
3506 case G_SUPPLICANT_STATE_INACTIVE:
3507 case G_SUPPLICANT_STATE_SCANNING:
3508 case G_SUPPLICANT_STATE_ASSOCIATED:
3510 case G_SUPPLICANT_STATE_AUTHENTICATING:
3511 case G_SUPPLICANT_STATE_ASSOCIATING:
3512 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3513 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3514 case G_SUPPLICANT_STATE_COMPLETED:
3521 static bool handle_wps_completion(GSupplicantInterface *interface,
3522 struct connman_network *network,
3523 struct connman_device *device,
3524 struct wifi_data *wifi)
3528 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3530 const unsigned char *ssid, *wps_ssid;
3531 unsigned int ssid_len, wps_ssid_len;
3532 const char *wps_key;
3534 /* Checking if we got associated with requested
3536 ssid = connman_network_get_blob(network, "WiFi.SSID",
3539 wps_ssid = g_supplicant_interface_get_wps_ssid(
3540 interface, &wps_ssid_len);
3542 if (!wps_ssid || wps_ssid_len != ssid_len ||
3543 memcmp(ssid, wps_ssid, ssid_len) != 0) {
3544 connman_network_set_associating(network, false);
3545 #if defined TIZEN_EXT
3546 g_supplicant_interface_disconnect(wifi->interface,
3547 disconnect_callback, wifi->network);
3549 connman_network_set_bool(network, "WiFi.UseWPS", false);
3550 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3552 g_supplicant_interface_disconnect(wifi->interface,
3553 disconnect_callback, wifi);
3558 wps_key = g_supplicant_interface_get_wps_key(interface);
3559 #if defined TIZEN_EXT
3560 /* Check the passphrase and encrypt it
3563 gchar *passphrase = g_strdup(wps_key);
3565 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3567 if (check_passphrase_ext(network, passphrase) < 0) {
3568 DBG("[WPS] Invalid passphrase");
3573 ret = send_encryption_request(passphrase, network);
3578 DBG("[WPS] Encryption request succeeded");
3580 DBG("[WPS] Encryption request failed %d", ret);
3583 connman_network_set_string(network, "WiFi.Passphrase",
3586 connman_network_set_string(network, "WiFi.PinWPS", NULL);
3593 static bool handle_assoc_status_code(GSupplicantInterface *interface,
3594 struct wifi_data *wifi)
3596 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
3597 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
3598 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
3599 wifi->load_shaping_retries ++;
3602 wifi->load_shaping_retries = 0;
3606 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
3607 struct connman_network *network,
3608 struct wifi_data *wifi)
3610 #if defined TIZEN_EXT
3611 const char *security;
3612 struct connman_service *service;
3614 if (wifi->connected)
3617 security = connman_network_get_string(network, "WiFi.Security");
3619 if (security && g_str_equal(security, "ieee8021x") == true &&
3620 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3622 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3627 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3630 struct connman_service *service;
3632 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
3635 if (wifi->connected)
3639 service = connman_service_lookup_from_network(network);
3645 if (connman_service_get_favorite(service)) {
3646 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
3651 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
3656 #if defined TIZEN_EXT
3657 static bool handle_wifi_assoc_retry(struct connman_network *network,
3658 struct wifi_data *wifi)
3660 const char *security;
3662 if (!wifi->network || wifi->connected || wifi->disconnecting ||
3663 connman_network_get_connecting(network) != true) {
3664 wifi->assoc_retry_count = 0;
3668 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
3669 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
3670 wifi->assoc_retry_count = 0;
3674 security = connman_network_get_string(network, "WiFi.Security");
3675 if (security && g_str_equal(security, "ieee8021x") == true &&
3676 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3677 wifi->assoc_retry_count = 0;
3681 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3682 wifi->assoc_retry_count = 0;
3684 /* Honestly it's not an invalid-key error,
3685 * however QA team recommends that the invalid-key error
3686 * might be better to display for user experience.
3688 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3697 static void interface_state(GSupplicantInterface *interface)
3699 struct connman_network *network;
3700 struct connman_device *device;
3701 struct wifi_data *wifi;
3702 GSupplicantState state = g_supplicant_interface_get_state(interface);
3706 wifi = g_supplicant_interface_get_data(interface);
3708 DBG("wifi %p interface state %d", wifi, state);
3713 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3714 if (wifi->tethering_param) {
3715 g_free(wifi->tethering_param->ssid);
3716 g_free(wifi->tethering_param);
3717 wifi->tethering_param = NULL;
3721 device = wifi->device;
3725 if (g_supplicant_interface_get_ready(interface) &&
3726 !wifi->interface_ready) {
3727 wifi->interface_ready = true;
3728 finalize_interface_creation(wifi);
3731 network = wifi->network;
3736 case G_SUPPLICANT_STATE_SCANNING:
3737 if (wifi->connected)
3738 connman_network_set_connected(network, false);
3742 case G_SUPPLICANT_STATE_AUTHENTICATING:
3743 case G_SUPPLICANT_STATE_ASSOCIATING:
3744 #if defined TIZEN_EXT
3745 reset_autoscan(device);
3747 stop_autoscan(device);
3750 if (!wifi->connected)
3751 connman_network_set_associating(network, true);
3755 case G_SUPPLICANT_STATE_COMPLETED:
3756 #if defined TIZEN_EXT
3757 /* though it should be already reset: */
3758 reset_autoscan(device);
3760 wifi->assoc_retry_count = 0;
3762 wifi->scan_pending_network = NULL;
3764 /* should be cleared scanning flag */
3765 bool scanning = connman_device_get_scanning(device);
3767 connman_device_set_scanning(device,
3768 CONNMAN_SERVICE_TYPE_WIFI, false);
3769 connman_device_unref(device);
3772 /* though it should be already stopped: */
3773 stop_autoscan(device);
3776 if (!handle_wps_completion(interface, network, device, wifi))
3779 connman_network_set_connected(network, true);
3781 wifi->disconnect_code = 0;
3782 wifi->assoc_code = 0;
3783 wifi->load_shaping_retries = 0;
3786 case G_SUPPLICANT_STATE_DISCONNECTED:
3788 * If we're in one of the idle modes, we have
3789 * not started association yet and thus setting
3790 * those ones to FALSE could cancel an association
3793 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3795 if (is_idle_wps(interface, wifi))
3801 if (handle_assoc_status_code(interface, wifi))
3804 /* If previous state was 4way-handshake, then
3805 * it's either: psk was incorrect and thus we retry
3806 * or if we reach the maximum retries we declare the
3808 if (handle_4way_handshake_failure(interface,
3812 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3813 switch (wifi->disconnect_code) {
3814 case 1: /* Unspecified reason */
3815 /* Let's assume it's because we got blocked */
3817 case 6: /* Class 2 frame received from nonauthenticated STA */
3818 connman_network_set_error(network,
3819 CONNMAN_NETWORK_ERROR_BLOCKED);
3826 #if defined TIZEN_EXT
3827 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3828 * Retry association until its retry count is expired */
3829 if (handle_wifi_assoc_retry(network, wifi) == true) {
3830 throw_wifi_scan(wifi->device, scan_callback);
3831 wifi->scan_pending_network = wifi->network;
3835 if(wifi->disconnect_code > 0){
3836 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3837 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3841 connman_network_set_connected(network, false);
3842 connman_network_set_associating(network, false);
3843 wifi->disconnecting = false;
3845 start_autoscan(device);
3849 case G_SUPPLICANT_STATE_INACTIVE:
3850 #if defined TIZEN_EXT
3851 if (handle_wps_completion(interface, network, device, wifi) == false)
3854 connman_network_set_associating(network, false);
3855 start_autoscan(device);
3859 case G_SUPPLICANT_STATE_UNKNOWN:
3860 case G_SUPPLICANT_STATE_DISABLED:
3861 case G_SUPPLICANT_STATE_ASSOCIATED:
3862 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3863 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3867 old_connected = wifi->connected;
3868 wifi->state = state;
3870 /* Saving wpa_s state policy:
3871 * If connected and if the state changes are roaming related:
3872 * --> We stay connected
3874 * --> We are connected
3876 * --> We are not connected
3879 case G_SUPPLICANT_STATE_AUTHENTICATING:
3880 case G_SUPPLICANT_STATE_ASSOCIATING:
3881 case G_SUPPLICANT_STATE_ASSOCIATED:
3882 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3883 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3884 if (wifi->connected)
3885 connman_warn("Probably roaming right now!"
3886 " Staying connected...");
3888 case G_SUPPLICANT_STATE_SCANNING:
3889 wifi->connected = false;
3892 start_autoscan(device);
3894 case G_SUPPLICANT_STATE_COMPLETED:
3895 wifi->connected = true;
3898 wifi->connected = false;
3905 static void interface_removed(GSupplicantInterface *interface)
3907 const char *ifname = g_supplicant_interface_get_ifname(interface);
3908 struct wifi_data *wifi;
3910 DBG("ifname %s", ifname);
3912 wifi = g_supplicant_interface_get_data(interface);
3914 #if defined TIZEN_EXT_WIFI_MESH
3915 if (wifi && wifi->mesh_interface) {
3916 DBG("Notify mesh interface remove");
3917 connman_mesh_notify_interface_remove(true);
3918 struct wifi_mesh_info *mesh_info = wifi->mesh_info;
3919 g_free(mesh_info->parent_ifname);
3920 g_free(mesh_info->ifname);
3921 g_free(mesh_info->identifier);
3923 wifi->mesh_interface = false;
3924 wifi->mesh_info = NULL;
3930 wifi->interface = NULL;
3932 if (wifi && wifi->tethering)
3935 if (!wifi || !wifi->device) {
3936 DBG("wifi interface already removed");
3940 connman_device_set_powered(wifi->device, false);
3942 check_p2p_technology();
3943 #if defined TIZEN_EXT_WIFI_MESH
3944 check_mesh_technology();
3948 static void set_device_type(const char *type, char dev_type[17])
3950 const char *oui = "0050F204";
3951 const char *category = "0001";
3952 const char *sub_category = "0000";
3954 if (!g_strcmp0(type, "handset")) {
3956 sub_category = "0005";
3957 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
3958 sub_category = "0001";
3959 else if (!g_strcmp0(type, "server"))
3960 sub_category = "0002";
3961 else if (!g_strcmp0(type, "laptop"))
3962 sub_category = "0005";
3963 else if (!g_strcmp0(type, "desktop"))
3964 sub_category = "0006";
3965 else if (!g_strcmp0(type, "tablet"))
3966 sub_category = "0009";
3967 else if (!g_strcmp0(type, "watch"))
3970 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
3973 static void p2p_support(GSupplicantInterface *interface)
3975 char dev_type[17] = {};
3976 const char *hostname;
3983 if (!g_supplicant_interface_has_p2p(interface))
3986 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3987 DBG("Could not register P2P technology driver");
3991 hostname = connman_utsname_get_hostname();
3993 hostname = "ConnMan";
3995 set_device_type(connman_machine_get_type(), dev_type);
3996 g_supplicant_interface_set_p2p_device_config(interface,
3997 hostname, dev_type);
3998 connman_peer_driver_register(&peer_driver);
4001 static void scan_started(GSupplicantInterface *interface)
4006 static void scan_finished(GSupplicantInterface *interface)
4008 #if defined TIZEN_EXT
4009 struct wifi_data *wifi;
4010 bool is_associating = false;
4011 static bool is_scanning = true;
4016 #if defined TIZEN_EXT
4017 wifi = g_supplicant_interface_get_data(interface);
4018 if (wifi && wifi->scan_pending_network) {
4019 network_connect(wifi->scan_pending_network);
4020 wifi->scan_pending_network = NULL;
4023 //service state - associating
4024 if(!wifi || !wifi->network)
4027 is_associating = connman_network_get_associating(wifi->network);
4028 if(is_associating && is_scanning){
4029 is_scanning = false;
4030 DBG("send scan for connecting");
4031 throw_wifi_scan(wifi->device, scan_callback);
4042 static void ap_create_fail(GSupplicantInterface *interface)
4044 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4047 if ((wifi->tethering) && (wifi->tethering_param)) {
4048 DBG("%s create AP fail \n",
4049 g_supplicant_interface_get_ifname(wifi->interface));
4051 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
4052 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4053 wifi->tethering = false;
4055 ret = tech_set_tethering(wifi->tethering_param->technology,
4056 wifi->tethering_param->ssid->ssid,
4057 wifi->tethering_param->ssid->passphrase,
4058 wifi->bridge, true);
4060 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
4061 connman_technology_tethering_notify(wifi_technology,false);
4064 g_free(wifi->tethering_param->ssid);
4065 g_free(wifi->tethering_param);
4066 wifi->tethering_param = NULL;
4072 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
4074 unsigned char strength;
4076 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
4078 #if !defined TIZEN_EXT
4085 #if defined TIZEN_EXT_WIFI_MESH
4086 static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
4088 GSupplicantInterface *interface;
4089 struct wifi_data *wifi;
4090 const char *name, *security;
4091 struct connman_mesh *connman_mesh;
4092 struct wifi_mesh_info *mesh_info;
4093 const unsigned char *bssid;
4094 const char *identifier;
4099 interface = g_supplicant_network_get_interface(supplicant_network);
4100 wifi = g_supplicant_interface_get_data(interface);
4101 if (!wifi || !wifi->mesh_interface) {
4102 DBG("Virtual Mesh interface not created");
4106 bssid = g_supplicant_network_get_bssid(supplicant_network);
4107 address = g_malloc0(19);
4108 snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
4109 bssid[2], bssid[3], bssid[4], bssid[5]);
4111 identifier = g_supplicant_network_get_identifier(supplicant_network);
4112 name = g_supplicant_network_get_name(supplicant_network);
4113 security = g_supplicant_network_get_security(supplicant_network);
4114 frequency = g_supplicant_network_get_frequency(supplicant_network);
4116 mesh_info = wifi->mesh_info;
4117 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4121 DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
4123 connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
4124 connman_mesh_set_name(connman_mesh, name);
4125 connman_mesh_set_security(connman_mesh, security);
4126 connman_mesh_set_frequency(connman_mesh, frequency);
4127 connman_mesh_set_address(connman_mesh, address);
4128 connman_mesh_set_index(connman_mesh, mesh_info->index);
4129 connman_mesh_set_strength(connman_mesh,
4130 calculate_strength(supplicant_network));
4131 connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
4133 ret = connman_mesh_register(connman_mesh);
4134 if (ret == -EALREADY)
4135 DBG("Mesh Peer is already registered");
4141 static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
4143 GSupplicantInterface *interface;
4144 struct wifi_data *wifi;
4145 struct connman_mesh *connman_mesh;
4146 struct wifi_mesh_info *mesh_info;
4147 const char *identifier;
4149 interface = g_supplicant_network_get_interface(supplicant_network);
4150 wifi = g_supplicant_interface_get_data(interface);
4151 if (!wifi || !wifi->mesh_interface) {
4152 DBG("Virtual Mesh interface not created");
4156 identifier = g_supplicant_network_get_identifier(supplicant_network);
4158 DBG("Failed to get Mesh Peer identifier");
4162 mesh_info = wifi->mesh_info;
4163 connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
4165 /* Do not unregister connected mesh peer */
4166 if (connman_mesh_peer_is_connected_state(connman_mesh)) {
4167 DBG("Mesh Peer %s is connected", identifier);
4170 DBG("Mesh Peer identifier %s removed", identifier);
4171 connman_mesh_unregister(connman_mesh);
4176 static void network_added(GSupplicantNetwork *supplicant_network)
4178 struct connman_network *network;
4179 GSupplicantInterface *interface;
4180 struct wifi_data *wifi;
4181 const char *name, *identifier, *security, *group, *mode;
4182 const unsigned char *ssid;
4183 unsigned int ssid_len;
4187 bool wps_advertizing;
4189 #if defined TIZEN_EXT
4190 GSList *vsie_list = NULL;
4191 const unsigned char *country_code;
4194 mode = g_supplicant_network_get_mode(supplicant_network);
4195 identifier = g_supplicant_network_get_identifier(supplicant_network);
4197 DBG("%s", identifier);
4199 if (!g_strcmp0(mode, "adhoc"))
4202 #if defined TIZEN_EXT_WIFI_MESH
4203 if (!g_strcmp0(mode, "mesh")) {
4204 mesh_peer_added(supplicant_network);
4209 interface = g_supplicant_network_get_interface(supplicant_network);
4210 wifi = g_supplicant_interface_get_data(interface);
4211 name = g_supplicant_network_get_name(supplicant_network);
4212 security = g_supplicant_network_get_security(supplicant_network);
4213 group = g_supplicant_network_get_identifier(supplicant_network);
4214 wps = g_supplicant_network_get_wps(supplicant_network);
4215 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
4216 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
4217 wps_advertizing = g_supplicant_network_is_wps_advertizing(
4218 supplicant_network);
4223 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
4225 network = connman_device_get_network(wifi->device, identifier);
4228 network = connman_network_create(identifier,
4229 CONNMAN_NETWORK_TYPE_WIFI);
4233 connman_network_set_index(network, wifi->index);
4235 if (connman_device_add_network(wifi->device, network) < 0) {
4236 connman_network_unref(network);
4240 wifi->networks = g_slist_prepend(wifi->networks, network);
4243 if (name && name[0] != '\0')
4244 connman_network_set_name(network, name);
4246 connman_network_set_blob(network, "WiFi.SSID",
4248 #if defined TIZEN_EXT
4249 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
4251 connman_network_set_vsie_list(network, vsie_list);
4253 DBG("vsie_list is NULL");
4254 country_code = g_supplicant_network_get_countrycode(supplicant_network);
4255 connman_network_set_countrycode(network, country_code);
4257 connman_network_set_string(network, "WiFi.Security", security);
4258 connman_network_set_strength(network,
4259 calculate_strength(supplicant_network));
4260 connman_network_set_bool(network, "WiFi.WPS", wps);
4263 /* Is AP advertizing for WPS association?
4264 * If so, we decide to use WPS by default */
4265 if (wps_ready && wps_pbc &&
4267 #if !defined TIZEN_EXT
4268 connman_network_set_bool(network, "WiFi.UseWPS", true);
4270 DBG("wps is activating by ap but ignore it.");
4275 connman_network_set_frequency(network,
4276 g_supplicant_network_get_frequency(supplicant_network));
4277 #if defined TIZEN_EXT
4278 connman_network_set_bssid(network,
4279 g_supplicant_network_get_bssid(supplicant_network));
4280 connman_network_set_maxrate(network,
4281 g_supplicant_network_get_maxrate(supplicant_network));
4282 connman_network_set_enc_mode(network,
4283 g_supplicant_network_get_enc_mode(supplicant_network));
4284 connman_network_set_rsn_mode(network,
4285 g_supplicant_network_get_rsn_mode(supplicant_network));
4286 connman_network_set_keymgmt(network,
4287 g_supplicant_network_get_keymgmt(supplicant_network));
4288 connman_network_set_bool(network, "WiFi.HS20AP",
4289 g_supplicant_network_is_hs20AP(supplicant_network));
4290 connman_network_set_bssid_list(network,
4291 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
4293 connman_network_set_available(network, true);
4294 connman_network_set_string(network, "WiFi.Mode", mode);
4296 #if defined TIZEN_EXT
4301 connman_network_set_group(network, group);
4303 #if defined TIZEN_EXT
4304 if (wifi_first_scan == true)
4305 found_with_first_scan = true;
4308 if (wifi->hidden && ssid) {
4309 #if defined TIZEN_EXT
4310 if (network_security(wifi->hidden->security) ==
4311 network_security(security) &&
4313 if (!g_strcmp0(wifi->hidden->security, security) &&
4315 wifi->hidden->ssid_len == ssid_len &&
4316 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
4317 connman_network_connect_hidden(network,
4318 wifi->hidden->identity,
4319 wifi->hidden->passphrase,
4320 wifi->hidden->user_data);
4321 wifi->hidden->user_data = NULL;
4322 hidden_free(wifi->hidden);
4323 wifi->hidden = NULL;
4328 static void network_removed(GSupplicantNetwork *network)
4330 GSupplicantInterface *interface;
4331 struct wifi_data *wifi;
4332 const char *name, *identifier;
4333 struct connman_network *connman_network;
4335 #if defined TIZEN_EXT_WIFI_MESH
4337 mode = g_supplicant_network_get_mode(network);
4338 if (!g_strcmp0(mode, "mesh")) {
4339 mesh_peer_removed(network);
4344 interface = g_supplicant_network_get_interface(network);
4345 wifi = g_supplicant_interface_get_data(interface);
4346 identifier = g_supplicant_network_get_identifier(network);
4347 name = g_supplicant_network_get_name(network);
4349 DBG("name %s", name);
4354 connman_network = connman_device_get_network(wifi->device, identifier);
4355 if (!connman_network)
4358 #if defined TIZEN_EXT
4359 if (connman_network == wifi->scan_pending_network)
4360 wifi->scan_pending_network = NULL;
4362 if (connman_network == wifi->pending_network)
4363 wifi->pending_network = NULL;
4365 if(connman_network_get_connecting(connman_network) == true){
4366 connman_network_set_connected(connman_network, false);
4370 wifi->networks = g_slist_remove(wifi->networks, connman_network);
4372 connman_device_remove_network(wifi->device, connman_network);
4373 connman_network_unref(connman_network);
4376 static void network_changed(GSupplicantNetwork *network, const char *property)
4378 GSupplicantInterface *interface;
4379 struct wifi_data *wifi;
4380 const char *name, *identifier;
4381 struct connman_network *connman_network;
4383 #if defined TIZEN_EXT
4384 const unsigned char *bssid;
4385 unsigned int maxrate;
4388 const unsigned char *country_code;
4392 interface = g_supplicant_network_get_interface(network);
4393 wifi = g_supplicant_interface_get_data(interface);
4394 identifier = g_supplicant_network_get_identifier(network);
4395 name = g_supplicant_network_get_name(network);
4397 DBG("name %s", name);
4402 connman_network = connman_device_get_network(wifi->device, identifier);
4403 if (!connman_network)
4406 if (g_str_equal(property, "Signal")) {
4407 connman_network_set_strength(connman_network,
4408 calculate_strength(network));
4409 connman_network_update(connman_network);
4412 #if defined TIZEN_EXT
4413 bssid = g_supplicant_network_get_bssid(network);
4414 maxrate = g_supplicant_network_get_maxrate(network);
4415 frequency = g_supplicant_network_get_frequency(network);
4416 wps = g_supplicant_network_get_wps(network);
4418 connman_network_set_bssid(connman_network, bssid);
4419 connman_network_set_maxrate(connman_network, maxrate);
4420 connman_network_set_frequency(connman_network, frequency);
4421 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
4422 country_code = g_supplicant_network_get_countrycode(network);
4423 connman_network_set_countrycode(connman_network, country_code);
4424 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
4425 connman_network_set_bssid_list(connman_network, bssid_list);
4429 static void network_associated(GSupplicantNetwork *network)
4431 GSupplicantInterface *interface;
4432 struct wifi_data *wifi;
4433 struct connman_network *connman_network;
4434 const char *identifier;
4438 interface = g_supplicant_network_get_interface(network);
4442 wifi = g_supplicant_interface_get_data(interface);
4446 identifier = g_supplicant_network_get_identifier(network);
4448 connman_network = connman_device_get_network(wifi->device, identifier);
4449 if (!connman_network)
4452 if (wifi->network) {
4453 if (wifi->network == connman_network)
4457 * This should never happen, we got associated with
4458 * a network different than the one we were expecting.
4460 DBG("Associated to %p while expecting %p",
4461 connman_network, wifi->network);
4463 connman_network_set_associating(wifi->network, false);
4466 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
4468 wifi->network = connman_network_ref(connman_network);
4472 * Interface state changes callback (interface_state) is always
4473 * called before network_associated callback thus we need to call
4474 * interface_state again in order to process the new state now that
4475 * we have the network properly set.
4477 interface_state(interface);
4480 static void apply_peer_services(GSupplicantPeer *peer,
4481 struct connman_peer *connman_peer)
4483 const unsigned char *data;
4488 connman_peer_reset_services(connman_peer);
4490 data = g_supplicant_peer_get_widi_ies(peer, &length);
4492 connman_peer_add_service(connman_peer,
4493 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
4497 static void add_station(const char *mac)
4499 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
4503 static void remove_station(const char *mac)
4505 connman_technology_tethering_remove_station(mac);
4508 static void peer_found(GSupplicantPeer *peer)
4510 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4511 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4512 struct connman_peer *connman_peer;
4513 const char *identifier, *name;
4515 #if defined TIZEN_EXT
4519 identifier = g_supplicant_peer_get_identifier(peer);
4520 name = g_supplicant_peer_get_name(peer);
4522 DBG("ident: %s", identifier);
4524 connman_peer = connman_peer_get(wifi->device, identifier);
4528 connman_peer = connman_peer_create(identifier);
4529 connman_peer_set_name(connman_peer, name);
4530 connman_peer_set_device(connman_peer, wifi->device);
4531 apply_peer_services(peer, connman_peer);
4533 ret = connman_peer_register(connman_peer);
4534 if (ret < 0 && ret != -EALREADY)
4535 connman_peer_unref(connman_peer);
4537 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
4540 static void peer_lost(GSupplicantPeer *peer)
4542 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4543 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4544 struct connman_peer *connman_peer;
4545 const char *identifier;
4550 identifier = g_supplicant_peer_get_identifier(peer);
4552 DBG("ident: %s", identifier);
4554 connman_peer = connman_peer_get(wifi->device, identifier);
4556 if (wifi->p2p_connecting &&
4557 wifi->pending_peer == connman_peer) {
4558 peer_connect_timeout(wifi);
4560 connman_peer_unregister(connman_peer);
4561 connman_peer_unref(connman_peer);
4564 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
4567 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
4569 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4570 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4571 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
4572 struct connman_peer *connman_peer;
4573 const char *identifier;
4575 identifier = g_supplicant_peer_get_identifier(peer);
4577 DBG("ident: %s", identifier);
4582 connman_peer = connman_peer_get(wifi->device, identifier);
4587 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
4588 apply_peer_services(peer, connman_peer);
4589 connman_peer_services_changed(connman_peer);
4591 case G_SUPPLICANT_PEER_GROUP_CHANGED:
4592 if (!g_supplicant_peer_is_in_a_group(peer))
4593 p_state = CONNMAN_PEER_STATE_IDLE;
4595 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
4597 case G_SUPPLICANT_PEER_GROUP_STARTED:
4599 case G_SUPPLICANT_PEER_GROUP_FINISHED:
4600 p_state = CONNMAN_PEER_STATE_IDLE;
4602 case G_SUPPLICANT_PEER_GROUP_JOINED:
4603 connman_peer_set_iface_address(connman_peer,
4604 g_supplicant_peer_get_iface_address(peer));
4606 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
4607 p_state = CONNMAN_PEER_STATE_IDLE;
4609 case G_SUPPLICANT_PEER_GROUP_FAILED:
4610 if (g_supplicant_peer_has_requested_connection(peer))
4611 p_state = CONNMAN_PEER_STATE_IDLE;
4613 p_state = CONNMAN_PEER_STATE_FAILURE;
4617 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
4618 p_state == CONNMAN_PEER_STATE_FAILURE) {
4619 if (wifi->p2p_connecting
4620 && connman_peer == wifi->pending_peer)
4621 peer_cancel_timeout(wifi);
4623 p_state = CONNMAN_PEER_STATE_UNKNOWN;
4626 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
4629 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
4630 GSupplicantInterface *g_iface;
4631 struct wifi_data *g_wifi;
4633 g_iface = g_supplicant_peer_get_group_interface(peer);
4637 g_wifi = g_supplicant_interface_get_data(g_iface);
4641 connman_peer_set_as_master(connman_peer,
4642 !g_supplicant_peer_is_client(peer));
4643 connman_peer_set_sub_device(connman_peer, g_wifi->device);
4646 * If wpa_supplicant didn't create a dedicated p2p-group
4647 * interface then mark this interface as p2p_device to avoid
4648 * scan and auto-scan are launched on it while P2P is connected.
4650 if (!g_list_find(p2p_iface_list, g_wifi))
4651 wifi->p2p_device = true;
4654 connman_peer_set_state(connman_peer, p_state);
4657 static void peer_request(GSupplicantPeer *peer)
4659 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
4660 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
4661 struct connman_peer *connman_peer;
4662 const char *identifier;
4664 #if defined TIZEN_EXT
4669 identifier = g_supplicant_peer_get_identifier(peer);
4671 DBG("ident: %s", identifier);
4673 connman_peer = connman_peer_get(wifi->device, identifier);
4677 connman_peer_request_connection(connman_peer);
4680 #if defined TIZEN_EXT
4681 static void system_power_off(void)
4684 struct wifi_data *wifi;
4685 struct connman_service *service;
4686 struct connman_ipconfig *ipconfig_ipv4;
4688 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
4689 for (list = iface_list; list; list = list->next) {
4692 if (wifi->network != NULL) {
4693 service = connman_service_lookup_from_network(wifi->network);
4694 ipconfig_ipv4 = __connman_service_get_ip4config(service);
4695 __connman_dhcp_stop(ipconfig_ipv4);
4701 static void network_merged(GSupplicantNetwork *network)
4703 GSupplicantInterface *interface;
4704 GSupplicantState state;
4705 struct wifi_data *wifi;
4706 const char *identifier;
4707 struct connman_network *connman_network;
4711 interface = g_supplicant_network_get_interface(network);
4715 state = g_supplicant_interface_get_state(interface);
4716 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
4719 wifi = g_supplicant_interface_get_data(interface);
4723 identifier = g_supplicant_network_get_identifier(network);
4725 connman_network = connman_device_get_network(wifi->device, identifier);
4726 if (!connman_network)
4729 DBG("merged identifier %s", identifier);
4731 if (wifi->connected == FALSE) {
4733 case G_SUPPLICANT_STATE_AUTHENTICATING:
4734 case G_SUPPLICANT_STATE_ASSOCIATING:
4735 case G_SUPPLICANT_STATE_ASSOCIATED:
4736 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4737 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4738 connman_network_set_associating(connman_network, TRUE);
4740 case G_SUPPLICANT_STATE_COMPLETED:
4741 connman_network_set_connected(connman_network, TRUE);
4744 DBG("Not handled the state : %d", state);
4749 ishs20AP = g_supplicant_network_is_hs20AP(network);
4752 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
4753 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
4754 connman_network_set_string(connman_network, "WiFi.EAP",
4756 connman_network_set_string(connman_network, "WiFi.Identity",
4757 g_supplicant_network_get_identity(network));
4758 connman_network_set_string(connman_network, "WiFi.Phase2",
4759 g_supplicant_network_get_phase2(network));
4764 wifi->network = connman_network;
4767 static void assoc_failed(void *user_data)
4769 struct connman_network *network = user_data;
4770 connman_network_set_associating(network, false);
4774 static void debug(const char *str)
4776 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
4777 connman_debug("%s", str);
4780 static void disconnect_reasoncode(GSupplicantInterface *interface,
4783 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4786 wifi->disconnect_code = reasoncode;
4790 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
4792 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4795 wifi->assoc_code = status_code;
4799 static const GSupplicantCallbacks callbacks = {
4800 .system_ready = system_ready,
4801 .system_killed = system_killed,
4802 .interface_added = interface_added,
4803 .interface_state = interface_state,
4804 .interface_removed = interface_removed,
4805 .p2p_support = p2p_support,
4806 .scan_started = scan_started,
4807 .scan_finished = scan_finished,
4808 .ap_create_fail = ap_create_fail,
4809 .network_added = network_added,
4810 .network_removed = network_removed,
4811 .network_changed = network_changed,
4812 .network_associated = network_associated,
4813 .add_station = add_station,
4814 .remove_station = remove_station,
4815 .peer_found = peer_found,
4816 .peer_lost = peer_lost,
4817 .peer_changed = peer_changed,
4818 .peer_request = peer_request,
4819 #if defined TIZEN_EXT
4820 .system_power_off = system_power_off,
4821 .network_merged = network_merged,
4822 .assoc_failed = assoc_failed,
4825 .disconnect_reasoncode = disconnect_reasoncode,
4826 .assoc_status_code = assoc_status_code,
4827 #if defined TIZEN_EXT_WIFI_MESH
4828 .mesh_support = mesh_support,
4829 .mesh_group_started = mesh_group_started,
4830 .mesh_group_removed = mesh_group_removed,
4831 .mesh_peer_connected = mesh_peer_connected,
4832 .mesh_peer_disconnected = mesh_peer_disconnected,
4837 static int tech_probe(struct connman_technology *technology)
4839 wifi_technology = technology;
4844 static void tech_remove(struct connman_technology *technology)
4846 wifi_technology = NULL;
4849 static GSupplicantSSID *ssid_ap_init(const char *ssid,
4850 const char *passphrase)
4852 GSupplicantSSID *ap;
4854 ap = g_try_malloc0(sizeof(GSupplicantSSID));
4858 ap->mode = G_SUPPLICANT_MODE_MASTER;
4859 #if defined TIZEN_EXT
4860 ap->ssid = (void *) ssid;
4864 ap->ssid_len = strlen(ssid);
4868 if (!passphrase || strlen(passphrase) == 0) {
4869 ap->security = G_SUPPLICANT_SECURITY_NONE;
4870 ap->passphrase = NULL;
4872 ap->security = G_SUPPLICANT_SECURITY_PSK;
4873 ap->protocol = G_SUPPLICANT_PROTO_RSN;
4874 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
4875 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
4876 ap->passphrase = passphrase;
4882 static void ap_start_callback(int result, GSupplicantInterface *interface,
4885 struct wifi_tethering_info *info = user_data;
4887 DBG("result %d index %d bridge %s",
4888 result, info->wifi->index, info->wifi->bridge);
4890 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4891 connman_inet_remove_from_bridge(info->wifi->index,
4892 info->wifi->bridge);
4894 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4895 connman_technology_tethering_notify(info->technology, false);
4896 g_free(info->wifi->tethering_param->ssid);
4897 g_free(info->wifi->tethering_param);
4898 info->wifi->tethering_param = NULL;
4902 g_free(info->ifname);
4906 static void ap_create_callback(int result,
4907 GSupplicantInterface *interface,
4910 struct wifi_tethering_info *info = user_data;
4912 DBG("result %d ifname %s", result,
4913 g_supplicant_interface_get_ifname(interface));
4915 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4916 connman_inet_remove_from_bridge(info->wifi->index,
4917 info->wifi->bridge);
4919 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4920 connman_technology_tethering_notify(info->technology, false);
4921 g_free(info->wifi->tethering_param->ssid);
4922 g_free(info->wifi->tethering_param);
4923 info->wifi->tethering_param = NULL;
4927 g_free(info->ifname);
4933 info->wifi->interface = interface;
4934 g_supplicant_interface_set_data(interface, info->wifi);
4936 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
4937 connman_error("Failed to set interface ap_scan property");
4939 g_supplicant_interface_connect(interface, info->ssid,
4940 ap_start_callback, info);
4943 static void sta_remove_callback(int result,
4944 GSupplicantInterface *interface,
4947 struct wifi_tethering_info *info = user_data;
4948 const char *driver = connman_option_get_string("wifi");
4950 DBG("ifname %s result %d ", info->ifname, result);
4952 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4953 info->wifi->tethering = false;
4954 connman_technology_tethering_notify(info->technology, false);
4956 g_free(info->ifname);
4960 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4961 g_free(info->wifi->tethering_param->ssid);
4962 g_free(info->wifi->tethering_param);
4963 info->wifi->tethering_param = NULL;
4968 info->wifi->interface = NULL;
4970 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
4975 static int enable_wifi_tethering(struct connman_technology *technology,
4976 const char *bridge, const char *identifier,
4977 const char *passphrase, bool available)
4980 GSupplicantInterface *interface;
4981 struct wifi_data *wifi;
4982 struct wifi_tethering_info *info;
4987 for (list = iface_list; list; list = list->next) {
4990 DBG("wifi %p network %p pending_network %p", wifi,
4991 wifi->network, wifi->pending_network);
4993 interface = wifi->interface;
4998 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
5001 ifname = g_supplicant_interface_get_ifname(wifi->interface);
5003 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
5004 DBG("%s does not support AP mode (detected)", ifname);
5008 mode = g_supplicant_interface_get_mode(interface);
5009 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
5010 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
5011 DBG("%s does not support AP mode (capability)", ifname);
5015 if (wifi->network && available)
5018 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
5022 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
5023 if (!wifi->tethering_param) {
5029 info->technology = technology;
5030 info->wifi->bridge = bridge;
5031 info->ssid = ssid_ap_init(identifier, passphrase);
5035 info->ifname = g_strdup(ifname);
5039 wifi->tethering_param->technology = technology;
5040 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
5041 if (!wifi->tethering_param->ssid)
5044 info->wifi->tethering = true;
5045 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
5047 berr = connman_technology_tethering_notify(technology, true);
5051 err = g_supplicant_interface_remove(interface,
5052 sta_remove_callback,
5055 DBG("tethering wifi %p ifname %s", wifi, ifname);
5060 g_free(info->ifname);
5063 g_free(wifi->tethering_param);
5064 wifi->tethering_param = NULL;
5067 * Remove bridge if it was correctly created but remove
5068 * operation failed. Instead, if bridge creation failed then
5069 * break out and do not try again on another interface,
5070 * bridge set-up does not depend on it.
5073 connman_technology_tethering_notify(technology, false);
5081 static int tech_set_tethering(struct connman_technology *technology,
5082 const char *identifier, const char *passphrase,
5083 const char *bridge, bool enabled)
5086 struct wifi_data *wifi;
5092 for (list = iface_list; list; list = list->next) {
5095 if (wifi->tethering) {
5096 wifi->tethering = false;
5098 connman_inet_remove_from_bridge(wifi->index,
5100 wifi->bridged = false;
5104 connman_technology_tethering_notify(technology, false);
5109 DBG("trying tethering for available devices");
5110 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
5114 DBG("trying tethering for any device");
5115 err = enable_wifi_tethering(technology, bridge, identifier,
5122 static void regdom_callback(int result, const char *alpha2, void *user_data)
5126 if (!wifi_technology)
5132 connman_technology_regdom_notify(wifi_technology, alpha2);
5135 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
5137 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
5140 static struct connman_technology_driver tech_driver = {
5142 .type = CONNMAN_SERVICE_TYPE_WIFI,
5143 .probe = tech_probe,
5144 .remove = tech_remove,
5145 .set_tethering = tech_set_tethering,
5146 .set_regdom = tech_set_regdom,
5149 static int wifi_init(void)
5153 err = connman_network_driver_register(&network_driver);
5157 err = g_supplicant_register(&callbacks);
5159 connman_network_driver_unregister(&network_driver);
5163 err = connman_technology_driver_register(&tech_driver);
5165 g_supplicant_unregister(&callbacks);
5166 connman_network_driver_unregister(&network_driver);
5173 static void wifi_exit(void)
5177 connman_technology_driver_unregister(&tech_driver);
5179 g_supplicant_unregister(&callbacks);
5181 connman_network_driver_unregister(&network_driver);
5184 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
5185 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)