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;
2512 #if defined TIZEN_EXT
2513 const void *ssid_data;
2516 memset(ssid, 0, sizeof(*ssid));
2517 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2518 #if defined TIZEN_EXT
2519 ssid_data = connman_network_get_blob(network, "WiFi.SSID",
2521 ssid->ssid = g_try_malloc0(ssid->ssid_len);
2522 memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
2524 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2527 ssid->scan_ssid = 1;
2528 security = connman_network_get_string(network, "WiFi.Security");
2529 ssid->security = network_security(security);
2530 ssid->passphrase = connman_network_get_string(network,
2532 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2535 * If our private key password is unset,
2536 * we use the supplied passphrase. That is needed
2537 * for PEAP where 2 passphrases (identity and client
2538 * cert may have to be provided.
2540 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2541 connman_network_set_string(network,
2542 "WiFi.PrivateKeyPassphrase",
2544 /* We must have an identity for both PEAP and TLS */
2545 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2547 /* Use agent provided identity as a fallback */
2548 if (!ssid->identity || strlen(ssid->identity) == 0)
2549 ssid->identity = connman_network_get_string(network,
2550 "WiFi.AgentIdentity");
2552 ssid->anonymous_identity = connman_network_get_string(network,
2553 "WiFi.AnonymousIdentity");
2554 ssid->ca_cert_path = connman_network_get_string(network,
2556 ssid->subject_match = connman_network_get_string(network,
2557 "WiFi.SubjectMatch");
2558 ssid->altsubject_match = connman_network_get_string(network,
2559 "WiFi.AltSubjectMatch");
2560 ssid->domain_suffix_match = connman_network_get_string(network,
2561 "WiFi.DomainSuffixMatch");
2562 ssid->domain_match = connman_network_get_string(network,
2563 "WiFi.DomainMatch");
2564 ssid->client_cert_path = connman_network_get_string(network,
2565 "WiFi.ClientCertFile");
2566 ssid->private_key_path = connman_network_get_string(network,
2567 "WiFi.PrivateKeyFile");
2568 ssid->private_key_passphrase = connman_network_get_string(network,
2569 "WiFi.PrivateKeyPassphrase");
2570 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2572 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2573 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2575 #if defined TIZEN_EXT
2576 ssid->bssid = connman_network_get_bssid(network);
2578 ssid->eap_keymgmt = network_eap_keymgmt(
2579 connman_network_get_string(network, "WiFi.KeymgmtType"));
2580 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
2582 if(g_strcmp0(ssid->eap, "fast") == 0)
2583 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
2585 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
2586 ssid->bssid_for_connect_len = 6;
2587 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
2588 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
2589 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
2590 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
2591 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
2593 ssid->freq = connman_network_get_frequency(network);
2597 if (connman_setting_get_bool("BackgroundScanning"))
2598 ssid->bgscan = BGSCAN_DEFAULT;
2601 static int network_connect(struct connman_network *network)
2603 struct connman_device *device = connman_network_get_device(network);
2604 struct wifi_data *wifi;
2605 GSupplicantInterface *interface;
2606 GSupplicantSSID *ssid;
2608 DBG("network %p", network);
2613 wifi = connman_device_get_data(device);
2617 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2621 interface = wifi->interface;
2623 ssid_init(ssid, network);
2625 if (wifi->disconnecting) {
2626 wifi->pending_network = network;
2627 #if defined TIZEN_EXT
2632 wifi->network = connman_network_ref(network);
2634 #if defined TIZEN_EXT
2635 wifi->scan_pending_network = NULL;
2638 return g_supplicant_interface_connect(interface, ssid,
2639 connect_callback, network);
2642 return -EINPROGRESS;
2645 static void disconnect_callback(int result, GSupplicantInterface *interface,
2648 #if defined TIZEN_EXT
2650 struct wifi_data *wifi;
2651 struct connman_network *network = user_data;
2653 DBG("network %p result %d", network, result);
2655 for (list = iface_list; list; list = list->next) {
2658 if (wifi->network == NULL && wifi->disconnecting == true)
2659 wifi->disconnecting = false;
2661 if (wifi->network == network)
2665 /* wifi_data may be invalid because wifi is already disabled */
2670 struct wifi_data *wifi = user_data;
2673 DBG("result %d supplicant interface %p wifi %p",
2674 result, interface, wifi);
2676 if (result == -ECONNABORTED) {
2677 DBG("wifi interface no longer available");
2681 if (wifi->network) {
2682 connman_network_set_connected(wifi->network, false);
2683 wifi->network = NULL;
2686 wifi->disconnecting = false;
2687 wifi->connected = false;
2689 if (wifi->pending_network) {
2690 network_connect(wifi->pending_network);
2691 wifi->pending_network = NULL;
2694 start_autoscan(wifi->device);
2697 static int network_disconnect(struct connman_network *network)
2699 struct connman_device *device = connman_network_get_device(network);
2700 struct wifi_data *wifi;
2702 #if defined TIZEN_EXT
2703 struct connman_service *service;
2706 DBG("network %p", network);
2708 wifi = connman_device_get_data(device);
2709 if (!wifi || !wifi->interface)
2712 #if defined TIZEN_EXT
2713 if (connman_network_get_associating(network) == true) {
2714 connman_network_clear_associating(network);
2715 connman_network_set_bool(network, "WiFi.UseWPS", false);
2717 service = connman_service_lookup_from_network(network);
2719 if (service != NULL &&
2720 (__connman_service_is_connected_state(service,
2721 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2722 __connman_service_is_connected_state(service,
2723 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2724 (connman_service_get_favorite(service) == false))
2725 __connman_service_set_passphrase(service, NULL);
2728 if (wifi->pending_network == network)
2729 wifi->pending_network = NULL;
2731 if (wifi->scan_pending_network == network)
2732 wifi->scan_pending_network = NULL;
2735 connman_network_set_associating(network, false);
2737 if (wifi->disconnecting)
2740 wifi->disconnecting = true;
2742 #if defined TIZEN_EXT
2743 err = g_supplicant_interface_disconnect(wifi->interface,
2744 disconnect_callback, network);
2746 err = g_supplicant_interface_disconnect(wifi->interface,
2747 disconnect_callback, wifi);
2751 wifi->disconnecting = false;
2756 static struct connman_network_driver network_driver = {
2758 .type = CONNMAN_NETWORK_TYPE_WIFI,
2759 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2760 .probe = network_probe,
2761 .remove = network_remove,
2762 .connect = network_connect,
2763 .disconnect = network_disconnect,
2766 static void interface_added(GSupplicantInterface *interface)
2768 const char *ifname = g_supplicant_interface_get_ifname(interface);
2769 const char *driver = g_supplicant_interface_get_driver(interface);
2770 struct wifi_data *wifi;
2772 wifi = g_supplicant_interface_get_data(interface);
2774 wifi = get_pending_wifi_data(ifname);
2778 wifi->interface = interface;
2779 g_supplicant_interface_set_data(interface, wifi);
2780 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2781 wifi->p2p_device = true;
2784 DBG("ifname %s driver %s wifi %p tethering %d",
2785 ifname, driver, wifi, wifi->tethering);
2787 if (!wifi->device) {
2788 connman_error("WiFi device not set");
2792 connman_device_set_powered(wifi->device, true);
2795 static bool is_idle(struct wifi_data *wifi)
2797 DBG("state %d", wifi->state);
2799 switch (wifi->state) {
2800 case G_SUPPLICANT_STATE_UNKNOWN:
2801 case G_SUPPLICANT_STATE_DISABLED:
2802 case G_SUPPLICANT_STATE_DISCONNECTED:
2803 case G_SUPPLICANT_STATE_INACTIVE:
2804 case G_SUPPLICANT_STATE_SCANNING:
2807 case G_SUPPLICANT_STATE_AUTHENTICATING:
2808 case G_SUPPLICANT_STATE_ASSOCIATING:
2809 case G_SUPPLICANT_STATE_ASSOCIATED:
2810 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2811 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2812 case G_SUPPLICANT_STATE_COMPLETED:
2819 static bool is_idle_wps(GSupplicantInterface *interface,
2820 struct wifi_data *wifi)
2822 /* First, let's check if WPS processing did not went wrong */
2823 if (g_supplicant_interface_get_wps_state(interface) ==
2824 G_SUPPLICANT_WPS_STATE_FAIL)
2827 /* Unlike normal connection, being associated while processing wps
2828 * actually means that we are idling. */
2829 switch (wifi->state) {
2830 case G_SUPPLICANT_STATE_UNKNOWN:
2831 case G_SUPPLICANT_STATE_DISABLED:
2832 case G_SUPPLICANT_STATE_DISCONNECTED:
2833 case G_SUPPLICANT_STATE_INACTIVE:
2834 case G_SUPPLICANT_STATE_SCANNING:
2835 case G_SUPPLICANT_STATE_ASSOCIATED:
2837 case G_SUPPLICANT_STATE_AUTHENTICATING:
2838 case G_SUPPLICANT_STATE_ASSOCIATING:
2839 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2840 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2841 case G_SUPPLICANT_STATE_COMPLETED:
2848 static bool handle_wps_completion(GSupplicantInterface *interface,
2849 struct connman_network *network,
2850 struct connman_device *device,
2851 struct wifi_data *wifi)
2855 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2857 const unsigned char *ssid, *wps_ssid;
2858 unsigned int ssid_len, wps_ssid_len;
2859 const char *wps_key;
2861 /* Checking if we got associated with requested
2863 ssid = connman_network_get_blob(network, "WiFi.SSID",
2866 wps_ssid = g_supplicant_interface_get_wps_ssid(
2867 interface, &wps_ssid_len);
2869 if (!wps_ssid || wps_ssid_len != ssid_len ||
2870 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2871 connman_network_set_associating(network, false);
2872 #if defined TIZEN_EXT
2873 g_supplicant_interface_disconnect(wifi->interface,
2874 disconnect_callback, wifi->network);
2876 connman_network_set_bool(network, "WiFi.UseWPS", false);
2877 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2879 g_supplicant_interface_disconnect(wifi->interface,
2880 disconnect_callback, wifi);
2885 wps_key = g_supplicant_interface_get_wps_key(interface);
2886 #if defined TIZEN_EXT
2887 /* Check the passphrase and encrypt it
2890 gchar *passphrase = g_strdup(wps_key);
2892 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2894 if (check_passphrase_ext(network, passphrase) < 0) {
2895 DBG("[WPS] Invalid passphrase");
2900 ret = send_encryption_request(passphrase, network);
2905 DBG("[WPS] Encryption request succeeded");
2907 DBG("[WPS] Encryption request failed %d", ret);
2910 connman_network_set_string(network, "WiFi.Passphrase",
2913 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2920 static bool handle_assoc_status_code(GSupplicantInterface *interface,
2921 struct wifi_data *wifi)
2923 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
2924 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
2925 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
2926 wifi->load_shaping_retries ++;
2929 wifi->load_shaping_retries = 0;
2933 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2934 struct connman_network *network,
2935 struct wifi_data *wifi)
2937 #if defined TIZEN_EXT
2938 const char *security;
2939 struct connman_service *service;
2941 if (wifi->connected)
2944 security = connman_network_get_string(network, "WiFi.Security");
2946 if (security && g_str_equal(security, "ieee8021x") == true &&
2947 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2949 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2954 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2957 struct connman_service *service;
2959 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2962 if (wifi->connected)
2966 service = connman_service_lookup_from_network(network);
2972 if (connman_service_get_favorite(service)) {
2973 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2978 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2983 #if defined TIZEN_EXT
2984 static bool handle_wifi_assoc_retry(struct connman_network *network,
2985 struct wifi_data *wifi)
2987 const char *security;
2989 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2990 connman_network_get_connecting(network) != true) {
2991 wifi->assoc_retry_count = 0;
2995 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2996 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2997 wifi->assoc_retry_count = 0;
3001 security = connman_network_get_string(network, "WiFi.Security");
3002 if (security && g_str_equal(security, "ieee8021x") == true &&
3003 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
3004 wifi->assoc_retry_count = 0;
3008 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
3009 wifi->assoc_retry_count = 0;
3011 /* Honestly it's not an invalid-key error,
3012 * however QA team recommends that the invalid-key error
3013 * might be better to display for user experience.
3015 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3024 static void interface_state(GSupplicantInterface *interface)
3026 struct connman_network *network;
3027 struct connman_device *device;
3028 struct wifi_data *wifi;
3029 GSupplicantState state = g_supplicant_interface_get_state(interface);
3033 wifi = g_supplicant_interface_get_data(interface);
3035 DBG("wifi %p interface state %d", wifi, state);
3040 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3041 if (wifi->tethering_param) {
3042 g_free(wifi->tethering_param->ssid);
3043 g_free(wifi->tethering_param);
3044 wifi->tethering_param = NULL;
3048 device = wifi->device;
3052 if (g_supplicant_interface_get_ready(interface) &&
3053 !wifi->interface_ready) {
3054 wifi->interface_ready = true;
3055 finalize_interface_creation(wifi);
3058 network = wifi->network;
3063 case G_SUPPLICANT_STATE_SCANNING:
3064 if (wifi->connected)
3065 connman_network_set_connected(network, false);
3069 case G_SUPPLICANT_STATE_AUTHENTICATING:
3070 case G_SUPPLICANT_STATE_ASSOCIATING:
3071 #if defined TIZEN_EXT
3072 reset_autoscan(device);
3074 stop_autoscan(device);
3077 if (!wifi->connected)
3078 connman_network_set_associating(network, true);
3082 case G_SUPPLICANT_STATE_COMPLETED:
3083 #if defined TIZEN_EXT
3084 /* though it should be already reset: */
3085 reset_autoscan(device);
3087 wifi->assoc_retry_count = 0;
3089 wifi->scan_pending_network = NULL;
3091 /* should be cleared scanning flag */
3092 bool scanning = connman_device_get_scanning(device);
3094 connman_device_set_scanning(device,
3095 CONNMAN_SERVICE_TYPE_WIFI, false);
3096 connman_device_unref(device);
3099 /* though it should be already stopped: */
3100 stop_autoscan(device);
3103 if (!handle_wps_completion(interface, network, device, wifi))
3106 connman_network_set_connected(network, true);
3108 wifi->disconnect_code = 0;
3109 wifi->assoc_code = 0;
3110 wifi->load_shaping_retries = 0;
3113 case G_SUPPLICANT_STATE_DISCONNECTED:
3115 * If we're in one of the idle modes, we have
3116 * not started association yet and thus setting
3117 * those ones to FALSE could cancel an association
3120 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3122 if (is_idle_wps(interface, wifi))
3128 if (handle_assoc_status_code(interface, wifi))
3131 /* If previous state was 4way-handshake, then
3132 * it's either: psk was incorrect and thus we retry
3133 * or if we reach the maximum retries we declare the
3135 if (handle_4way_handshake_failure(interface,
3139 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3140 switch (wifi->disconnect_code) {
3141 case 1: /* Unspecified reason */
3142 /* Let's assume it's because we got blocked */
3144 case 6: /* Class 2 frame received from nonauthenticated STA */
3145 connman_network_set_error(network,
3146 CONNMAN_NETWORK_ERROR_BLOCKED);
3153 #if defined TIZEN_EXT
3154 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3155 * Retry association until its retry count is expired */
3156 if (handle_wifi_assoc_retry(network, wifi) == true) {
3157 throw_wifi_scan(wifi->device, scan_callback);
3158 wifi->scan_pending_network = wifi->network;
3162 if(wifi->disconnect_code > 0){
3163 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3164 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3168 connman_network_set_connected(network, false);
3169 connman_network_set_associating(network, false);
3170 wifi->disconnecting = false;
3172 start_autoscan(device);
3176 case G_SUPPLICANT_STATE_INACTIVE:
3177 #if defined TIZEN_EXT
3178 if (handle_wps_completion(interface, network, device, wifi) == false)
3181 connman_network_set_associating(network, false);
3182 start_autoscan(device);
3186 case G_SUPPLICANT_STATE_UNKNOWN:
3187 case G_SUPPLICANT_STATE_DISABLED:
3188 case G_SUPPLICANT_STATE_ASSOCIATED:
3189 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3190 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3194 old_connected = wifi->connected;
3195 wifi->state = state;
3197 /* Saving wpa_s state policy:
3198 * If connected and if the state changes are roaming related:
3199 * --> We stay connected
3201 * --> We are connected
3203 * --> We are not connected
3206 case G_SUPPLICANT_STATE_AUTHENTICATING:
3207 case G_SUPPLICANT_STATE_ASSOCIATING:
3208 case G_SUPPLICANT_STATE_ASSOCIATED:
3209 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3210 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3211 if (wifi->connected)
3212 connman_warn("Probably roaming right now!"
3213 " Staying connected...");
3215 case G_SUPPLICANT_STATE_SCANNING:
3216 wifi->connected = false;
3219 start_autoscan(device);
3221 case G_SUPPLICANT_STATE_COMPLETED:
3222 wifi->connected = true;
3225 wifi->connected = false;
3232 static void interface_removed(GSupplicantInterface *interface)
3234 const char *ifname = g_supplicant_interface_get_ifname(interface);
3235 struct wifi_data *wifi;
3237 DBG("ifname %s", ifname);
3239 wifi = g_supplicant_interface_get_data(interface);
3242 wifi->interface = NULL;
3244 if (wifi && wifi->tethering)
3247 if (!wifi || !wifi->device) {
3248 DBG("wifi interface already removed");
3252 connman_device_set_powered(wifi->device, false);
3254 check_p2p_technology();
3257 static void set_device_type(const char *type, char dev_type[17])
3259 const char *oui = "0050F204";
3260 const char *category = "0001";
3261 const char *sub_category = "0000";
3263 if (!g_strcmp0(type, "handset")) {
3265 sub_category = "0005";
3266 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
3267 sub_category = "0001";
3268 else if (!g_strcmp0(type, "server"))
3269 sub_category = "0002";
3270 else if (!g_strcmp0(type, "laptop"))
3271 sub_category = "0005";
3272 else if (!g_strcmp0(type, "desktop"))
3273 sub_category = "0006";
3274 else if (!g_strcmp0(type, "tablet"))
3275 sub_category = "0009";
3276 else if (!g_strcmp0(type, "watch"))
3279 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
3282 static void p2p_support(GSupplicantInterface *interface)
3284 char dev_type[17] = {};
3285 const char *hostname;
3292 if (!g_supplicant_interface_has_p2p(interface))
3295 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3296 DBG("Could not register P2P technology driver");
3300 hostname = connman_utsname_get_hostname();
3302 hostname = "ConnMan";
3304 set_device_type(connman_machine_get_type(), dev_type);
3305 g_supplicant_interface_set_p2p_device_config(interface,
3306 hostname, dev_type);
3307 connman_peer_driver_register(&peer_driver);
3310 static void scan_started(GSupplicantInterface *interface)
3315 static void scan_finished(GSupplicantInterface *interface)
3317 #if defined TIZEN_EXT
3318 struct wifi_data *wifi;
3319 bool is_associating = false;
3320 static bool is_scanning = true;
3325 #if defined TIZEN_EXT
3326 wifi = g_supplicant_interface_get_data(interface);
3327 if (wifi && wifi->scan_pending_network) {
3328 network_connect(wifi->scan_pending_network);
3329 wifi->scan_pending_network = NULL;
3332 //service state - associating
3333 if(!wifi || !wifi->network)
3336 is_associating = connman_network_get_associating(wifi->network);
3337 if(is_associating && is_scanning){
3338 is_scanning = false;
3339 DBG("send scan for connecting");
3340 throw_wifi_scan(wifi->device, scan_callback);
3351 static void ap_create_fail(GSupplicantInterface *interface)
3353 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3356 if ((wifi->tethering) && (wifi->tethering_param)) {
3357 DBG("%s create AP fail \n",
3358 g_supplicant_interface_get_ifname(wifi->interface));
3360 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
3361 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
3362 wifi->tethering = false;
3364 ret = tech_set_tethering(wifi->tethering_param->technology,
3365 wifi->tethering_param->ssid->ssid,
3366 wifi->tethering_param->ssid->passphrase,
3367 wifi->bridge, true);
3369 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
3370 connman_technology_tethering_notify(wifi_technology,false);
3373 g_free(wifi->tethering_param->ssid);
3374 g_free(wifi->tethering_param);
3375 wifi->tethering_param = NULL;
3381 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3383 unsigned char strength;
3385 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3387 #if !defined TIZEN_EXT
3394 static void network_added(GSupplicantNetwork *supplicant_network)
3396 struct connman_network *network;
3397 GSupplicantInterface *interface;
3398 struct wifi_data *wifi;
3399 const char *name, *identifier, *security, *group, *mode;
3400 const unsigned char *ssid;
3401 unsigned int ssid_len;
3405 bool wps_advertizing;
3407 #if defined TIZEN_EXT
3408 GSList *vsie_list = NULL;
3409 const unsigned char *country_code;
3412 mode = g_supplicant_network_get_mode(supplicant_network);
3413 identifier = g_supplicant_network_get_identifier(supplicant_network);
3415 DBG("%s", identifier);
3417 if (!g_strcmp0(mode, "adhoc"))
3420 interface = g_supplicant_network_get_interface(supplicant_network);
3421 wifi = g_supplicant_interface_get_data(interface);
3422 name = g_supplicant_network_get_name(supplicant_network);
3423 security = g_supplicant_network_get_security(supplicant_network);
3424 group = g_supplicant_network_get_identifier(supplicant_network);
3425 wps = g_supplicant_network_get_wps(supplicant_network);
3426 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3427 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3428 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3429 supplicant_network);
3434 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3436 network = connman_device_get_network(wifi->device, identifier);
3439 network = connman_network_create(identifier,
3440 CONNMAN_NETWORK_TYPE_WIFI);
3444 connman_network_set_index(network, wifi->index);
3446 if (connman_device_add_network(wifi->device, network) < 0) {
3447 connman_network_unref(network);
3451 wifi->networks = g_slist_prepend(wifi->networks, network);
3454 if (name && name[0] != '\0')
3455 connman_network_set_name(network, name);
3457 connman_network_set_blob(network, "WiFi.SSID",
3459 #if defined TIZEN_EXT
3460 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
3462 connman_network_set_vsie_list(network, vsie_list);
3464 DBG("vsie_list is NULL");
3465 country_code = g_supplicant_network_get_countrycode(supplicant_network);
3466 connman_network_set_countrycode(network, country_code);
3468 connman_network_set_string(network, "WiFi.Security", security);
3469 connman_network_set_strength(network,
3470 calculate_strength(supplicant_network));
3471 connman_network_set_bool(network, "WiFi.WPS", wps);
3474 /* Is AP advertizing for WPS association?
3475 * If so, we decide to use WPS by default */
3476 if (wps_ready && wps_pbc &&
3478 #if !defined TIZEN_EXT
3479 connman_network_set_bool(network, "WiFi.UseWPS", true);
3481 DBG("wps is activating by ap but ignore it.");
3486 connman_network_set_frequency(network,
3487 g_supplicant_network_get_frequency(supplicant_network));
3488 #if defined TIZEN_EXT
3489 connman_network_set_bssid(network,
3490 g_supplicant_network_get_bssid(supplicant_network));
3491 connman_network_set_maxrate(network,
3492 g_supplicant_network_get_maxrate(supplicant_network));
3493 connman_network_set_enc_mode(network,
3494 g_supplicant_network_get_enc_mode(supplicant_network));
3495 connman_network_set_rsn_mode(network,
3496 g_supplicant_network_get_rsn_mode(supplicant_network));
3497 connman_network_set_keymgmt(network,
3498 g_supplicant_network_get_keymgmt(supplicant_network));
3499 connman_network_set_bool(network, "WiFi.HS20AP",
3500 g_supplicant_network_is_hs20AP(supplicant_network));
3501 connman_network_set_bssid_list(network,
3502 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
3504 connman_network_set_available(network, true);
3505 connman_network_set_string(network, "WiFi.Mode", mode);
3507 #if defined TIZEN_EXT
3512 connman_network_set_group(network, group);
3514 #if defined TIZEN_EXT
3515 if (wifi_first_scan == true)
3516 found_with_first_scan = true;
3519 if (wifi->hidden && ssid) {
3520 #if defined TIZEN_EXT
3521 if (network_security(wifi->hidden->security) ==
3522 network_security(security) &&
3524 if (!g_strcmp0(wifi->hidden->security, security) &&
3526 wifi->hidden->ssid_len == ssid_len &&
3527 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3528 connman_network_connect_hidden(network,
3529 wifi->hidden->identity,
3530 wifi->hidden->passphrase,
3531 wifi->hidden->user_data);
3532 wifi->hidden->user_data = NULL;
3533 hidden_free(wifi->hidden);
3534 wifi->hidden = NULL;
3539 static void network_removed(GSupplicantNetwork *network)
3541 GSupplicantInterface *interface;
3542 struct wifi_data *wifi;
3543 const char *name, *identifier;
3544 struct connman_network *connman_network;
3546 interface = g_supplicant_network_get_interface(network);
3547 wifi = g_supplicant_interface_get_data(interface);
3548 identifier = g_supplicant_network_get_identifier(network);
3549 name = g_supplicant_network_get_name(network);
3551 DBG("name %s", name);
3556 connman_network = connman_device_get_network(wifi->device, identifier);
3557 if (!connman_network)
3560 #if defined TIZEN_EXT
3561 if (connman_network == wifi->scan_pending_network)
3562 wifi->scan_pending_network = NULL;
3564 if (connman_network == wifi->pending_network)
3565 wifi->pending_network = NULL;
3567 if(connman_network_get_connecting(connman_network) == true){
3568 connman_network_set_connected(connman_network, false);
3572 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3574 connman_device_remove_network(wifi->device, connman_network);
3575 connman_network_unref(connman_network);
3578 static void network_changed(GSupplicantNetwork *network, const char *property)
3580 GSupplicantInterface *interface;
3581 struct wifi_data *wifi;
3582 const char *name, *identifier;
3583 struct connman_network *connman_network;
3585 #if defined TIZEN_EXT
3586 const unsigned char *bssid;
3587 unsigned int maxrate;
3590 const unsigned char *country_code;
3594 interface = g_supplicant_network_get_interface(network);
3595 wifi = g_supplicant_interface_get_data(interface);
3596 identifier = g_supplicant_network_get_identifier(network);
3597 name = g_supplicant_network_get_name(network);
3599 DBG("name %s", name);
3604 connman_network = connman_device_get_network(wifi->device, identifier);
3605 if (!connman_network)
3608 if (g_str_equal(property, "Signal")) {
3609 connman_network_set_strength(connman_network,
3610 calculate_strength(network));
3611 connman_network_update(connman_network);
3614 #if defined TIZEN_EXT
3615 bssid = g_supplicant_network_get_bssid(network);
3616 maxrate = g_supplicant_network_get_maxrate(network);
3617 frequency = g_supplicant_network_get_frequency(network);
3618 wps = g_supplicant_network_get_wps(network);
3620 connman_network_set_bssid(connman_network, bssid);
3621 connman_network_set_maxrate(connman_network, maxrate);
3622 connman_network_set_frequency(connman_network, frequency);
3623 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3624 country_code = g_supplicant_network_get_countrycode(network);
3625 connman_network_set_countrycode(connman_network, country_code);
3626 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
3627 connman_network_set_bssid_list(connman_network, bssid_list);
3631 static void network_associated(GSupplicantNetwork *network)
3633 GSupplicantInterface *interface;
3634 struct wifi_data *wifi;
3635 struct connman_network *connman_network;
3636 const char *identifier;
3640 interface = g_supplicant_network_get_interface(network);
3644 wifi = g_supplicant_interface_get_data(interface);
3648 identifier = g_supplicant_network_get_identifier(network);
3650 connman_network = connman_device_get_network(wifi->device, identifier);
3651 if (!connman_network)
3654 if (wifi->network) {
3655 if (wifi->network == connman_network)
3659 * This should never happen, we got associated with
3660 * a network different than the one we were expecting.
3662 DBG("Associated to %p while expecting %p",
3663 connman_network, wifi->network);
3665 connman_network_set_associating(wifi->network, false);
3668 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
3670 wifi->network = connman_network_ref(connman_network);
3674 * Interface state changes callback (interface_state) is always
3675 * called before network_associated callback thus we need to call
3676 * interface_state again in order to process the new state now that
3677 * we have the network properly set.
3679 interface_state(interface);
3682 static void apply_peer_services(GSupplicantPeer *peer,
3683 struct connman_peer *connman_peer)
3685 const unsigned char *data;
3690 connman_peer_reset_services(connman_peer);
3692 data = g_supplicant_peer_get_widi_ies(peer, &length);
3694 connman_peer_add_service(connman_peer,
3695 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3699 static void add_station(const char *mac)
3701 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3705 static void remove_station(const char *mac)
3707 connman_technology_tethering_remove_station(mac);
3710 static void peer_found(GSupplicantPeer *peer)
3712 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3713 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3714 struct connman_peer *connman_peer;
3715 const char *identifier, *name;
3717 #if defined TIZEN_EXT
3721 identifier = g_supplicant_peer_get_identifier(peer);
3722 name = g_supplicant_peer_get_name(peer);
3724 DBG("ident: %s", identifier);
3726 connman_peer = connman_peer_get(wifi->device, identifier);
3730 connman_peer = connman_peer_create(identifier);
3731 connman_peer_set_name(connman_peer, name);
3732 connman_peer_set_device(connman_peer, wifi->device);
3733 apply_peer_services(peer, connman_peer);
3735 ret = connman_peer_register(connman_peer);
3736 if (ret < 0 && ret != -EALREADY)
3737 connman_peer_unref(connman_peer);
3739 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
3742 static void peer_lost(GSupplicantPeer *peer)
3744 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3745 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3746 struct connman_peer *connman_peer;
3747 const char *identifier;
3752 identifier = g_supplicant_peer_get_identifier(peer);
3754 DBG("ident: %s", identifier);
3756 connman_peer = connman_peer_get(wifi->device, identifier);
3758 if (wifi->p2p_connecting &&
3759 wifi->pending_peer == connman_peer) {
3760 peer_connect_timeout(wifi);
3762 connman_peer_unregister(connman_peer);
3763 connman_peer_unref(connman_peer);
3766 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
3769 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3771 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3772 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3773 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3774 struct connman_peer *connman_peer;
3775 const char *identifier;
3777 identifier = g_supplicant_peer_get_identifier(peer);
3779 DBG("ident: %s", identifier);
3784 connman_peer = connman_peer_get(wifi->device, identifier);
3789 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3790 apply_peer_services(peer, connman_peer);
3791 connman_peer_services_changed(connman_peer);
3793 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3794 if (!g_supplicant_peer_is_in_a_group(peer))
3795 p_state = CONNMAN_PEER_STATE_IDLE;
3797 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3799 case G_SUPPLICANT_PEER_GROUP_STARTED:
3801 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3802 p_state = CONNMAN_PEER_STATE_IDLE;
3804 case G_SUPPLICANT_PEER_GROUP_JOINED:
3805 connman_peer_set_iface_address(connman_peer,
3806 g_supplicant_peer_get_iface_address(peer));
3808 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3809 p_state = CONNMAN_PEER_STATE_IDLE;
3811 case G_SUPPLICANT_PEER_GROUP_FAILED:
3812 if (g_supplicant_peer_has_requested_connection(peer))
3813 p_state = CONNMAN_PEER_STATE_IDLE;
3815 p_state = CONNMAN_PEER_STATE_FAILURE;
3819 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3820 p_state == CONNMAN_PEER_STATE_FAILURE) {
3821 if (wifi->p2p_connecting
3822 && connman_peer == wifi->pending_peer)
3823 peer_cancel_timeout(wifi);
3825 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3828 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3831 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3832 GSupplicantInterface *g_iface;
3833 struct wifi_data *g_wifi;
3835 g_iface = g_supplicant_peer_get_group_interface(peer);
3839 g_wifi = g_supplicant_interface_get_data(g_iface);
3843 connman_peer_set_as_master(connman_peer,
3844 !g_supplicant_peer_is_client(peer));
3845 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3848 * If wpa_supplicant didn't create a dedicated p2p-group
3849 * interface then mark this interface as p2p_device to avoid
3850 * scan and auto-scan are launched on it while P2P is connected.
3852 if (!g_list_find(p2p_iface_list, g_wifi))
3853 wifi->p2p_device = true;
3856 connman_peer_set_state(connman_peer, p_state);
3859 static void peer_request(GSupplicantPeer *peer)
3861 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3862 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3863 struct connman_peer *connman_peer;
3864 const char *identifier;
3866 #if defined TIZEN_EXT
3871 identifier = g_supplicant_peer_get_identifier(peer);
3873 DBG("ident: %s", identifier);
3875 connman_peer = connman_peer_get(wifi->device, identifier);
3879 connman_peer_request_connection(connman_peer);
3882 #if defined TIZEN_EXT
3883 static void system_power_off(void)
3886 struct wifi_data *wifi;
3887 struct connman_service *service;
3888 struct connman_ipconfig *ipconfig_ipv4;
3890 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3891 for (list = iface_list; list; list = list->next) {
3894 if (wifi->network != NULL) {
3895 service = connman_service_lookup_from_network(wifi->network);
3896 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3897 __connman_dhcp_stop(ipconfig_ipv4);
3903 static void network_merged(GSupplicantNetwork *network)
3905 GSupplicantInterface *interface;
3906 GSupplicantState state;
3907 struct wifi_data *wifi;
3908 const char *identifier;
3909 struct connman_network *connman_network;
3913 interface = g_supplicant_network_get_interface(network);
3917 state = g_supplicant_interface_get_state(interface);
3918 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3921 wifi = g_supplicant_interface_get_data(interface);
3925 identifier = g_supplicant_network_get_identifier(network);
3927 connman_network = connman_device_get_network(wifi->device, identifier);
3928 if (!connman_network)
3931 DBG("merged identifier %s", identifier);
3933 if (wifi->connected == FALSE) {
3935 case G_SUPPLICANT_STATE_AUTHENTICATING:
3936 case G_SUPPLICANT_STATE_ASSOCIATING:
3937 case G_SUPPLICANT_STATE_ASSOCIATED:
3938 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3939 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3940 connman_network_set_associating(connman_network, TRUE);
3942 case G_SUPPLICANT_STATE_COMPLETED:
3943 connman_network_set_connected(connman_network, TRUE);
3946 DBG("Not handled the state : %d", state);
3951 ishs20AP = g_supplicant_network_is_hs20AP(network);
3954 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3955 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3956 connman_network_set_string(connman_network, "WiFi.EAP",
3958 connman_network_set_string(connman_network, "WiFi.Identity",
3959 g_supplicant_network_get_identity(network));
3960 connman_network_set_string(connman_network, "WiFi.Phase2",
3961 g_supplicant_network_get_phase2(network));
3966 wifi->network = connman_network;
3969 static void assoc_failed(void *user_data)
3971 struct connman_network *network = user_data;
3972 connman_network_set_associating(network, false);
3976 static void debug(const char *str)
3978 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3979 connman_debug("%s", str);
3982 static void disconnect_reasoncode(GSupplicantInterface *interface,
3985 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3988 wifi->disconnect_code = reasoncode;
3992 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
3994 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3997 wifi->assoc_code = status_code;
4001 static const GSupplicantCallbacks callbacks = {
4002 .system_ready = system_ready,
4003 .system_killed = system_killed,
4004 .interface_added = interface_added,
4005 .interface_state = interface_state,
4006 .interface_removed = interface_removed,
4007 .p2p_support = p2p_support,
4008 .scan_started = scan_started,
4009 .scan_finished = scan_finished,
4010 .ap_create_fail = ap_create_fail,
4011 .network_added = network_added,
4012 .network_removed = network_removed,
4013 .network_changed = network_changed,
4014 .network_associated = network_associated,
4015 .add_station = add_station,
4016 .remove_station = remove_station,
4017 .peer_found = peer_found,
4018 .peer_lost = peer_lost,
4019 .peer_changed = peer_changed,
4020 .peer_request = peer_request,
4021 #if defined TIZEN_EXT
4022 .system_power_off = system_power_off,
4023 .network_merged = network_merged,
4024 .assoc_failed = assoc_failed,
4027 .disconnect_reasoncode = disconnect_reasoncode,
4028 .assoc_status_code = assoc_status_code,
4032 static int tech_probe(struct connman_technology *technology)
4034 wifi_technology = technology;
4039 static void tech_remove(struct connman_technology *technology)
4041 wifi_technology = NULL;
4044 static GSupplicantSSID *ssid_ap_init(const char *ssid,
4045 const char *passphrase)
4047 GSupplicantSSID *ap;
4049 ap = g_try_malloc0(sizeof(GSupplicantSSID));
4053 ap->mode = G_SUPPLICANT_MODE_MASTER;
4054 #if defined TIZEN_EXT
4055 ap->ssid = (void *) ssid;
4059 ap->ssid_len = strlen(ssid);
4063 if (!passphrase || strlen(passphrase) == 0) {
4064 ap->security = G_SUPPLICANT_SECURITY_NONE;
4065 ap->passphrase = NULL;
4067 ap->security = G_SUPPLICANT_SECURITY_PSK;
4068 ap->protocol = G_SUPPLICANT_PROTO_RSN;
4069 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
4070 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
4071 ap->passphrase = passphrase;
4077 static void ap_start_callback(int result, GSupplicantInterface *interface,
4080 struct wifi_tethering_info *info = user_data;
4082 DBG("result %d index %d bridge %s",
4083 result, info->wifi->index, info->wifi->bridge);
4085 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4086 connman_inet_remove_from_bridge(info->wifi->index,
4087 info->wifi->bridge);
4089 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4090 connman_technology_tethering_notify(info->technology, false);
4091 g_free(info->wifi->tethering_param->ssid);
4092 g_free(info->wifi->tethering_param);
4093 info->wifi->tethering_param = NULL;
4097 g_free(info->ifname);
4101 static void ap_create_callback(int result,
4102 GSupplicantInterface *interface,
4105 struct wifi_tethering_info *info = user_data;
4107 DBG("result %d ifname %s", result,
4108 g_supplicant_interface_get_ifname(interface));
4110 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4111 connman_inet_remove_from_bridge(info->wifi->index,
4112 info->wifi->bridge);
4114 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4115 connman_technology_tethering_notify(info->technology, false);
4116 g_free(info->wifi->tethering_param->ssid);
4117 g_free(info->wifi->tethering_param);
4118 info->wifi->tethering_param = NULL;
4122 g_free(info->ifname);
4128 info->wifi->interface = interface;
4129 g_supplicant_interface_set_data(interface, info->wifi);
4131 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
4132 connman_error("Failed to set interface ap_scan property");
4134 g_supplicant_interface_connect(interface, info->ssid,
4135 ap_start_callback, info);
4138 static void sta_remove_callback(int result,
4139 GSupplicantInterface *interface,
4142 struct wifi_tethering_info *info = user_data;
4143 const char *driver = connman_option_get_string("wifi");
4145 DBG("ifname %s result %d ", info->ifname, result);
4147 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4148 info->wifi->tethering = false;
4149 connman_technology_tethering_notify(info->technology, false);
4151 g_free(info->ifname);
4155 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4156 g_free(info->wifi->tethering_param->ssid);
4157 g_free(info->wifi->tethering_param);
4158 info->wifi->tethering_param = NULL;
4163 info->wifi->interface = NULL;
4165 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
4170 static int enable_wifi_tethering(struct connman_technology *technology,
4171 const char *bridge, const char *identifier,
4172 const char *passphrase, bool available)
4175 GSupplicantInterface *interface;
4176 struct wifi_data *wifi;
4177 struct wifi_tethering_info *info;
4182 for (list = iface_list; list; list = list->next) {
4185 DBG("wifi %p network %p pending_network %p", wifi,
4186 wifi->network, wifi->pending_network);
4188 interface = wifi->interface;
4193 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
4196 ifname = g_supplicant_interface_get_ifname(wifi->interface);
4198 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
4199 DBG("%s does not support AP mode (detected)", ifname);
4203 mode = g_supplicant_interface_get_mode(interface);
4204 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
4205 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4206 DBG("%s does not support AP mode (capability)", ifname);
4210 if (wifi->network && available)
4213 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
4217 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
4218 if (!wifi->tethering_param) {
4224 info->technology = technology;
4225 info->wifi->bridge = bridge;
4226 info->ssid = ssid_ap_init(identifier, passphrase);
4230 info->ifname = g_strdup(ifname);
4234 wifi->tethering_param->technology = technology;
4235 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
4236 if (!wifi->tethering_param->ssid)
4239 info->wifi->tethering = true;
4240 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
4242 berr = connman_technology_tethering_notify(technology, true);
4246 err = g_supplicant_interface_remove(interface,
4247 sta_remove_callback,
4250 DBG("tethering wifi %p ifname %s", wifi, ifname);
4255 g_free(info->ifname);
4258 g_free(wifi->tethering_param);
4259 wifi->tethering_param = NULL;
4262 * Remove bridge if it was correctly created but remove
4263 * operation failed. Instead, if bridge creation failed then
4264 * break out and do not try again on another interface,
4265 * bridge set-up does not depend on it.
4268 connman_technology_tethering_notify(technology, false);
4276 static int tech_set_tethering(struct connman_technology *technology,
4277 const char *identifier, const char *passphrase,
4278 const char *bridge, bool enabled)
4281 struct wifi_data *wifi;
4287 for (list = iface_list; list; list = list->next) {
4290 if (wifi->tethering) {
4291 wifi->tethering = false;
4293 connman_inet_remove_from_bridge(wifi->index,
4295 wifi->bridged = false;
4299 connman_technology_tethering_notify(technology, false);
4304 DBG("trying tethering for available devices");
4305 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
4309 DBG("trying tethering for any device");
4310 err = enable_wifi_tethering(technology, bridge, identifier,
4317 static void regdom_callback(int result, const char *alpha2, void *user_data)
4321 if (!wifi_technology)
4327 connman_technology_regdom_notify(wifi_technology, alpha2);
4330 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
4332 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
4335 static struct connman_technology_driver tech_driver = {
4337 .type = CONNMAN_SERVICE_TYPE_WIFI,
4338 .probe = tech_probe,
4339 .remove = tech_remove,
4340 .set_tethering = tech_set_tethering,
4341 .set_regdom = tech_set_regdom,
4344 static int wifi_init(void)
4348 err = connman_network_driver_register(&network_driver);
4352 err = g_supplicant_register(&callbacks);
4354 connman_network_driver_unregister(&network_driver);
4358 err = connman_technology_driver_register(&tech_driver);
4360 g_supplicant_unregister(&callbacks);
4361 connman_network_driver_unregister(&network_driver);
4368 static void wifi_exit(void)
4372 connman_technology_driver_unregister(&tech_driver);
4374 g_supplicant_unregister(&callbacks);
4376 connman_network_driver_unregister(&network_driver);
4379 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
4380 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)