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;
168 #if defined TIZEN_EXT
172 #define TIZEN_ASSOC_RETRY_COUNT 4
174 static gboolean wifi_first_scan = false;
175 static gboolean found_with_first_scan = false;
176 static gboolean is_wifi_notifier_registered = false;
180 static GList *iface_list = NULL;
182 static GList *pending_wifi_device = NULL;
183 static GList *p2p_iface_list = NULL;
184 bool wfd_service_registered = false;
186 static void start_autoscan(struct connman_device *device);
188 static int tech_set_tethering(struct connman_technology *technology,
189 const char *identifier, const char *passphrase,
190 const char *bridge, bool enabled);
192 #if defined TIZEN_EXT
193 #define NETCONFIG_SERVICE "net.netconfig"
194 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
195 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
197 struct enc_method_call_data {
198 DBusConnection *connection;
199 struct connman_network *network;
202 static struct enc_method_call_data encrypt_request_data;
204 static void encryption_request_reply(DBusPendingCall *call,
209 DBusMessageIter args;
211 struct connman_service *service;
212 gchar* encrypted_value = NULL;
213 struct connman_network *network = encrypt_request_data.network;
217 reply = dbus_pending_call_steal_reply(call);
219 dbus_error_init(&error);
220 if (dbus_set_error_from_message(&error, reply)) {
221 DBG("send_encryption_request() %s %s", error.name, error.message);
222 dbus_error_free(&error);
226 if (dbus_message_iter_init(reply, &args) == FALSE)
229 dbus_message_iter_get_basic(&args, &out_data);
231 encrypted_value = g_strdup((const gchar *)out_data);
232 service = connman_service_lookup_from_network(network);
235 DBG("encryption result: no service");
239 if (connman_service_get_favorite(service)) {
240 __connman_service_set_passphrase(service, encrypted_value);
241 __connman_service_save(service);
243 connman_network_set_string(network, "WiFi.Passphrase",
246 DBG("encryption result: succeeded");
249 dbus_message_unref(reply);
250 dbus_pending_call_unref(call);
251 dbus_connection_unref(encrypt_request_data.connection);
252 g_free(encrypted_value);
254 encrypt_request_data.connection = NULL;
255 encrypt_request_data.network = NULL;
258 static int send_encryption_request(const char *passphrase,
259 struct connman_network *network)
261 DBusConnection *connection = NULL;
262 DBusMessage *msg = NULL;
263 DBusPendingCall *call;
266 DBG("Invalid parameter");
270 connection = connman_dbus_get_connection();
272 DBG("dbus connection does not exist");
276 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
277 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
279 dbus_connection_unref(connection);
283 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
286 if (!dbus_connection_send_with_reply(connection, msg,
287 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
288 dbus_message_unref(msg);
289 dbus_connection_unref(connection);
294 dbus_message_unref(msg);
295 dbus_connection_unref(connection);
299 encrypt_request_data.connection = connection;
300 encrypt_request_data.network = network;
302 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
303 dbus_message_unref(msg);
309 static int p2p_tech_probe(struct connman_technology *technology)
311 p2p_technology = technology;
316 static void p2p_tech_remove(struct connman_technology *technology)
318 p2p_technology = NULL;
321 static struct connman_technology_driver p2p_tech_driver = {
323 .type = CONNMAN_SERVICE_TYPE_P2P,
324 .probe = p2p_tech_probe,
325 .remove = p2p_tech_remove,
328 static bool is_p2p_connecting(void)
332 for (list = iface_list; list; list = list->next) {
333 struct wifi_data *wifi = list->data;
335 if (wifi->p2p_connecting)
342 static void add_pending_wifi_device(struct wifi_data *wifi)
344 if (g_list_find(pending_wifi_device, wifi))
347 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
350 static struct wifi_data *get_pending_wifi_data(const char *ifname)
354 for (list = pending_wifi_device; list; list = list->next) {
355 struct wifi_data *wifi;
356 const char *dev_name;
359 if (!wifi || !wifi->device)
362 dev_name = connman_device_get_string(wifi->device, "Interface");
363 if (!g_strcmp0(ifname, dev_name)) {
364 pending_wifi_device = g_list_delete_link(
365 pending_wifi_device, list);
373 static void remove_pending_wifi_device(struct wifi_data *wifi)
377 link = g_list_find(pending_wifi_device, wifi);
382 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
385 static void peer_cancel_timeout(struct wifi_data *wifi)
387 if (wifi->p2p_connection_timeout > 0)
388 g_source_remove(wifi->p2p_connection_timeout);
390 wifi->p2p_connection_timeout = 0;
391 wifi->p2p_connecting = false;
393 if (wifi->pending_peer) {
394 connman_peer_unref(wifi->pending_peer);
395 wifi->pending_peer = NULL;
399 static gboolean peer_connect_timeout(gpointer data)
401 struct wifi_data *wifi = data;
405 if (wifi->p2p_connecting) {
406 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
407 GSupplicantPeer *gs_peer =
408 g_supplicant_interface_peer_lookup(wifi->interface,
409 connman_peer_get_identifier(wifi->pending_peer));
411 if (g_supplicant_peer_has_requested_connection(gs_peer))
412 state = CONNMAN_PEER_STATE_IDLE;
414 connman_peer_set_state(wifi->pending_peer, state);
417 peer_cancel_timeout(wifi);
422 static void peer_connect_callback(int result, GSupplicantInterface *interface,
425 struct wifi_data *wifi = user_data;
426 struct connman_peer *peer = wifi->pending_peer;
428 DBG("peer %p - %d", peer, result);
434 peer_connect_timeout(wifi);
438 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
440 wifi->p2p_connection_timeout = g_timeout_add_seconds(
441 P2P_CONNECTION_TIMEOUT,
442 peer_connect_timeout, wifi);
445 static int peer_connect(struct connman_peer *peer,
446 enum connman_peer_wps_method wps_method,
449 struct connman_device *device = connman_peer_get_device(peer);
450 GSupplicantPeerParams *peer_params;
451 GSupplicantPeer *gs_peer;
452 struct wifi_data *wifi;
456 DBG("peer %p", peer);
461 wifi = connman_device_get_data(device);
462 if (!wifi || !wifi->interface)
465 if (wifi->p2p_connecting)
468 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
469 connman_peer_get_identifier(peer));
473 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
474 pin = g_supplicant_peer_is_wps_pin(gs_peer);
476 switch (wps_method) {
477 case CONNMAN_PEER_WPS_UNKNOWN:
478 if ((pbc && pin) || pin)
481 case CONNMAN_PEER_WPS_PBC:
486 case CONNMAN_PEER_WPS_PIN:
487 if (!pin || !wps_pin)
492 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
496 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
498 peer_params->wps_pin = g_strdup(wps_pin);
500 peer_params->master = connman_peer_service_is_master();
502 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
503 peer_connect_callback, wifi);
504 if (ret == -EINPROGRESS) {
505 wifi->pending_peer = connman_peer_ref(peer);
506 wifi->p2p_connecting = true;
507 } else if (ret < 0) {
508 g_free(peer_params->path);
509 g_free(peer_params->wps_pin);
516 static int peer_disconnect(struct connman_peer *peer)
518 struct connman_device *device = connman_peer_get_device(peer);
519 GSupplicantPeerParams peer_params = {};
520 GSupplicantPeer *gs_peer;
521 struct wifi_data *wifi;
524 DBG("peer %p", peer);
529 wifi = connman_device_get_data(device);
533 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
534 connman_peer_get_identifier(peer));
538 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
540 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
542 g_free(peer_params.path);
544 if (ret == -EINPROGRESS) {
545 peer_cancel_timeout(wifi);
546 wifi->p2p_device = false;
552 struct peer_service_registration {
553 peer_service_registration_cb_t callback;
557 static bool is_service_wfd(const unsigned char *specs, int length)
559 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
565 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
567 struct wifi_data *wifi = data;
569 if (!wifi->interface ||
570 !g_supplicant_interface_has_p2p(wifi->interface))
573 if (!wifi->servicing) {
574 g_supplicant_interface_p2p_listen(wifi->interface,
575 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
581 static void register_wfd_service_cb(int result,
582 GSupplicantInterface *iface, void *user_data)
584 struct peer_service_registration *reg_data = user_data;
589 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
591 if (reg_data && reg_data->callback) {
592 reg_data->callback(result, reg_data->user_data);
597 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
598 const unsigned char *spec,
599 int spec_length, const unsigned char *query,
600 int query_length, int version)
602 GSupplicantP2PServiceParams *params;
604 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
609 params->version = version;
610 params->service = g_memdup(spec, spec_length);
611 } else if (query_length > 0 && spec_length > 0) {
612 params->query = g_memdup(query, query_length);
613 params->query_length = query_length;
615 params->response = g_memdup(spec, spec_length);
616 params->response_length = spec_length;
618 params->wfd_ies = g_memdup(spec, spec_length);
619 params->wfd_ies_length = spec_length;
625 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
630 g_free(params->service);
631 g_free(params->query);
632 g_free(params->response);
633 g_free(params->wfd_ies);
638 static int peer_register_wfd_service(const unsigned char *specification,
639 int specification_length,
640 peer_service_registration_cb_t callback,
643 struct peer_service_registration *reg_data = NULL;
644 static GSupplicantP2PServiceParams *params;
649 if (wfd_service_registered)
652 params = fill_in_peer_service_params(specification,
653 specification_length, NULL, 0, 0);
657 reg_data = g_try_malloc0(sizeof(*reg_data));
663 reg_data->callback = callback;
664 reg_data->user_data = user_data;
666 ret = g_supplicant_set_widi_ies(params,
667 register_wfd_service_cb, reg_data);
668 if (ret < 0 && ret != -EINPROGRESS)
671 wfd_service_registered = true;
675 free_peer_service_params(params);
681 static void register_peer_service_cb(int result,
682 GSupplicantInterface *iface, void *user_data)
684 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
685 struct peer_service_registration *reg_data = user_data;
687 #if defined TIZEN_EXT
695 apply_p2p_listen_on_iface(wifi, NULL);
697 if (reg_data->callback)
698 reg_data->callback(result, reg_data->user_data);
703 static int peer_register_service(const unsigned char *specification,
704 int specification_length,
705 const unsigned char *query,
706 int query_length, int version,
707 peer_service_registration_cb_t callback,
710 struct peer_service_registration *reg_data;
711 GSupplicantP2PServiceParams *params;
718 if (specification && !version && !query &&
719 is_service_wfd(specification, specification_length)) {
720 return peer_register_wfd_service(specification,
721 specification_length, callback, user_data);
724 reg_data = g_try_malloc0(sizeof(*reg_data));
728 reg_data->callback = callback;
729 reg_data->user_data = user_data;
733 for (list = iface_list; list; list = list->next) {
734 struct wifi_data *wifi = list->data;
735 GSupplicantInterface *iface = wifi->interface;
737 if (!g_supplicant_interface_has_p2p(iface))
740 params = fill_in_peer_service_params(specification,
741 specification_length, query,
742 query_length, version);
749 ret_f = g_supplicant_interface_p2p_add_service(iface,
750 register_peer_service_cb, params, reg_data);
751 if (ret_f == 0 || ret_f == -EINPROGRESS)
755 ret = g_supplicant_interface_p2p_add_service(iface,
756 register_peer_service_cb, params, NULL);
757 if (ret != 0 && ret != -EINPROGRESS)
758 free_peer_service_params(params);
761 if (ret_f != 0 && ret_f != -EINPROGRESS)
767 static int peer_unregister_wfd_service(void)
769 GSupplicantP2PServiceParams *params;
772 if (!wfd_service_registered)
775 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
779 wfd_service_registered = false;
781 g_supplicant_set_widi_ies(params, NULL, NULL);
783 for (list = iface_list; list; list = list->next) {
784 struct wifi_data *wifi = list->data;
786 if (!g_supplicant_interface_has_p2p(wifi->interface))
790 if (!wifi->servicing || wifi->servicing < 0) {
791 g_supplicant_interface_p2p_listen(wifi->interface,
800 static int peer_unregister_service(const unsigned char *specification,
801 int specification_length,
802 const unsigned char *query,
803 int query_length, int version)
805 GSupplicantP2PServiceParams *params;
810 if (specification && !version && !query &&
811 is_service_wfd(specification, specification_length)) {
812 ret = peer_unregister_wfd_service();
813 if (ret != 0 && ret != -EINPROGRESS)
818 for (list = iface_list; list; list = list->next) {
819 struct wifi_data *wifi = list->data;
820 GSupplicantInterface *iface = wifi->interface;
825 if (!g_supplicant_interface_has_p2p(iface))
828 params = fill_in_peer_service_params(specification,
829 specification_length, query,
830 query_length, version);
836 ret = g_supplicant_interface_p2p_del_service(iface, params);
837 if (ret != 0 && ret != -EINPROGRESS)
838 free_peer_service_params(params);
841 if (!wifi->servicing || wifi->servicing < 0) {
842 g_supplicant_interface_p2p_listen(iface, 0, 0);
850 static struct connman_peer_driver peer_driver = {
851 .connect = peer_connect,
852 .disconnect = peer_disconnect,
853 .register_service = peer_register_service,
854 .unregister_service = peer_unregister_service,
857 static void handle_tethering(struct wifi_data *wifi)
859 if (!wifi->tethering)
868 DBG("index %d bridge %s", wifi->index, wifi->bridge);
870 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
873 wifi->bridged = true;
876 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
878 struct connman_device *device = user_data;
879 struct wifi_data *wifi = connman_device_get_data(device);
884 DBG("index %d flags %d change %d", wifi->index, flags, change);
886 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
890 DBG("interface down");
893 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
894 if (flags & IFF_LOWER_UP) {
897 handle_tethering(wifi);
905 static int wifi_probe(struct connman_device *device)
907 struct wifi_data *wifi;
909 DBG("device %p", device);
911 wifi = g_try_new0(struct wifi_data, 1);
915 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
916 wifi->ap_supported = WIFI_AP_UNKNOWN;
917 wifi->tethering_param = NULL;
919 connman_device_set_data(device, wifi);
920 wifi->device = connman_device_ref(device);
922 wifi->index = connman_device_get_index(device);
925 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
926 wifi_newlink, device);
927 if (is_p2p_connecting())
928 add_pending_wifi_device(wifi);
930 iface_list = g_list_append(iface_list, wifi);
935 static void remove_networks(struct connman_device *device,
936 struct wifi_data *wifi)
940 for (list = wifi->networks; list; list = list->next) {
941 struct connman_network *network = list->data;
943 connman_device_remove_network(device, network);
944 connman_network_unref(network);
947 g_slist_free(wifi->networks);
948 wifi->networks = NULL;
951 static void remove_peers(struct wifi_data *wifi)
955 for (list = wifi->peers; list; list = list->next) {
956 struct connman_peer *peer = list->data;
958 connman_peer_unregister(peer);
959 connman_peer_unref(peer);
962 g_slist_free(wifi->peers);
966 static void reset_autoscan(struct connman_device *device)
968 struct wifi_data *wifi = connman_device_get_data(device);
969 struct autoscan_params *autoscan;
973 if (!wifi || !wifi->autoscan)
976 autoscan = wifi->autoscan;
978 if (autoscan->timeout == 0 && autoscan->interval == 0)
981 g_source_remove(autoscan->timeout);
983 autoscan->timeout = 0;
984 autoscan->interval = 0;
986 connman_device_unref(device);
989 static void stop_autoscan(struct connman_device *device)
991 const struct wifi_data *wifi = connman_device_get_data(device);
993 if (!wifi || !wifi->autoscan)
996 reset_autoscan(device);
998 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1001 static void check_p2p_technology(void)
1003 bool p2p_exists = false;
1006 for (list = iface_list; list; list = list->next) {
1007 struct wifi_data *w = list->data;
1010 g_supplicant_interface_has_p2p(w->interface))
1015 connman_technology_driver_unregister(&p2p_tech_driver);
1016 connman_peer_driver_unregister(&peer_driver);
1020 static void wifi_remove(struct connman_device *device)
1022 struct wifi_data *wifi = connman_device_get_data(device);
1024 DBG("device %p wifi %p", device, wifi);
1029 stop_autoscan(device);
1031 if (wifi->p2p_device)
1032 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1034 iface_list = g_list_remove(iface_list, wifi);
1036 check_p2p_technology();
1038 remove_pending_wifi_device(wifi);
1040 if (wifi->p2p_find_timeout) {
1041 g_source_remove(wifi->p2p_find_timeout);
1042 connman_device_unref(wifi->device);
1045 if (wifi->p2p_connection_timeout)
1046 g_source_remove(wifi->p2p_connection_timeout);
1048 remove_networks(device, wifi);
1051 connman_device_set_powered(device, false);
1052 connman_device_set_data(device, NULL);
1053 connman_device_unref(wifi->device);
1054 connman_rtnl_remove_watch(wifi->watch);
1056 g_supplicant_interface_set_data(wifi->interface, NULL);
1058 g_supplicant_interface_cancel(wifi->interface);
1060 if (wifi->scan_params)
1061 g_supplicant_free_scan_params(wifi->scan_params);
1063 g_free(wifi->autoscan);
1064 g_free(wifi->identifier);
1068 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1072 for (iter = list; iter; iter = g_slist_next(iter)) {
1073 struct scan_ssid *scan_ssid = iter->data;
1075 if (ssid_len == scan_ssid->ssid_len &&
1076 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1083 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1084 int freq, GSupplicantScanParams *scan_data,
1085 int driver_max_scan_ssids, char *ssid_name)
1088 struct scan_ssid *scan_ssid;
1090 if ((driver_max_scan_ssids == 0 ||
1091 driver_max_scan_ssids > scan_data->num_ssids) &&
1092 (hex_ssid || raw_ssid)) {
1094 unsigned int j = 0, hex;
1097 size_t hex_ssid_len = strlen(hex_ssid);
1099 ssid = g_try_malloc0(hex_ssid_len / 2);
1103 for (i = 0; i < hex_ssid_len; i += 2) {
1104 sscanf(hex_ssid + i, "%02x", &hex);
1113 * If we have already added hidden AP to the list,
1114 * then do not do it again. This might happen if you have
1115 * used or are using multiple wifi cards, so in that case
1116 * you might have multiple service files for same AP.
1118 if (is_duplicate(scan_data->ssids, ssid, j)) {
1124 scan_ssid = g_try_new(struct scan_ssid, 1);
1131 memcpy(scan_ssid->ssid, ssid, j);
1132 scan_ssid->ssid_len = j;
1133 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1136 scan_data->num_ssids++;
1138 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1139 scan_data->num_ssids);
1146 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1148 if (!scan_data->freqs) {
1149 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1150 if (!scan_data->freqs) {
1151 g_slist_free_full(scan_data->ssids, g_free);
1155 scan_data->num_freqs = 1;
1156 scan_data->freqs[0] = freq;
1158 bool duplicate = false;
1160 /* Don't add duplicate entries */
1161 for (i = 0; i < scan_data->num_freqs; i++) {
1162 if (scan_data->freqs[i] == freq) {
1169 scan_data->num_freqs++;
1170 scan_data->freqs = g_try_realloc(scan_data->freqs,
1171 sizeof(uint16_t) * scan_data->num_freqs);
1172 if (!scan_data->freqs) {
1173 g_slist_free_full(scan_data->ssids, g_free);
1176 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1183 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1185 struct connman_config_entry **entries;
1191 int num_ssids = 0, add_param_failed = 0;
1193 services = connman_storage_get_services();
1194 for (i = 0; services && services[i]; i++) {
1195 if (strncmp(services[i], "wifi_", 5) != 0)
1198 keyfile = connman_storage_load_service(services[i]);
1202 value = g_key_file_get_boolean(keyfile,
1203 services[i], "Hidden", NULL);
1205 g_key_file_free(keyfile);
1209 value = g_key_file_get_boolean(keyfile,
1210 services[i], "Favorite", NULL);
1212 g_key_file_free(keyfile);
1216 #if defined TIZEN_EXT
1217 value = g_key_file_get_boolean(keyfile,
1218 services[i], "AutoConnect", NULL);
1220 g_key_file_free(keyfile);
1225 ssid = g_key_file_get_string(keyfile,
1226 services[i], "SSID", NULL);
1228 name = g_key_file_get_string(keyfile, services[i], "Name",
1231 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1239 g_key_file_free(keyfile);
1243 * Check if there are any hidden AP that needs to be provisioned.
1245 entries = connman_config_get_entries("wifi");
1246 for (i = 0; entries && entries[i]; i++) {
1249 if (!entries[i]->hidden)
1252 if (!entries[i]->ssid) {
1253 ssid = entries[i]->name;
1256 ssid = entries[i]->ssid;
1257 len = entries[i]->ssid_len;
1263 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1270 connman_config_free_entries(entries);
1272 if (add_param_failed > 0)
1273 DBG("Unable to scan %d out of %d SSIDs",
1274 add_param_failed, num_ssids);
1276 g_strfreev(services);
1281 static int get_hidden_connections_params(struct wifi_data *wifi,
1282 GSupplicantScanParams *scan_params)
1284 int driver_max_ssids, i;
1285 GSupplicantScanParams *orig_params;
1288 * Scan hidden networks so that we can autoconnect to them.
1289 * We will assume 1 as a default number of ssid to scan.
1291 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1293 if (driver_max_ssids == 0)
1294 driver_max_ssids = 1;
1296 DBG("max ssids %d", driver_max_ssids);
1298 if (!wifi->scan_params) {
1299 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1300 if (!wifi->scan_params)
1303 if (get_hidden_connections(wifi->scan_params) == 0) {
1304 g_supplicant_free_scan_params(wifi->scan_params);
1305 wifi->scan_params = NULL;
1311 orig_params = wifi->scan_params;
1313 /* Let's transfer driver_max_ssids params */
1314 for (i = 0; i < driver_max_ssids; i++) {
1315 struct scan_ssid *ssid;
1317 if (!wifi->scan_params->ssids)
1320 ssid = orig_params->ssids->data;
1321 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1322 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1326 scan_params->num_ssids = i;
1327 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1329 scan_params->freqs = g_memdup(orig_params->freqs,
1330 sizeof(uint16_t) * orig_params->num_freqs);
1331 if (!scan_params->freqs)
1334 scan_params->num_freqs = orig_params->num_freqs;
1339 orig_params->num_ssids -= scan_params->num_ssids;
1341 return scan_params->num_ssids;
1344 g_slist_free_full(scan_params->ssids, g_free);
1345 g_supplicant_free_scan_params(wifi->scan_params);
1346 wifi->scan_params = NULL;
1351 static int throw_wifi_scan(struct connman_device *device,
1352 GSupplicantInterfaceCallback callback)
1354 struct wifi_data *wifi = connman_device_get_data(device);
1360 DBG("device %p %p", device, wifi->interface);
1362 if (wifi->tethering)
1364 #if defined TIZEN_EXT
1365 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1367 if (connman_device_get_scanning(device))
1371 connman_device_ref(device);
1373 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1376 connman_device_set_scanning(device,
1377 CONNMAN_SERVICE_TYPE_WIFI, true);
1379 connman_device_unref(device);
1384 static void hidden_free(struct hidden_params *hidden)
1389 if (hidden->scan_params)
1390 g_supplicant_free_scan_params(hidden->scan_params);
1391 g_free(hidden->identity);
1392 g_free(hidden->passphrase);
1393 g_free(hidden->security);
1397 #if defined TIZEN_EXT
1398 static void service_state_changed(struct connman_service *service,
1399 enum connman_service_state state);
1401 static int network_connect(struct connman_network *network);
1403 static struct connman_notifier notifier = {
1405 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1406 .service_state_changed = service_state_changed,
1409 static void service_state_changed(struct connman_service *service,
1410 enum connman_service_state state)
1412 enum connman_service_type type;
1414 type = connman_service_get_type(service);
1415 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1418 DBG("service %p state %d", service, state);
1421 case CONNMAN_SERVICE_STATE_READY:
1422 case CONNMAN_SERVICE_STATE_ONLINE:
1423 case CONNMAN_SERVICE_STATE_FAILURE:
1424 connman_notifier_unregister(¬ifier);
1425 is_wifi_notifier_registered = FALSE;
1427 __connman_device_request_scan(type);
1436 static void scan_callback(int result, GSupplicantInterface *interface,
1439 struct connman_device *device = user_data;
1440 struct wifi_data *wifi = connman_device_get_data(device);
1443 DBG("result %d wifi %p", result, wifi);
1446 if (wifi->hidden && !wifi->postpone_hidden) {
1447 connman_network_clear_hidden(wifi->hidden->user_data);
1448 hidden_free(wifi->hidden);
1449 wifi->hidden = NULL;
1452 if (wifi->scan_params) {
1453 g_supplicant_free_scan_params(wifi->scan_params);
1454 wifi->scan_params = NULL;
1459 connman_device_reset_scanning(device);
1461 /* User is connecting to a hidden AP, let's wait for finished event */
1462 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1463 GSupplicantScanParams *scan_params;
1466 wifi->postpone_hidden = false;
1467 scan_params = wifi->hidden->scan_params;
1468 wifi->hidden->scan_params = NULL;
1470 reset_autoscan(device);
1472 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1473 scan_callback, device);
1477 /* On error, let's recall scan_callback, which will cleanup */
1478 return scan_callback(ret, interface, user_data);
1481 #if defined TIZEN_EXT
1482 if (wifi && wifi->allow_full_scan) {
1484 DBG("Trigger Full Channel Scan");
1485 wifi->allow_full_scan = FALSE;
1487 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1488 scan_callback, device);
1492 /* On error, let's recall scan_callback, which will cleanup */
1493 return scan_callback(ret, interface, user_data);
1497 scanning = connman_device_get_scanning(device);
1499 connman_device_set_scanning(device,
1500 CONNMAN_SERVICE_TYPE_WIFI, false);
1502 if (result != -ENOLINK)
1503 #if defined TIZEN_EXT
1506 start_autoscan(device);
1509 * If we are here then we were scanning; however, if we are
1510 * also mid-flight disabling the interface, then wifi_disable
1511 * has already cleared the device scanning state and
1512 * unreferenced the device, obviating the need to do it here.
1516 connman_device_unref(device);
1518 #if defined TIZEN_EXT
1519 if (wifi && wifi->scan_pending_network && result != -EIO) {
1520 network_connect(wifi->scan_pending_network);
1521 wifi->scan_pending_network = NULL;
1522 connman_network_set_connecting(wifi->network);
1525 if (is_wifi_notifier_registered != true &&
1526 wifi_first_scan == true && found_with_first_scan == true) {
1527 wifi_first_scan = false;
1528 found_with_first_scan = false;
1530 connman_notifier_register(¬ifier);
1531 is_wifi_notifier_registered = true;
1536 static void scan_callback_hidden(int result,
1537 GSupplicantInterface *interface, void *user_data)
1539 struct connman_device *device = user_data;
1540 struct wifi_data *wifi = connman_device_get_data(device);
1541 GSupplicantScanParams *scan_params;
1544 DBG("result %d wifi %p", result, wifi);
1549 /* User is trying to connect to a hidden AP */
1550 if (wifi->hidden && wifi->postpone_hidden)
1553 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1557 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1558 ret = g_supplicant_interface_scan(wifi->interface,
1560 scan_callback_hidden,
1566 g_supplicant_free_scan_params(scan_params);
1569 scan_callback(result, interface, user_data);
1572 static gboolean autoscan_timeout(gpointer data)
1574 struct connman_device *device = data;
1575 struct wifi_data *wifi = connman_device_get_data(device);
1576 struct autoscan_params *autoscan;
1582 autoscan = wifi->autoscan;
1584 if (autoscan->interval <= 0) {
1585 interval = autoscan->base;
1588 interval = autoscan->interval * autoscan->base;
1590 #if defined TIZEN_EXT
1591 if (autoscan->interval >= autoscan->limit)
1593 if (interval > autoscan->limit)
1595 interval = autoscan->limit;
1597 throw_wifi_scan(wifi->device, scan_callback_hidden);
1600 DBG("interval %d", interval);
1602 autoscan->interval = interval;
1604 autoscan->timeout = g_timeout_add_seconds(interval,
1605 autoscan_timeout, device);
1610 static void start_autoscan(struct connman_device *device)
1612 struct wifi_data *wifi = connman_device_get_data(device);
1613 struct autoscan_params *autoscan;
1620 if (wifi->p2p_device)
1623 if (wifi->connected)
1626 autoscan = wifi->autoscan;
1630 if (autoscan->timeout > 0 || autoscan->interval > 0)
1633 connman_device_ref(device);
1635 autoscan_timeout(device);
1638 static struct autoscan_params *parse_autoscan_params(const char *params)
1640 struct autoscan_params *autoscan;
1645 DBG("Emulating autoscan");
1647 list_params = g_strsplit(params, ":", 0);
1648 if (list_params == 0)
1651 if (g_strv_length(list_params) < 3) {
1652 g_strfreev(list_params);
1656 base = atoi(list_params[1]);
1657 limit = atoi(list_params[2]);
1659 g_strfreev(list_params);
1661 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1663 DBG("Could not allocate memory for autoscan");
1667 DBG("base %d - limit %d", base, limit);
1668 autoscan->base = base;
1669 autoscan->limit = limit;
1674 static void setup_autoscan(struct wifi_data *wifi)
1676 if (!wifi->autoscan)
1677 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1679 start_autoscan(wifi->device);
1682 static void finalize_interface_creation(struct wifi_data *wifi)
1684 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1686 if (!wifi->device) {
1687 connman_error("WiFi device not set");
1691 connman_device_set_powered(wifi->device, true);
1693 if (!connman_setting_get_bool("BackgroundScanning"))
1696 if (wifi->p2p_device)
1699 setup_autoscan(wifi);
1702 static void interface_create_callback(int result,
1703 GSupplicantInterface *interface,
1706 struct wifi_data *wifi = user_data;
1708 DBG("result %d ifname %s, wifi %p", result,
1709 g_supplicant_interface_get_ifname(interface),
1712 if (result < 0 || !wifi)
1715 wifi->interface = interface;
1716 g_supplicant_interface_set_data(interface, wifi);
1718 if (g_supplicant_interface_get_ready(interface)) {
1719 wifi->interface_ready = true;
1720 finalize_interface_creation(wifi);
1724 static int wifi_enable(struct connman_device *device)
1726 struct wifi_data *wifi = connman_device_get_data(device);
1729 const char *driver = connman_option_get_string("wifi");
1732 DBG("device %p %p", device, wifi);
1734 index = connman_device_get_index(device);
1735 if (!wifi || index < 0)
1738 if (is_p2p_connecting())
1739 return -EINPROGRESS;
1741 interface = connman_inet_ifname(index);
1742 ret = g_supplicant_interface_create(interface, driver, NULL,
1743 interface_create_callback,
1750 return -EINPROGRESS;
1753 static int wifi_disable(struct connman_device *device)
1755 struct wifi_data *wifi = connman_device_get_data(device);
1758 DBG("device %p wifi %p", device, wifi);
1763 wifi->connected = false;
1764 wifi->disconnecting = false;
1766 if (wifi->pending_network)
1767 wifi->pending_network = NULL;
1769 stop_autoscan(device);
1771 if (wifi->p2p_find_timeout) {
1772 g_source_remove(wifi->p2p_find_timeout);
1773 wifi->p2p_find_timeout = 0;
1774 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1775 connman_device_unref(wifi->device);
1778 /* In case of a user scan, device is still referenced */
1779 if (connman_device_get_scanning(device)) {
1780 connman_device_set_scanning(device,
1781 CONNMAN_SERVICE_TYPE_WIFI, false);
1782 connman_device_unref(wifi->device);
1785 remove_networks(device, wifi);
1788 #if defined TIZEN_EXT
1789 wifi->scan_pending_network = NULL;
1791 if (is_wifi_notifier_registered == true) {
1792 connman_notifier_unregister(¬ifier);
1793 is_wifi_notifier_registered = false;
1797 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1801 return -EINPROGRESS;
1804 struct last_connected {
1810 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1812 GTimeVal *aval = (GTimeVal *)a;
1813 GTimeVal *bval = (GTimeVal *)b;
1815 /* Note that the sort order is descending */
1816 if (aval->tv_sec < bval->tv_sec)
1819 if (aval->tv_sec > bval->tv_sec)
1825 static void free_entry(gpointer data)
1827 struct last_connected *entry = data;
1829 g_free(entry->ssid);
1833 static int get_latest_connections(int max_ssids,
1834 GSupplicantScanParams *scan_data)
1836 GSequenceIter *iter;
1837 GSequence *latest_list;
1838 struct last_connected *entry;
1847 latest_list = g_sequence_new(free_entry);
1851 services = connman_storage_get_services();
1852 for (i = 0; services && services[i]; i++) {
1853 if (strncmp(services[i], "wifi_", 5) != 0)
1856 keyfile = connman_storage_load_service(services[i]);
1860 str = g_key_file_get_string(keyfile,
1861 services[i], "Favorite", NULL);
1862 if (!str || g_strcmp0(str, "true")) {
1864 g_key_file_free(keyfile);
1869 str = g_key_file_get_string(keyfile,
1870 services[i], "AutoConnect", NULL);
1871 if (!str || g_strcmp0(str, "true")) {
1873 g_key_file_free(keyfile);
1878 str = g_key_file_get_string(keyfile,
1879 services[i], "Modified", NULL);
1881 g_key_file_free(keyfile);
1884 g_time_val_from_iso8601(str, &modified);
1887 ssid = g_key_file_get_string(keyfile,
1888 services[i], "SSID", NULL);
1890 freq = g_key_file_get_integer(keyfile, services[i],
1893 entry = g_try_new(struct last_connected, 1);
1895 g_sequence_free(latest_list);
1896 g_key_file_free(keyfile);
1902 entry->modified = modified;
1905 g_sequence_insert_sorted(latest_list, entry,
1911 g_key_file_free(keyfile);
1914 g_strfreev(services);
1916 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1918 iter = g_sequence_get_begin_iter(latest_list);
1920 for (i = 0; i < num_ssids; i++) {
1921 entry = g_sequence_get(iter);
1923 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1924 entry->modified.tv_sec);
1926 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1927 max_ssids, entry->ssid);
1929 iter = g_sequence_iter_next(iter);
1932 g_sequence_free(latest_list);
1936 static int wifi_scan_simple(struct connman_device *device)
1938 reset_autoscan(device);
1940 return throw_wifi_scan(device, scan_callback_hidden);
1943 static gboolean p2p_find_stop(gpointer data)
1945 struct connman_device *device = data;
1946 struct wifi_data *wifi = connman_device_get_data(device);
1951 wifi->p2p_find_timeout = 0;
1953 g_supplicant_interface_p2p_stop_find(wifi->interface);
1956 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1958 connman_device_unref(device);
1959 reset_autoscan(device);
1964 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1967 struct connman_device *device = user_data;
1968 struct wifi_data *wifi = connman_device_get_data(device);
1970 DBG("result %d wifi %p", result, wifi);
1975 if (wifi->p2p_find_timeout) {
1976 g_source_remove(wifi->p2p_find_timeout);
1977 wifi->p2p_find_timeout = 0;
1983 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1984 p2p_find_stop, device);
1985 if (!wifi->p2p_find_timeout)
1990 p2p_find_stop(device);
1993 static int p2p_find(struct connman_device *device)
1995 struct wifi_data *wifi;
2000 if (!p2p_technology)
2003 wifi = connman_device_get_data(device);
2005 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2008 reset_autoscan(device);
2009 connman_device_ref(device);
2011 ret = g_supplicant_interface_p2p_find(wifi->interface,
2012 p2p_find_callback, device);
2014 connman_device_unref(device);
2015 start_autoscan(device);
2017 connman_device_set_scanning(device,
2018 CONNMAN_SERVICE_TYPE_P2P, true);
2024 #if defined TIZEN_EXT
2025 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2028 struct connman_device *device = user_data;
2029 struct wifi_data *wifi = connman_device_get_data(device);
2032 DBG("result %d wifi %p", result, wifi);
2034 if (wifi && wifi->scan_params) {
2035 g_supplicant_free_scan_params(wifi->scan_params);
2036 wifi->scan_params = NULL;
2039 scanning = connman_device_get_scanning(device);
2041 connman_device_set_scanning(device,
2042 CONNMAN_SERVICE_TYPE_WIFI, false);
2043 connman_device_unref(device);
2047 static int wifi_specific_scan(enum connman_service_type type,
2048 struct connman_device *device, int scan_type,
2049 GSList *specific_scan_list, void *user_data)
2051 GSList *list = NULL;
2053 struct wifi_data *wifi = connman_device_get_data(device);
2054 GSupplicantScanParams *scan_params = NULL;
2055 struct scan_ssid *scan_ssid = NULL;
2064 if (wifi->p2p_device)
2067 if (type == CONNMAN_SERVICE_TYPE_P2P)
2068 return p2p_find(device);
2070 if (wifi->tethering)
2073 scanning = connman_device_get_scanning(device);
2077 DBG("scan_type: %d", scan_type);
2078 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2079 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2081 DBG("Failed to allocate memory.");
2085 for (list = specific_scan_list; list; list = list->next) {
2086 ssid = (char *)list->data;
2087 int ssid_len = strlen(ssid);
2089 scan_ssid = g_try_new0(struct scan_ssid, 1);
2091 DBG("Failed to allocate memory.");
2092 g_supplicant_free_scan_params(scan_params);
2096 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2097 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
2098 scan_ssid->ssid_len = ssid_len;
2099 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2102 scan_params->num_ssids = count;
2104 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2106 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2108 DBG("Failed to allocate memory.");
2112 guint num_freqs = g_slist_length(specific_scan_list);
2113 DBG("num_freqs: %d", num_freqs);
2115 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2116 if (!scan_params->freqs) {
2117 DBG("Failed to allocate memory.");
2118 g_free(scan_params);
2123 for (list = specific_scan_list; list; list = list->next) {
2124 freq = (int)list->data;
2126 scan_params->freqs[count] = freq;
2127 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2130 scan_params->num_freqs = count;
2132 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2133 int freq_count, ap_count;
2134 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2136 DBG("Failed to allocate memory.");
2140 guint size = g_slist_length(specific_scan_list);
2142 scan_params->freqs = g_try_new0(uint16_t, size/2);
2143 if (!scan_params->freqs) {
2144 DBG("Failed to allocate memory.");
2145 g_free(scan_params);
2149 ap_count = freq_count = 0;
2150 for (list = specific_scan_list; list; list = list->next) {
2151 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2152 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2153 int ssid_len = strlen(ssid);
2155 scan_ssid = g_try_new0(struct scan_ssid, 1);
2157 DBG("Failed to allocate memory.");
2158 g_supplicant_free_scan_params(scan_params);
2162 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2163 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
2164 scan_ssid->ssid_len = ssid_len;
2165 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2169 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2170 scan_params->freqs[freq_count] = freq;
2171 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2175 scan_params->num_ssids = ap_count;
2176 scan_params->num_freqs = freq_count;
2178 DBG("Invalid scan");
2182 reset_autoscan(device);
2183 connman_device_ref(device);
2185 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2186 specific_scan_callback, device);
2189 connman_device_set_scanning(device,
2190 CONNMAN_SERVICE_TYPE_WIFI, true);
2192 g_supplicant_free_scan_params(scan_params);
2193 connman_device_unref(device);
2201 * Note that the hidden scan is only used when connecting to this specific
2202 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2204 static int wifi_scan(enum connman_service_type type,
2205 struct connman_device *device,
2206 const char *ssid, unsigned int ssid_len,
2207 const char *identity, const char* passphrase,
2208 const char *security, void *user_data)
2210 struct wifi_data *wifi = connman_device_get_data(device);
2211 GSupplicantScanParams *scan_params = NULL;
2212 struct scan_ssid *scan_ssid;
2213 struct hidden_params *hidden;
2215 int driver_max_ssids = 0;
2222 if (wifi->p2p_device)
2225 if (wifi->tethering)
2228 if (type == CONNMAN_SERVICE_TYPE_P2P)
2229 return p2p_find(device);
2231 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2233 scanning = connman_device_get_scanning(device);
2235 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2239 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2241 DBG("max ssids %d", driver_max_ssids);
2242 if (driver_max_ssids == 0)
2243 return wifi_scan_simple(device);
2247 if (scanning && wifi->hidden && wifi->postpone_hidden)
2253 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2258 scan_ssid = g_try_new(struct scan_ssid, 1);
2260 g_free(scan_params);
2264 memcpy(scan_ssid->ssid, ssid, ssid_len);
2265 scan_ssid->ssid_len = ssid_len;
2266 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2268 scan_params->num_ssids = 1;
2270 hidden = g_try_new0(struct hidden_params, 1);
2272 g_supplicant_free_scan_params(scan_params);
2277 hidden_free(wifi->hidden);
2278 wifi->hidden = NULL;
2281 memcpy(hidden->ssid, ssid, ssid_len);
2282 hidden->ssid_len = ssid_len;
2283 hidden->identity = g_strdup(identity);
2284 hidden->passphrase = g_strdup(passphrase);
2285 hidden->security = g_strdup(security);
2286 hidden->user_data = user_data;
2287 wifi->hidden = hidden;
2290 /* Let's keep this active scan for later,
2291 * when current scan will be over. */
2292 wifi->postpone_hidden = TRUE;
2293 hidden->scan_params = scan_params;
2297 } else if (wifi->connected) {
2298 g_supplicant_free_scan_params(scan_params);
2299 return wifi_scan_simple(device);
2301 ret = get_latest_connections(driver_max_ssids, scan_params);
2303 g_supplicant_free_scan_params(scan_params);
2304 return wifi_scan_simple(device);
2308 connman_device_ref(device);
2310 reset_autoscan(device);
2312 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2313 scan_callback, device);
2316 connman_device_set_scanning(device,
2317 CONNMAN_SERVICE_TYPE_WIFI, true);
2318 #if defined TIZEN_EXT
2319 /*To allow the Full Scan after ssid based scan, set the flag here
2320 It is required because Tizen does not use the ConnMan specific
2321 backgroung Scan feature.Tizen has added the BG Scan feature in
2322 net-config. To sync with up ConnMan, we need to issue the Full Scan
2323 after SSID specific scan.*/
2324 wifi->allow_full_scan = TRUE;
2327 g_supplicant_free_scan_params(scan_params);
2328 connman_device_unref(device);
2331 hidden_free(wifi->hidden);
2332 wifi->hidden = NULL;
2339 static void wifi_regdom_callback(int result,
2343 struct connman_device *device = user_data;
2345 connman_device_regdom_notify(device, result, alpha2);
2347 connman_device_unref(device);
2350 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2352 struct wifi_data *wifi = connman_device_get_data(device);
2358 connman_device_ref(device);
2360 ret = g_supplicant_interface_set_country(wifi->interface,
2361 wifi_regdom_callback,
2364 connman_device_unref(device);
2369 static struct connman_device_driver wifi_ng_driver = {
2371 .type = CONNMAN_DEVICE_TYPE_WIFI,
2372 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2373 .probe = wifi_probe,
2374 .remove = wifi_remove,
2375 .enable = wifi_enable,
2376 .disable = wifi_disable,
2378 .set_regdom = wifi_set_regdom,
2379 #if defined TIZEN_EXT
2380 .specific_scan = wifi_specific_scan,
2384 static void system_ready(void)
2388 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2389 connman_error("Failed to register WiFi driver");
2392 static void system_killed(void)
2396 connman_device_driver_unregister(&wifi_ng_driver);
2399 static int network_probe(struct connman_network *network)
2401 DBG("network %p", network);
2406 static void network_remove(struct connman_network *network)
2408 struct connman_device *device = connman_network_get_device(network);
2409 struct wifi_data *wifi;
2411 DBG("network %p", network);
2413 wifi = connman_device_get_data(device);
2417 if (wifi->network != network)
2420 wifi->network = NULL;
2422 #if defined TIZEN_EXT
2423 wifi->disconnecting = false;
2425 if (wifi->pending_network == network)
2426 wifi->pending_network = NULL;
2428 if (wifi->scan_pending_network == network)
2429 wifi->scan_pending_network = NULL;
2433 static void connect_callback(int result, GSupplicantInterface *interface,
2436 #if defined TIZEN_EXT
2438 struct wifi_data *wifi;
2440 struct connman_network *network = user_data;
2442 DBG("network %p result %d", network, result);
2444 #if defined TIZEN_EXT
2445 set_connman_bssid(RESET_BSSID, NULL);
2447 for (list = iface_list; list; list = list->next) {
2450 if (wifi && wifi->network == network)
2454 /* wifi_data may be invalid because wifi is already disabled */
2459 if (result == -ENOKEY) {
2460 connman_network_set_error(network,
2461 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2462 } else if (result < 0) {
2463 connman_network_set_error(network,
2464 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2467 connman_network_unref(network);
2470 static GSupplicantSecurity network_security(const char *security)
2472 if (g_str_equal(security, "none"))
2473 return G_SUPPLICANT_SECURITY_NONE;
2474 else if (g_str_equal(security, "wep"))
2475 return G_SUPPLICANT_SECURITY_WEP;
2476 else if (g_str_equal(security, "psk"))
2477 return G_SUPPLICANT_SECURITY_PSK;
2478 else if (g_str_equal(security, "wpa"))
2479 return G_SUPPLICANT_SECURITY_PSK;
2480 else if (g_str_equal(security, "rsn"))
2481 return G_SUPPLICANT_SECURITY_PSK;
2482 else if (g_str_equal(security, "ieee8021x"))
2483 return G_SUPPLICANT_SECURITY_IEEE8021X;
2484 #if defined TIZEN_EXT
2485 else if (g_str_equal(security, "ft_psk") == TRUE)
2486 return G_SUPPLICANT_SECURITY_FT_PSK;
2487 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2488 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2491 return G_SUPPLICANT_SECURITY_UNKNOWN;
2494 #if defined TIZEN_EXT
2495 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
2497 if (security == NULL)
2498 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
2500 if (g_str_equal(security, "FT") == TRUE)
2501 return G_SUPPLICANT_EAP_KEYMGMT_FT;
2502 else if (g_str_equal(security, "CCKM") == TRUE)
2503 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
2505 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
2509 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2511 const char *security;
2513 memset(ssid, 0, sizeof(*ssid));
2514 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2515 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2517 ssid->scan_ssid = 1;
2518 security = connman_network_get_string(network, "WiFi.Security");
2519 ssid->security = network_security(security);
2520 ssid->passphrase = connman_network_get_string(network,
2522 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2525 * If our private key password is unset,
2526 * we use the supplied passphrase. That is needed
2527 * for PEAP where 2 passphrases (identity and client
2528 * cert may have to be provided.
2530 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2531 connman_network_set_string(network,
2532 "WiFi.PrivateKeyPassphrase",
2534 /* We must have an identity for both PEAP and TLS */
2535 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2537 /* Use agent provided identity as a fallback */
2538 if (!ssid->identity || strlen(ssid->identity) == 0)
2539 ssid->identity = connman_network_get_string(network,
2540 "WiFi.AgentIdentity");
2542 ssid->anonymous_identity = connman_network_get_string(network,
2543 "WiFi.AnonymousIdentity");
2544 ssid->ca_cert_path = connman_network_get_string(network,
2546 ssid->subject_match = connman_network_get_string(network,
2547 "WiFi.SubjectMatch");
2548 ssid->altsubject_match = connman_network_get_string(network,
2549 "WiFi.AltSubjectMatch");
2550 ssid->domain_suffix_match = connman_network_get_string(network,
2551 "WiFi.DomainSuffixMatch");
2552 ssid->domain_match = connman_network_get_string(network,
2553 "WiFi.DomainMatch");
2554 ssid->client_cert_path = connman_network_get_string(network,
2555 "WiFi.ClientCertFile");
2556 ssid->private_key_path = connman_network_get_string(network,
2557 "WiFi.PrivateKeyFile");
2558 ssid->private_key_passphrase = connman_network_get_string(network,
2559 "WiFi.PrivateKeyPassphrase");
2560 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2562 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2563 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2565 #if defined TIZEN_EXT
2566 ssid->bssid = connman_network_get_bssid(network);
2568 ssid->eap_keymgmt = network_eap_keymgmt(
2569 connman_network_get_string(network, "WiFi.KeymgmtType"));
2570 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
2572 if(g_strcmp0(ssid->eap, "fast") == 0)
2573 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
2575 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
2576 ssid->bssid_for_connect_len = 6;
2577 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
2578 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
2579 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
2580 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
2581 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
2583 ssid->freq = connman_network_get_frequency(network);
2587 if (connman_setting_get_bool("BackgroundScanning"))
2588 ssid->bgscan = BGSCAN_DEFAULT;
2591 static int network_connect(struct connman_network *network)
2593 struct connman_device *device = connman_network_get_device(network);
2594 struct wifi_data *wifi;
2595 GSupplicantInterface *interface;
2596 GSupplicantSSID *ssid;
2598 DBG("network %p", network);
2603 wifi = connman_device_get_data(device);
2607 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2611 interface = wifi->interface;
2613 ssid_init(ssid, network);
2615 if (wifi->disconnecting) {
2616 wifi->pending_network = network;
2619 wifi->network = connman_network_ref(network);
2621 #if defined TIZEN_EXT
2622 wifi->scan_pending_network = NULL;
2625 return g_supplicant_interface_connect(interface, ssid,
2626 connect_callback, network);
2629 return -EINPROGRESS;
2632 static void disconnect_callback(int result, GSupplicantInterface *interface,
2635 #if defined TIZEN_EXT
2637 struct wifi_data *wifi;
2638 struct connman_network *network = user_data;
2640 DBG("network %p result %d", network, result);
2642 for (list = iface_list; list; list = list->next) {
2645 if (wifi->network == NULL && wifi->disconnecting == true)
2646 wifi->disconnecting = false;
2648 if (wifi->network == network)
2652 /* wifi_data may be invalid because wifi is already disabled */
2657 struct wifi_data *wifi = user_data;
2660 DBG("result %d supplicant interface %p wifi %p",
2661 result, interface, wifi);
2663 if (result == -ECONNABORTED) {
2664 DBG("wifi interface no longer available");
2668 if (wifi->network) {
2669 connman_network_set_connected(wifi->network, false);
2670 wifi->network = NULL;
2673 wifi->disconnecting = false;
2674 wifi->connected = false;
2676 if (wifi->pending_network) {
2677 network_connect(wifi->pending_network);
2678 wifi->pending_network = NULL;
2681 start_autoscan(wifi->device);
2684 static int network_disconnect(struct connman_network *network)
2686 struct connman_device *device = connman_network_get_device(network);
2687 struct wifi_data *wifi;
2689 #if defined TIZEN_EXT
2690 struct connman_service *service;
2693 DBG("network %p", network);
2695 wifi = connman_device_get_data(device);
2696 if (!wifi || !wifi->interface)
2699 #if defined TIZEN_EXT
2700 if (connman_network_get_associating(network) == true) {
2701 connman_network_clear_associating(network);
2702 connman_network_set_bool(network, "WiFi.UseWPS", false);
2704 service = connman_service_lookup_from_network(network);
2706 if (service != NULL &&
2707 (__connman_service_is_connected_state(service,
2708 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2709 __connman_service_is_connected_state(service,
2710 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2711 (connman_service_get_favorite(service) == false))
2712 __connman_service_set_passphrase(service, NULL);
2715 if (wifi->pending_network == network)
2716 wifi->pending_network = NULL;
2718 if (wifi->scan_pending_network == network)
2719 wifi->scan_pending_network = NULL;
2722 connman_network_set_associating(network, false);
2724 if (wifi->disconnecting)
2727 wifi->disconnecting = true;
2729 #if defined TIZEN_EXT
2730 err = g_supplicant_interface_disconnect(wifi->interface,
2731 disconnect_callback, network);
2733 err = g_supplicant_interface_disconnect(wifi->interface,
2734 disconnect_callback, wifi);
2738 wifi->disconnecting = false;
2743 static struct connman_network_driver network_driver = {
2745 .type = CONNMAN_NETWORK_TYPE_WIFI,
2746 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2747 .probe = network_probe,
2748 .remove = network_remove,
2749 .connect = network_connect,
2750 .disconnect = network_disconnect,
2753 static void interface_added(GSupplicantInterface *interface)
2755 const char *ifname = g_supplicant_interface_get_ifname(interface);
2756 const char *driver = g_supplicant_interface_get_driver(interface);
2757 struct wifi_data *wifi;
2759 wifi = g_supplicant_interface_get_data(interface);
2761 wifi = get_pending_wifi_data(ifname);
2765 wifi->interface = interface;
2766 g_supplicant_interface_set_data(interface, wifi);
2767 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2768 wifi->p2p_device = true;
2771 DBG("ifname %s driver %s wifi %p tethering %d",
2772 ifname, driver, wifi, wifi->tethering);
2774 if (!wifi->device) {
2775 connman_error("WiFi device not set");
2779 connman_device_set_powered(wifi->device, true);
2782 static bool is_idle(struct wifi_data *wifi)
2784 DBG("state %d", wifi->state);
2786 switch (wifi->state) {
2787 case G_SUPPLICANT_STATE_UNKNOWN:
2788 case G_SUPPLICANT_STATE_DISABLED:
2789 case G_SUPPLICANT_STATE_DISCONNECTED:
2790 case G_SUPPLICANT_STATE_INACTIVE:
2791 case G_SUPPLICANT_STATE_SCANNING:
2794 case G_SUPPLICANT_STATE_AUTHENTICATING:
2795 case G_SUPPLICANT_STATE_ASSOCIATING:
2796 case G_SUPPLICANT_STATE_ASSOCIATED:
2797 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2798 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2799 case G_SUPPLICANT_STATE_COMPLETED:
2806 static bool is_idle_wps(GSupplicantInterface *interface,
2807 struct wifi_data *wifi)
2809 /* First, let's check if WPS processing did not went wrong */
2810 if (g_supplicant_interface_get_wps_state(interface) ==
2811 G_SUPPLICANT_WPS_STATE_FAIL)
2814 /* Unlike normal connection, being associated while processing wps
2815 * actually means that we are idling. */
2816 switch (wifi->state) {
2817 case G_SUPPLICANT_STATE_UNKNOWN:
2818 case G_SUPPLICANT_STATE_DISABLED:
2819 case G_SUPPLICANT_STATE_DISCONNECTED:
2820 case G_SUPPLICANT_STATE_INACTIVE:
2821 case G_SUPPLICANT_STATE_SCANNING:
2822 case G_SUPPLICANT_STATE_ASSOCIATED:
2824 case G_SUPPLICANT_STATE_AUTHENTICATING:
2825 case G_SUPPLICANT_STATE_ASSOCIATING:
2826 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2827 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2828 case G_SUPPLICANT_STATE_COMPLETED:
2835 static bool handle_wps_completion(GSupplicantInterface *interface,
2836 struct connman_network *network,
2837 struct connman_device *device,
2838 struct wifi_data *wifi)
2842 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2844 const unsigned char *ssid, *wps_ssid;
2845 unsigned int ssid_len, wps_ssid_len;
2846 const char *wps_key;
2848 /* Checking if we got associated with requested
2850 ssid = connman_network_get_blob(network, "WiFi.SSID",
2853 wps_ssid = g_supplicant_interface_get_wps_ssid(
2854 interface, &wps_ssid_len);
2856 if (!wps_ssid || wps_ssid_len != ssid_len ||
2857 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2858 connman_network_set_associating(network, false);
2859 #if defined TIZEN_EXT
2860 g_supplicant_interface_disconnect(wifi->interface,
2861 disconnect_callback, wifi->network);
2863 connman_network_set_bool(network, "WiFi.UseWPS", false);
2864 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2866 g_supplicant_interface_disconnect(wifi->interface,
2867 disconnect_callback, wifi);
2872 wps_key = g_supplicant_interface_get_wps_key(interface);
2873 #if defined TIZEN_EXT
2874 /* Check the passphrase and encrypt it
2877 gchar *passphrase = g_strdup(wps_key);
2879 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2881 if (check_passphrase_ext(network, passphrase) < 0) {
2882 DBG("[WPS] Invalid passphrase");
2887 ret = send_encryption_request(passphrase, network);
2892 DBG("[WPS] Encryption request succeeded");
2894 DBG("[WPS] Encryption request failed %d", ret);
2897 connman_network_set_string(network, "WiFi.Passphrase",
2900 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2907 static bool handle_assoc_status_code(GSupplicantInterface *interface,
2908 struct wifi_data *wifi)
2910 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
2911 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
2912 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
2913 wifi->load_shaping_retries ++;
2916 wifi->load_shaping_retries = 0;
2920 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2921 struct connman_network *network,
2922 struct wifi_data *wifi)
2924 #if defined TIZEN_EXT
2925 const char *security;
2926 struct connman_service *service;
2928 if (wifi->connected)
2931 security = connman_network_get_string(network, "WiFi.Security");
2933 if (security && g_str_equal(security, "ieee8021x") == true &&
2934 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2936 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2941 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2944 struct connman_service *service;
2946 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2949 if (wifi->connected)
2953 service = connman_service_lookup_from_network(network);
2959 if (connman_service_get_favorite(service)) {
2960 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2965 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2970 #if defined TIZEN_EXT
2971 static bool handle_wifi_assoc_retry(struct connman_network *network,
2972 struct wifi_data *wifi)
2974 const char *security;
2976 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2977 connman_network_get_connecting(network) != true) {
2978 wifi->assoc_retry_count = 0;
2982 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2983 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2984 wifi->assoc_retry_count = 0;
2988 security = connman_network_get_string(network, "WiFi.Security");
2989 if (security && g_str_equal(security, "ieee8021x") == true &&
2990 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2991 wifi->assoc_retry_count = 0;
2995 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2996 wifi->assoc_retry_count = 0;
2998 /* Honestly it's not an invalid-key error,
2999 * however QA team recommends that the invalid-key error
3000 * might be better to display for user experience.
3002 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3011 static void interface_state(GSupplicantInterface *interface)
3013 struct connman_network *network;
3014 struct connman_device *device;
3015 struct wifi_data *wifi;
3016 GSupplicantState state = g_supplicant_interface_get_state(interface);
3020 wifi = g_supplicant_interface_get_data(interface);
3022 DBG("wifi %p interface state %d", wifi, state);
3027 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3028 if (wifi->tethering_param) {
3029 g_free(wifi->tethering_param->ssid);
3030 g_free(wifi->tethering_param);
3031 wifi->tethering_param = NULL;
3035 device = wifi->device;
3039 if (g_supplicant_interface_get_ready(interface) &&
3040 !wifi->interface_ready) {
3041 wifi->interface_ready = true;
3042 finalize_interface_creation(wifi);
3045 network = wifi->network;
3050 case G_SUPPLICANT_STATE_SCANNING:
3051 if (wifi->connected)
3052 connman_network_set_connected(network, false);
3056 case G_SUPPLICANT_STATE_AUTHENTICATING:
3057 case G_SUPPLICANT_STATE_ASSOCIATING:
3058 #if defined TIZEN_EXT
3059 reset_autoscan(device);
3061 stop_autoscan(device);
3064 if (!wifi->connected)
3065 connman_network_set_associating(network, true);
3069 case G_SUPPLICANT_STATE_COMPLETED:
3070 #if defined TIZEN_EXT
3071 /* though it should be already reset: */
3072 reset_autoscan(device);
3074 wifi->assoc_retry_count = 0;
3076 wifi->scan_pending_network = NULL;
3078 /* should be cleared scanning flag */
3079 bool scanning = connman_device_get_scanning(device);
3081 connman_device_set_scanning(device,
3082 CONNMAN_SERVICE_TYPE_WIFI, false);
3083 connman_device_unref(device);
3086 /* though it should be already stopped: */
3087 stop_autoscan(device);
3090 if (!handle_wps_completion(interface, network, device, wifi))
3093 connman_network_set_connected(network, true);
3095 wifi->disconnect_code = 0;
3096 wifi->assoc_code = 0;
3097 wifi->load_shaping_retries = 0;
3100 case G_SUPPLICANT_STATE_DISCONNECTED:
3102 * If we're in one of the idle modes, we have
3103 * not started association yet and thus setting
3104 * those ones to FALSE could cancel an association
3107 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3109 if (is_idle_wps(interface, wifi))
3115 if (handle_assoc_status_code(interface, wifi))
3118 /* If previous state was 4way-handshake, then
3119 * it's either: psk was incorrect and thus we retry
3120 * or if we reach the maximum retries we declare the
3122 if (handle_4way_handshake_failure(interface,
3126 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3127 switch (wifi->disconnect_code) {
3128 case 1: /* Unspecified reason */
3129 /* Let's assume it's because we got blocked */
3131 case 6: /* Class 2 frame received from nonauthenticated STA */
3132 connman_network_set_error(network,
3133 CONNMAN_NETWORK_ERROR_BLOCKED);
3140 #if defined TIZEN_EXT
3141 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3142 * Retry association until its retry count is expired */
3143 if (handle_wifi_assoc_retry(network, wifi) == true) {
3144 throw_wifi_scan(wifi->device, scan_callback);
3145 wifi->scan_pending_network = wifi->network;
3149 if(wifi->disconnect_code > 0){
3150 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3151 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3155 connman_network_set_connected(network, false);
3156 connman_network_set_associating(network, false);
3157 wifi->disconnecting = false;
3159 start_autoscan(device);
3163 case G_SUPPLICANT_STATE_INACTIVE:
3164 #if defined TIZEN_EXT
3165 if (handle_wps_completion(interface, network, device, wifi) == false)
3168 connman_network_set_associating(network, false);
3169 start_autoscan(device);
3173 case G_SUPPLICANT_STATE_UNKNOWN:
3174 case G_SUPPLICANT_STATE_DISABLED:
3175 case G_SUPPLICANT_STATE_ASSOCIATED:
3176 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3177 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3181 old_connected = wifi->connected;
3182 wifi->state = state;
3184 /* Saving wpa_s state policy:
3185 * If connected and if the state changes are roaming related:
3186 * --> We stay connected
3188 * --> We are connected
3190 * --> We are not connected
3193 case G_SUPPLICANT_STATE_AUTHENTICATING:
3194 case G_SUPPLICANT_STATE_ASSOCIATING:
3195 case G_SUPPLICANT_STATE_ASSOCIATED:
3196 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3197 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3198 if (wifi->connected)
3199 connman_warn("Probably roaming right now!"
3200 " Staying connected...");
3202 case G_SUPPLICANT_STATE_SCANNING:
3203 wifi->connected = false;
3206 start_autoscan(device);
3208 case G_SUPPLICANT_STATE_COMPLETED:
3209 wifi->connected = true;
3212 wifi->connected = false;
3219 static void interface_removed(GSupplicantInterface *interface)
3221 const char *ifname = g_supplicant_interface_get_ifname(interface);
3222 struct wifi_data *wifi;
3224 DBG("ifname %s", ifname);
3226 wifi = g_supplicant_interface_get_data(interface);
3229 wifi->interface = NULL;
3231 if (wifi && wifi->tethering)
3234 if (!wifi || !wifi->device) {
3235 DBG("wifi interface already removed");
3239 connman_device_set_powered(wifi->device, false);
3241 check_p2p_technology();
3244 static void set_device_type(const char *type, char dev_type[17])
3246 const char *oui = "0050F204";
3247 const char *category = "0001";
3248 const char *sub_category = "0000";
3250 if (!g_strcmp0(type, "handset")) {
3252 sub_category = "0005";
3253 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
3254 sub_category = "0001";
3255 else if (!g_strcmp0(type, "server"))
3256 sub_category = "0002";
3257 else if (!g_strcmp0(type, "laptop"))
3258 sub_category = "0005";
3259 else if (!g_strcmp0(type, "desktop"))
3260 sub_category = "0006";
3261 else if (!g_strcmp0(type, "tablet"))
3262 sub_category = "0009";
3263 else if (!g_strcmp0(type, "watch"))
3266 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
3269 static void p2p_support(GSupplicantInterface *interface)
3271 char dev_type[17] = {};
3272 const char *hostname;
3279 if (!g_supplicant_interface_has_p2p(interface))
3282 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3283 DBG("Could not register P2P technology driver");
3287 hostname = connman_utsname_get_hostname();
3289 hostname = "ConnMan";
3291 set_device_type(connman_machine_get_type(), dev_type);
3292 g_supplicant_interface_set_p2p_device_config(interface,
3293 hostname, dev_type);
3294 connman_peer_driver_register(&peer_driver);
3297 static void scan_started(GSupplicantInterface *interface)
3302 static void scan_finished(GSupplicantInterface *interface)
3304 #if defined TIZEN_EXT
3305 struct wifi_data *wifi;
3306 bool is_associating = false;
3307 static bool is_scanning = true;
3312 #if defined TIZEN_EXT
3313 wifi = g_supplicant_interface_get_data(interface);
3314 if (wifi && wifi->scan_pending_network) {
3315 network_connect(wifi->scan_pending_network);
3316 wifi->scan_pending_network = NULL;
3319 //service state - associating
3320 if(!wifi || !wifi->network)
3323 is_associating = connman_network_get_associating(wifi->network);
3324 if(is_associating && is_scanning){
3325 is_scanning = false;
3326 DBG("send scan for connecting");
3327 throw_wifi_scan(wifi->device, scan_callback);
3338 static void ap_create_fail(GSupplicantInterface *interface)
3340 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3343 if ((wifi->tethering) && (wifi->tethering_param)) {
3344 DBG("%s create AP fail \n",
3345 g_supplicant_interface_get_ifname(wifi->interface));
3347 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
3348 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
3349 wifi->tethering = false;
3351 ret = tech_set_tethering(wifi->tethering_param->technology,
3352 wifi->tethering_param->ssid->ssid,
3353 wifi->tethering_param->ssid->passphrase,
3354 wifi->bridge, true);
3356 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
3357 connman_technology_tethering_notify(wifi_technology,false);
3360 g_free(wifi->tethering_param->ssid);
3361 g_free(wifi->tethering_param);
3362 wifi->tethering_param = NULL;
3368 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3370 unsigned char strength;
3372 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3374 #if !defined TIZEN_EXT
3381 static void network_added(GSupplicantNetwork *supplicant_network)
3383 struct connman_network *network;
3384 GSupplicantInterface *interface;
3385 struct wifi_data *wifi;
3386 const char *name, *identifier, *security, *group, *mode;
3387 const unsigned char *ssid;
3388 unsigned int ssid_len;
3392 bool wps_advertizing;
3394 #if defined TIZEN_EXT
3395 GSList *vsie_list = NULL;
3396 const unsigned char *country_code;
3399 mode = g_supplicant_network_get_mode(supplicant_network);
3400 identifier = g_supplicant_network_get_identifier(supplicant_network);
3402 DBG("%s", identifier);
3404 if (!g_strcmp0(mode, "adhoc"))
3407 interface = g_supplicant_network_get_interface(supplicant_network);
3408 wifi = g_supplicant_interface_get_data(interface);
3409 name = g_supplicant_network_get_name(supplicant_network);
3410 security = g_supplicant_network_get_security(supplicant_network);
3411 group = g_supplicant_network_get_identifier(supplicant_network);
3412 wps = g_supplicant_network_get_wps(supplicant_network);
3413 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3414 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3415 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3416 supplicant_network);
3421 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3423 network = connman_device_get_network(wifi->device, identifier);
3426 network = connman_network_create(identifier,
3427 CONNMAN_NETWORK_TYPE_WIFI);
3431 connman_network_set_index(network, wifi->index);
3433 if (connman_device_add_network(wifi->device, network) < 0) {
3434 connman_network_unref(network);
3438 wifi->networks = g_slist_prepend(wifi->networks, network);
3441 if (name && name[0] != '\0')
3442 connman_network_set_name(network, name);
3444 connman_network_set_blob(network, "WiFi.SSID",
3446 #if defined TIZEN_EXT
3447 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
3449 connman_network_set_vsie_list(network, vsie_list);
3451 DBG("vsie_list is NULL");
3452 country_code = g_supplicant_network_get_countrycode(supplicant_network);
3453 connman_network_set_countrycode(network, country_code);
3455 connman_network_set_string(network, "WiFi.Security", security);
3456 connman_network_set_strength(network,
3457 calculate_strength(supplicant_network));
3458 connman_network_set_bool(network, "WiFi.WPS", wps);
3461 /* Is AP advertizing for WPS association?
3462 * If so, we decide to use WPS by default */
3463 if (wps_ready && wps_pbc &&
3465 #if !defined TIZEN_EXT
3466 connman_network_set_bool(network, "WiFi.UseWPS", true);
3468 DBG("wps is activating by ap but ignore it.");
3473 connman_network_set_frequency(network,
3474 g_supplicant_network_get_frequency(supplicant_network));
3475 #if defined TIZEN_EXT
3476 connman_network_set_bssid(network,
3477 g_supplicant_network_get_bssid(supplicant_network));
3478 connman_network_set_maxrate(network,
3479 g_supplicant_network_get_maxrate(supplicant_network));
3480 connman_network_set_enc_mode(network,
3481 g_supplicant_network_get_enc_mode(supplicant_network));
3482 connman_network_set_rsn_mode(network,
3483 g_supplicant_network_get_rsn_mode(supplicant_network));
3484 connman_network_set_keymgmt(network,
3485 g_supplicant_network_get_keymgmt(supplicant_network));
3486 connman_network_set_bool(network, "WiFi.HS20AP",
3487 g_supplicant_network_is_hs20AP(supplicant_network));
3488 connman_network_set_bssid_list(network,
3489 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
3491 connman_network_set_available(network, true);
3492 connman_network_set_string(network, "WiFi.Mode", mode);
3494 #if defined TIZEN_EXT
3499 connman_network_set_group(network, group);
3501 #if defined TIZEN_EXT
3502 if (wifi_first_scan == true)
3503 found_with_first_scan = true;
3506 if (wifi->hidden && ssid) {
3507 #if defined TIZEN_EXT
3508 if (network_security(wifi->hidden->security) ==
3509 network_security(security) &&
3511 if (!g_strcmp0(wifi->hidden->security, security) &&
3513 wifi->hidden->ssid_len == ssid_len &&
3514 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3515 connman_network_connect_hidden(network,
3516 wifi->hidden->identity,
3517 wifi->hidden->passphrase,
3518 wifi->hidden->user_data);
3519 wifi->hidden->user_data = NULL;
3520 hidden_free(wifi->hidden);
3521 wifi->hidden = NULL;
3526 static void network_removed(GSupplicantNetwork *network)
3528 GSupplicantInterface *interface;
3529 struct wifi_data *wifi;
3530 const char *name, *identifier;
3531 struct connman_network *connman_network;
3533 interface = g_supplicant_network_get_interface(network);
3534 wifi = g_supplicant_interface_get_data(interface);
3535 identifier = g_supplicant_network_get_identifier(network);
3536 name = g_supplicant_network_get_name(network);
3538 DBG("name %s", name);
3543 connman_network = connman_device_get_network(wifi->device, identifier);
3544 if (!connman_network)
3547 #if defined TIZEN_EXT
3548 if (connman_network == wifi->scan_pending_network)
3549 wifi->scan_pending_network = NULL;
3551 if (connman_network == wifi->pending_network)
3552 wifi->pending_network = NULL;
3554 if(connman_network_get_connecting(connman_network) == true){
3555 connman_network_set_connected(connman_network, false);
3559 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3561 connman_device_remove_network(wifi->device, connman_network);
3562 connman_network_unref(connman_network);
3565 static void network_changed(GSupplicantNetwork *network, const char *property)
3567 GSupplicantInterface *interface;
3568 struct wifi_data *wifi;
3569 const char *name, *identifier;
3570 struct connman_network *connman_network;
3572 #if defined TIZEN_EXT
3573 const unsigned char *bssid;
3574 unsigned int maxrate;
3577 const unsigned char *country_code;
3581 interface = g_supplicant_network_get_interface(network);
3582 wifi = g_supplicant_interface_get_data(interface);
3583 identifier = g_supplicant_network_get_identifier(network);
3584 name = g_supplicant_network_get_name(network);
3586 DBG("name %s", name);
3591 connman_network = connman_device_get_network(wifi->device, identifier);
3592 if (!connman_network)
3595 if (g_str_equal(property, "Signal")) {
3596 connman_network_set_strength(connman_network,
3597 calculate_strength(network));
3598 connman_network_update(connman_network);
3601 #if defined TIZEN_EXT
3602 bssid = g_supplicant_network_get_bssid(network);
3603 maxrate = g_supplicant_network_get_maxrate(network);
3604 frequency = g_supplicant_network_get_frequency(network);
3605 wps = g_supplicant_network_get_wps(network);
3607 connman_network_set_bssid(connman_network, bssid);
3608 connman_network_set_maxrate(connman_network, maxrate);
3609 connman_network_set_frequency(connman_network, frequency);
3610 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3611 country_code = g_supplicant_network_get_countrycode(network);
3612 connman_network_set_countrycode(connman_network, country_code);
3613 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
3614 connman_network_set_bssid_list(connman_network, bssid_list);
3618 static void network_associated(GSupplicantNetwork *network)
3620 GSupplicantInterface *interface;
3621 struct wifi_data *wifi;
3622 struct connman_network *connman_network;
3623 const char *identifier;
3627 interface = g_supplicant_network_get_interface(network);
3631 wifi = g_supplicant_interface_get_data(interface);
3635 identifier = g_supplicant_network_get_identifier(network);
3637 connman_network = connman_device_get_network(wifi->device, identifier);
3638 if (!connman_network)
3641 if (wifi->network) {
3642 if (wifi->network == connman_network)
3646 * This should never happen, we got associated with
3647 * a network different than the one we were expecting.
3649 DBG("Associated to %p while expecting %p",
3650 connman_network, wifi->network);
3652 connman_network_set_associating(wifi->network, false);
3655 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
3657 wifi->network = connman_network_ref(connman_network);
3661 * Interface state changes callback (interface_state) is always
3662 * called before network_associated callback thus we need to call
3663 * interface_state again in order to process the new state now that
3664 * we have the network properly set.
3666 interface_state(interface);
3669 static void apply_peer_services(GSupplicantPeer *peer,
3670 struct connman_peer *connman_peer)
3672 const unsigned char *data;
3677 connman_peer_reset_services(connman_peer);
3679 data = g_supplicant_peer_get_widi_ies(peer, &length);
3681 connman_peer_add_service(connman_peer,
3682 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3686 static void add_station(const char *mac)
3688 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3692 static void remove_station(const char *mac)
3694 connman_technology_tethering_remove_station(mac);
3697 static void peer_found(GSupplicantPeer *peer)
3699 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3700 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3701 struct connman_peer *connman_peer;
3702 const char *identifier, *name;
3704 #if defined TIZEN_EXT
3708 identifier = g_supplicant_peer_get_identifier(peer);
3709 name = g_supplicant_peer_get_name(peer);
3711 DBG("ident: %s", identifier);
3713 connman_peer = connman_peer_get(wifi->device, identifier);
3717 connman_peer = connman_peer_create(identifier);
3718 connman_peer_set_name(connman_peer, name);
3719 connman_peer_set_device(connman_peer, wifi->device);
3720 apply_peer_services(peer, connman_peer);
3722 ret = connman_peer_register(connman_peer);
3723 if (ret < 0 && ret != -EALREADY)
3724 connman_peer_unref(connman_peer);
3726 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
3729 static void peer_lost(GSupplicantPeer *peer)
3731 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3732 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3733 struct connman_peer *connman_peer;
3734 const char *identifier;
3739 identifier = g_supplicant_peer_get_identifier(peer);
3741 DBG("ident: %s", identifier);
3743 connman_peer = connman_peer_get(wifi->device, identifier);
3745 if (wifi->p2p_connecting &&
3746 wifi->pending_peer == connman_peer) {
3747 peer_connect_timeout(wifi);
3749 connman_peer_unregister(connman_peer);
3750 connman_peer_unref(connman_peer);
3753 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
3756 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3758 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3759 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3760 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3761 struct connman_peer *connman_peer;
3762 const char *identifier;
3764 identifier = g_supplicant_peer_get_identifier(peer);
3766 DBG("ident: %s", identifier);
3771 connman_peer = connman_peer_get(wifi->device, identifier);
3776 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3777 apply_peer_services(peer, connman_peer);
3778 connman_peer_services_changed(connman_peer);
3780 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3781 if (!g_supplicant_peer_is_in_a_group(peer))
3782 p_state = CONNMAN_PEER_STATE_IDLE;
3784 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3786 case G_SUPPLICANT_PEER_GROUP_STARTED:
3788 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3789 p_state = CONNMAN_PEER_STATE_IDLE;
3791 case G_SUPPLICANT_PEER_GROUP_JOINED:
3792 connman_peer_set_iface_address(connman_peer,
3793 g_supplicant_peer_get_iface_address(peer));
3795 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3796 p_state = CONNMAN_PEER_STATE_IDLE;
3798 case G_SUPPLICANT_PEER_GROUP_FAILED:
3799 if (g_supplicant_peer_has_requested_connection(peer))
3800 p_state = CONNMAN_PEER_STATE_IDLE;
3802 p_state = CONNMAN_PEER_STATE_FAILURE;
3806 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3807 p_state == CONNMAN_PEER_STATE_FAILURE) {
3808 if (wifi->p2p_connecting
3809 && connman_peer == wifi->pending_peer)
3810 peer_cancel_timeout(wifi);
3812 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3815 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3818 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3819 GSupplicantInterface *g_iface;
3820 struct wifi_data *g_wifi;
3822 g_iface = g_supplicant_peer_get_group_interface(peer);
3826 g_wifi = g_supplicant_interface_get_data(g_iface);
3830 connman_peer_set_as_master(connman_peer,
3831 !g_supplicant_peer_is_client(peer));
3832 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3835 * If wpa_supplicant didn't create a dedicated p2p-group
3836 * interface then mark this interface as p2p_device to avoid
3837 * scan and auto-scan are launched on it while P2P is connected.
3839 if (!g_list_find(p2p_iface_list, g_wifi))
3840 wifi->p2p_device = true;
3843 connman_peer_set_state(connman_peer, p_state);
3846 static void peer_request(GSupplicantPeer *peer)
3848 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3849 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3850 struct connman_peer *connman_peer;
3851 const char *identifier;
3853 #if defined TIZEN_EXT
3858 identifier = g_supplicant_peer_get_identifier(peer);
3860 DBG("ident: %s", identifier);
3862 connman_peer = connman_peer_get(wifi->device, identifier);
3866 connman_peer_request_connection(connman_peer);
3869 #if defined TIZEN_EXT
3870 static void system_power_off(void)
3873 struct wifi_data *wifi;
3874 struct connman_service *service;
3875 struct connman_ipconfig *ipconfig_ipv4;
3877 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3878 for (list = iface_list; list; list = list->next) {
3881 if (wifi->network != NULL) {
3882 service = connman_service_lookup_from_network(wifi->network);
3883 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3884 __connman_dhcp_stop(ipconfig_ipv4);
3890 static void network_merged(GSupplicantNetwork *network)
3892 GSupplicantInterface *interface;
3893 GSupplicantState state;
3894 struct wifi_data *wifi;
3895 const char *identifier;
3896 struct connman_network *connman_network;
3900 interface = g_supplicant_network_get_interface(network);
3904 state = g_supplicant_interface_get_state(interface);
3905 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3908 wifi = g_supplicant_interface_get_data(interface);
3912 identifier = g_supplicant_network_get_identifier(network);
3914 connman_network = connman_device_get_network(wifi->device, identifier);
3915 if (!connman_network)
3918 DBG("merged identifier %s", identifier);
3920 if (wifi->connected == FALSE) {
3922 case G_SUPPLICANT_STATE_AUTHENTICATING:
3923 case G_SUPPLICANT_STATE_ASSOCIATING:
3924 case G_SUPPLICANT_STATE_ASSOCIATED:
3925 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3926 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3927 connman_network_set_associating(connman_network, TRUE);
3929 case G_SUPPLICANT_STATE_COMPLETED:
3930 connman_network_set_connected(connman_network, TRUE);
3933 DBG("Not handled the state : %d", state);
3938 ishs20AP = g_supplicant_network_is_hs20AP(network);
3941 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3942 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3943 connman_network_set_string(connman_network, "WiFi.EAP",
3945 connman_network_set_string(connman_network, "WiFi.Identity",
3946 g_supplicant_network_get_identity(network));
3947 connman_network_set_string(connman_network, "WiFi.Phase2",
3948 g_supplicant_network_get_phase2(network));
3953 wifi->network = connman_network;
3956 static void assoc_failed(void *user_data)
3958 struct connman_network *network = user_data;
3959 connman_network_set_associating(network, false);
3963 static void debug(const char *str)
3965 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3966 connman_debug("%s", str);
3969 static void disconnect_reasoncode(GSupplicantInterface *interface,
3972 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3975 wifi->disconnect_code = reasoncode;
3979 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
3981 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3984 wifi->assoc_code = status_code;
3988 static const GSupplicantCallbacks callbacks = {
3989 .system_ready = system_ready,
3990 .system_killed = system_killed,
3991 .interface_added = interface_added,
3992 .interface_state = interface_state,
3993 .interface_removed = interface_removed,
3994 .p2p_support = p2p_support,
3995 .scan_started = scan_started,
3996 .scan_finished = scan_finished,
3997 .ap_create_fail = ap_create_fail,
3998 .network_added = network_added,
3999 .network_removed = network_removed,
4000 .network_changed = network_changed,
4001 .network_associated = network_associated,
4002 .add_station = add_station,
4003 .remove_station = remove_station,
4004 .peer_found = peer_found,
4005 .peer_lost = peer_lost,
4006 .peer_changed = peer_changed,
4007 .peer_request = peer_request,
4008 #if defined TIZEN_EXT
4009 .system_power_off = system_power_off,
4010 .network_merged = network_merged,
4011 .assoc_failed = assoc_failed,
4014 .disconnect_reasoncode = disconnect_reasoncode,
4015 .assoc_status_code = assoc_status_code,
4019 static int tech_probe(struct connman_technology *technology)
4021 wifi_technology = technology;
4026 static void tech_remove(struct connman_technology *technology)
4028 wifi_technology = NULL;
4031 static GSupplicantSSID *ssid_ap_init(const char *ssid,
4032 const char *passphrase)
4034 GSupplicantSSID *ap;
4036 ap = g_try_malloc0(sizeof(GSupplicantSSID));
4040 ap->mode = G_SUPPLICANT_MODE_MASTER;
4042 ap->ssid_len = strlen(ssid);
4046 if (!passphrase || strlen(passphrase) == 0) {
4047 ap->security = G_SUPPLICANT_SECURITY_NONE;
4048 ap->passphrase = NULL;
4050 ap->security = G_SUPPLICANT_SECURITY_PSK;
4051 ap->protocol = G_SUPPLICANT_PROTO_RSN;
4052 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
4053 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
4054 ap->passphrase = passphrase;
4060 static void ap_start_callback(int result, GSupplicantInterface *interface,
4063 struct wifi_tethering_info *info = user_data;
4065 DBG("result %d index %d bridge %s",
4066 result, info->wifi->index, info->wifi->bridge);
4068 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4069 connman_inet_remove_from_bridge(info->wifi->index,
4070 info->wifi->bridge);
4072 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4073 connman_technology_tethering_notify(info->technology, false);
4074 g_free(info->wifi->tethering_param->ssid);
4075 g_free(info->wifi->tethering_param);
4076 info->wifi->tethering_param = NULL;
4080 g_free(info->ifname);
4084 static void ap_create_callback(int result,
4085 GSupplicantInterface *interface,
4088 struct wifi_tethering_info *info = user_data;
4090 DBG("result %d ifname %s", result,
4091 g_supplicant_interface_get_ifname(interface));
4093 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4094 connman_inet_remove_from_bridge(info->wifi->index,
4095 info->wifi->bridge);
4097 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4098 connman_technology_tethering_notify(info->technology, false);
4099 g_free(info->wifi->tethering_param->ssid);
4100 g_free(info->wifi->tethering_param);
4101 info->wifi->tethering_param = NULL;
4105 g_free(info->ifname);
4111 info->wifi->interface = interface;
4112 g_supplicant_interface_set_data(interface, info->wifi);
4114 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
4115 connman_error("Failed to set interface ap_scan property");
4117 g_supplicant_interface_connect(interface, info->ssid,
4118 ap_start_callback, info);
4121 static void sta_remove_callback(int result,
4122 GSupplicantInterface *interface,
4125 struct wifi_tethering_info *info = user_data;
4126 const char *driver = connman_option_get_string("wifi");
4128 DBG("ifname %s result %d ", info->ifname, result);
4130 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4131 info->wifi->tethering = false;
4132 connman_technology_tethering_notify(info->technology, false);
4134 g_free(info->ifname);
4138 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4139 g_free(info->wifi->tethering_param->ssid);
4140 g_free(info->wifi->tethering_param);
4141 info->wifi->tethering_param = NULL;
4146 info->wifi->interface = NULL;
4148 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
4153 static int enable_wifi_tethering(struct connman_technology *technology,
4154 const char *bridge, const char *identifier,
4155 const char *passphrase, bool available)
4158 GSupplicantInterface *interface;
4159 struct wifi_data *wifi;
4160 struct wifi_tethering_info *info;
4165 for (list = iface_list; list; list = list->next) {
4168 DBG("wifi %p network %p pending_network %p", wifi,
4169 wifi->network, wifi->pending_network);
4171 interface = wifi->interface;
4176 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
4179 ifname = g_supplicant_interface_get_ifname(wifi->interface);
4181 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
4182 DBG("%s does not support AP mode (detected)", ifname);
4186 mode = g_supplicant_interface_get_mode(interface);
4187 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
4188 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4189 DBG("%s does not support AP mode (capability)", ifname);
4193 if (wifi->network && available)
4196 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
4200 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
4201 if (!wifi->tethering_param) {
4207 info->technology = technology;
4208 info->wifi->bridge = bridge;
4209 info->ssid = ssid_ap_init(identifier, passphrase);
4213 info->ifname = g_strdup(ifname);
4217 wifi->tethering_param->technology = technology;
4218 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
4219 if (!wifi->tethering_param->ssid)
4222 info->wifi->tethering = true;
4223 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
4225 berr = connman_technology_tethering_notify(technology, true);
4229 err = g_supplicant_interface_remove(interface,
4230 sta_remove_callback,
4233 DBG("tethering wifi %p ifname %s", wifi, ifname);
4238 g_free(info->ifname);
4241 g_free(wifi->tethering_param);
4242 wifi->tethering_param = NULL;
4245 * Remove bridge if it was correctly created but remove
4246 * operation failed. Instead, if bridge creation failed then
4247 * break out and do not try again on another interface,
4248 * bridge set-up does not depend on it.
4251 connman_technology_tethering_notify(technology, false);
4259 static int tech_set_tethering(struct connman_technology *technology,
4260 const char *identifier, const char *passphrase,
4261 const char *bridge, bool enabled)
4264 struct wifi_data *wifi;
4270 for (list = iface_list; list; list = list->next) {
4273 if (wifi->tethering) {
4274 wifi->tethering = false;
4276 connman_inet_remove_from_bridge(wifi->index,
4278 wifi->bridged = false;
4282 connman_technology_tethering_notify(technology, false);
4287 DBG("trying tethering for available devices");
4288 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
4292 DBG("trying tethering for any device");
4293 err = enable_wifi_tethering(technology, bridge, identifier,
4300 static void regdom_callback(int result, const char *alpha2, void *user_data)
4304 if (!wifi_technology)
4310 connman_technology_regdom_notify(wifi_technology, alpha2);
4313 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
4315 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
4318 static struct connman_technology_driver tech_driver = {
4320 .type = CONNMAN_SERVICE_TYPE_WIFI,
4321 .probe = tech_probe,
4322 .remove = tech_remove,
4323 .set_tethering = tech_set_tethering,
4324 .set_regdom = tech_set_regdom,
4327 static int wifi_init(void)
4331 err = connman_network_driver_register(&network_driver);
4335 err = g_supplicant_register(&callbacks);
4337 connman_network_driver_unregister(&network_driver);
4341 err = connman_technology_driver_register(&tech_driver);
4343 g_supplicant_unregister(&callbacks);
4344 connman_network_driver_unregister(&network_driver);
4351 static void wifi_exit(void)
4355 connman_technology_driver_unregister(&tech_driver);
4357 g_supplicant_unregister(&callbacks);
4359 connman_network_driver_unregister(&network_driver);
4362 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
4363 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)