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 == 1) { /* 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 == 2) { /* 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;
2133 DBG("Invalid scan");
2137 reset_autoscan(device);
2138 connman_device_ref(device);
2140 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2141 specific_scan_callback, device);
2144 connman_device_set_scanning(device,
2145 CONNMAN_SERVICE_TYPE_WIFI, true);
2147 g_supplicant_free_scan_params(scan_params);
2148 connman_device_unref(device);
2156 * Note that the hidden scan is only used when connecting to this specific
2157 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2159 static int wifi_scan(enum connman_service_type type,
2160 struct connman_device *device,
2161 const char *ssid, unsigned int ssid_len,
2162 const char *identity, const char* passphrase,
2163 const char *security, void *user_data)
2165 struct wifi_data *wifi = connman_device_get_data(device);
2166 GSupplicantScanParams *scan_params = NULL;
2167 struct scan_ssid *scan_ssid;
2168 struct hidden_params *hidden;
2170 int driver_max_ssids = 0;
2177 if (wifi->p2p_device)
2180 if (wifi->tethering)
2183 if (type == CONNMAN_SERVICE_TYPE_P2P)
2184 return p2p_find(device);
2186 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2188 scanning = connman_device_get_scanning(device);
2190 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2194 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2196 DBG("max ssids %d", driver_max_ssids);
2197 if (driver_max_ssids == 0)
2198 return wifi_scan_simple(device);
2202 if (scanning && wifi->hidden && wifi->postpone_hidden)
2208 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2213 scan_ssid = g_try_new(struct scan_ssid, 1);
2215 g_free(scan_params);
2219 memcpy(scan_ssid->ssid, ssid, ssid_len);
2220 scan_ssid->ssid_len = ssid_len;
2221 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2223 scan_params->num_ssids = 1;
2225 hidden = g_try_new0(struct hidden_params, 1);
2227 g_supplicant_free_scan_params(scan_params);
2232 hidden_free(wifi->hidden);
2233 wifi->hidden = NULL;
2236 memcpy(hidden->ssid, ssid, ssid_len);
2237 hidden->ssid_len = ssid_len;
2238 hidden->identity = g_strdup(identity);
2239 hidden->passphrase = g_strdup(passphrase);
2240 hidden->security = g_strdup(security);
2241 hidden->user_data = user_data;
2242 wifi->hidden = hidden;
2245 /* Let's keep this active scan for later,
2246 * when current scan will be over. */
2247 wifi->postpone_hidden = TRUE;
2248 hidden->scan_params = scan_params;
2252 } else if (wifi->connected) {
2253 g_supplicant_free_scan_params(scan_params);
2254 return wifi_scan_simple(device);
2256 ret = get_latest_connections(driver_max_ssids, scan_params);
2258 g_supplicant_free_scan_params(scan_params);
2259 return wifi_scan_simple(device);
2263 connman_device_ref(device);
2265 reset_autoscan(device);
2267 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2268 scan_callback, device);
2271 connman_device_set_scanning(device,
2272 CONNMAN_SERVICE_TYPE_WIFI, true);
2273 #if defined TIZEN_EXT
2274 /*To allow the Full Scan after ssid based scan, set the flag here
2275 It is required because Tizen does not use the ConnMan specific
2276 backgroung Scan feature.Tizen has added the BG Scan feature in
2277 net-config. To sync with up ConnMan, we need to issue the Full Scan
2278 after SSID specific scan.*/
2279 wifi->allow_full_scan = TRUE;
2282 g_supplicant_free_scan_params(scan_params);
2283 connman_device_unref(device);
2286 hidden_free(wifi->hidden);
2287 wifi->hidden = NULL;
2294 static void wifi_regdom_callback(int result,
2298 struct connman_device *device = user_data;
2300 connman_device_regdom_notify(device, result, alpha2);
2302 connman_device_unref(device);
2305 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2307 struct wifi_data *wifi = connman_device_get_data(device);
2313 connman_device_ref(device);
2315 ret = g_supplicant_interface_set_country(wifi->interface,
2316 wifi_regdom_callback,
2319 connman_device_unref(device);
2324 static struct connman_device_driver wifi_ng_driver = {
2326 .type = CONNMAN_DEVICE_TYPE_WIFI,
2327 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2328 .probe = wifi_probe,
2329 .remove = wifi_remove,
2330 .enable = wifi_enable,
2331 .disable = wifi_disable,
2333 .set_regdom = wifi_set_regdom,
2334 #if defined TIZEN_EXT
2335 .specific_scan = wifi_specific_scan,
2339 static void system_ready(void)
2343 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2344 connman_error("Failed to register WiFi driver");
2347 static void system_killed(void)
2351 connman_device_driver_unregister(&wifi_ng_driver);
2354 static int network_probe(struct connman_network *network)
2356 DBG("network %p", network);
2361 static void network_remove(struct connman_network *network)
2363 struct connman_device *device = connman_network_get_device(network);
2364 struct wifi_data *wifi;
2366 DBG("network %p", network);
2368 wifi = connman_device_get_data(device);
2372 if (wifi->network != network)
2375 wifi->network = NULL;
2377 #if defined TIZEN_EXT
2378 wifi->disconnecting = false;
2380 if (wifi->pending_network == network)
2381 wifi->pending_network = NULL;
2383 if (wifi->scan_pending_network == network)
2384 wifi->scan_pending_network = NULL;
2388 static void connect_callback(int result, GSupplicantInterface *interface,
2391 #if defined TIZEN_EXT
2393 struct wifi_data *wifi;
2395 struct connman_network *network = user_data;
2397 DBG("network %p result %d", network, result);
2399 #if defined TIZEN_EXT
2400 set_connman_bssid(RESET_BSSID, NULL);
2402 for (list = iface_list; list; list = list->next) {
2405 if (wifi && wifi->network == network)
2409 /* wifi_data may be invalid because wifi is already disabled */
2414 if (result == -ENOKEY) {
2415 connman_network_set_error(network,
2416 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2417 } else if (result < 0) {
2418 connman_network_set_error(network,
2419 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2422 connman_network_unref(network);
2425 static GSupplicantSecurity network_security(const char *security)
2427 if (g_str_equal(security, "none"))
2428 return G_SUPPLICANT_SECURITY_NONE;
2429 else if (g_str_equal(security, "wep"))
2430 return G_SUPPLICANT_SECURITY_WEP;
2431 else if (g_str_equal(security, "psk"))
2432 return G_SUPPLICANT_SECURITY_PSK;
2433 else if (g_str_equal(security, "wpa"))
2434 return G_SUPPLICANT_SECURITY_PSK;
2435 else if (g_str_equal(security, "rsn"))
2436 return G_SUPPLICANT_SECURITY_PSK;
2437 else if (g_str_equal(security, "ieee8021x"))
2438 return G_SUPPLICANT_SECURITY_IEEE8021X;
2439 #if defined TIZEN_EXT
2440 else if (g_str_equal(security, "ft_psk") == TRUE)
2441 return G_SUPPLICANT_SECURITY_FT_PSK;
2442 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2443 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2446 return G_SUPPLICANT_SECURITY_UNKNOWN;
2449 #if defined TIZEN_EXT
2450 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
2452 if (security == NULL)
2453 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
2455 if (g_str_equal(security, "FT") == TRUE)
2456 return G_SUPPLICANT_EAP_KEYMGMT_FT;
2457 else if (g_str_equal(security, "CCKM") == TRUE)
2458 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
2460 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
2464 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2466 const char *security;
2468 memset(ssid, 0, sizeof(*ssid));
2469 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2470 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2472 ssid->scan_ssid = 1;
2473 security = connman_network_get_string(network, "WiFi.Security");
2474 ssid->security = network_security(security);
2475 ssid->passphrase = connman_network_get_string(network,
2477 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2480 * If our private key password is unset,
2481 * we use the supplied passphrase. That is needed
2482 * for PEAP where 2 passphrases (identity and client
2483 * cert may have to be provided.
2485 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2486 connman_network_set_string(network,
2487 "WiFi.PrivateKeyPassphrase",
2489 /* We must have an identity for both PEAP and TLS */
2490 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2492 /* Use agent provided identity as a fallback */
2493 if (!ssid->identity || strlen(ssid->identity) == 0)
2494 ssid->identity = connman_network_get_string(network,
2495 "WiFi.AgentIdentity");
2497 ssid->anonymous_identity = connman_network_get_string(network,
2498 "WiFi.AnonymousIdentity");
2499 ssid->ca_cert_path = connman_network_get_string(network,
2501 ssid->subject_match = connman_network_get_string(network,
2502 "WiFi.SubjectMatch");
2503 ssid->altsubject_match = connman_network_get_string(network,
2504 "WiFi.AltSubjectMatch");
2505 ssid->domain_suffix_match = connman_network_get_string(network,
2506 "WiFi.DomainSuffixMatch");
2507 ssid->domain_match = connman_network_get_string(network,
2508 "WiFi.DomainMatch");
2509 ssid->client_cert_path = connman_network_get_string(network,
2510 "WiFi.ClientCertFile");
2511 ssid->private_key_path = connman_network_get_string(network,
2512 "WiFi.PrivateKeyFile");
2513 ssid->private_key_passphrase = connman_network_get_string(network,
2514 "WiFi.PrivateKeyPassphrase");
2515 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2517 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2518 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2520 #if defined TIZEN_EXT
2521 ssid->bssid = connman_network_get_bssid(network);
2523 ssid->eap_keymgmt = network_eap_keymgmt(
2524 connman_network_get_string(network, "WiFi.KeymgmtType"));
2525 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
2527 if(g_strcmp0(ssid->eap, "fast") == 0)
2528 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
2530 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
2531 ssid->bssid_for_connect_len = 6;
2532 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
2533 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
2534 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
2535 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
2536 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
2538 ssid->freq = connman_network_get_frequency(network);
2542 if (connman_setting_get_bool("BackgroundScanning"))
2543 ssid->bgscan = BGSCAN_DEFAULT;
2546 static int network_connect(struct connman_network *network)
2548 struct connman_device *device = connman_network_get_device(network);
2549 struct wifi_data *wifi;
2550 GSupplicantInterface *interface;
2551 GSupplicantSSID *ssid;
2553 DBG("network %p", network);
2558 wifi = connman_device_get_data(device);
2562 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2566 interface = wifi->interface;
2568 ssid_init(ssid, network);
2570 if (wifi->disconnecting) {
2571 wifi->pending_network = network;
2574 wifi->network = connman_network_ref(network);
2576 #if defined TIZEN_EXT
2577 wifi->scan_pending_network = NULL;
2580 return g_supplicant_interface_connect(interface, ssid,
2581 connect_callback, network);
2584 return -EINPROGRESS;
2587 static void disconnect_callback(int result, GSupplicantInterface *interface,
2590 #if defined TIZEN_EXT
2592 struct wifi_data *wifi;
2593 struct connman_network *network = user_data;
2595 DBG("network %p result %d", network, result);
2597 for (list = iface_list; list; list = list->next) {
2600 if (wifi->network == NULL && wifi->disconnecting == true)
2601 wifi->disconnecting = false;
2603 if (wifi->network == network)
2607 /* wifi_data may be invalid because wifi is already disabled */
2612 struct wifi_data *wifi = user_data;
2615 DBG("result %d supplicant interface %p wifi %p",
2616 result, interface, wifi);
2618 if (result == -ECONNABORTED) {
2619 DBG("wifi interface no longer available");
2623 if (wifi->network) {
2624 connman_network_set_connected(wifi->network, false);
2625 wifi->network = NULL;
2628 wifi->disconnecting = false;
2629 wifi->connected = false;
2631 if (wifi->pending_network) {
2632 network_connect(wifi->pending_network);
2633 wifi->pending_network = NULL;
2636 start_autoscan(wifi->device);
2639 static int network_disconnect(struct connman_network *network)
2641 struct connman_device *device = connman_network_get_device(network);
2642 struct wifi_data *wifi;
2644 #if defined TIZEN_EXT
2645 struct connman_service *service;
2648 DBG("network %p", network);
2650 wifi = connman_device_get_data(device);
2651 if (!wifi || !wifi->interface)
2654 #if defined TIZEN_EXT
2655 if (connman_network_get_associating(network) == true) {
2656 connman_network_clear_associating(network);
2657 connman_network_set_bool(network, "WiFi.UseWPS", false);
2659 service = connman_service_lookup_from_network(network);
2661 if (service != NULL &&
2662 (__connman_service_is_connected_state(service,
2663 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2664 __connman_service_is_connected_state(service,
2665 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2666 (connman_service_get_favorite(service) == false))
2667 __connman_service_set_passphrase(service, NULL);
2670 if (wifi->pending_network == network)
2671 wifi->pending_network = NULL;
2673 if (wifi->scan_pending_network == network)
2674 wifi->scan_pending_network = NULL;
2677 connman_network_set_associating(network, false);
2679 if (wifi->disconnecting)
2682 wifi->disconnecting = true;
2684 #if defined TIZEN_EXT
2685 err = g_supplicant_interface_disconnect(wifi->interface,
2686 disconnect_callback, network);
2688 err = g_supplicant_interface_disconnect(wifi->interface,
2689 disconnect_callback, wifi);
2693 wifi->disconnecting = false;
2698 static struct connman_network_driver network_driver = {
2700 .type = CONNMAN_NETWORK_TYPE_WIFI,
2701 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2702 .probe = network_probe,
2703 .remove = network_remove,
2704 .connect = network_connect,
2705 .disconnect = network_disconnect,
2708 static void interface_added(GSupplicantInterface *interface)
2710 const char *ifname = g_supplicant_interface_get_ifname(interface);
2711 const char *driver = g_supplicant_interface_get_driver(interface);
2712 struct wifi_data *wifi;
2714 wifi = g_supplicant_interface_get_data(interface);
2716 wifi = get_pending_wifi_data(ifname);
2720 wifi->interface = interface;
2721 g_supplicant_interface_set_data(interface, wifi);
2722 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2723 wifi->p2p_device = true;
2726 DBG("ifname %s driver %s wifi %p tethering %d",
2727 ifname, driver, wifi, wifi->tethering);
2729 if (!wifi->device) {
2730 connman_error("WiFi device not set");
2734 connman_device_set_powered(wifi->device, true);
2737 static bool is_idle(struct wifi_data *wifi)
2739 DBG("state %d", wifi->state);
2741 switch (wifi->state) {
2742 case G_SUPPLICANT_STATE_UNKNOWN:
2743 case G_SUPPLICANT_STATE_DISABLED:
2744 case G_SUPPLICANT_STATE_DISCONNECTED:
2745 case G_SUPPLICANT_STATE_INACTIVE:
2746 case G_SUPPLICANT_STATE_SCANNING:
2749 case G_SUPPLICANT_STATE_AUTHENTICATING:
2750 case G_SUPPLICANT_STATE_ASSOCIATING:
2751 case G_SUPPLICANT_STATE_ASSOCIATED:
2752 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2753 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2754 case G_SUPPLICANT_STATE_COMPLETED:
2761 static bool is_idle_wps(GSupplicantInterface *interface,
2762 struct wifi_data *wifi)
2764 /* First, let's check if WPS processing did not went wrong */
2765 if (g_supplicant_interface_get_wps_state(interface) ==
2766 G_SUPPLICANT_WPS_STATE_FAIL)
2769 /* Unlike normal connection, being associated while processing wps
2770 * actually means that we are idling. */
2771 switch (wifi->state) {
2772 case G_SUPPLICANT_STATE_UNKNOWN:
2773 case G_SUPPLICANT_STATE_DISABLED:
2774 case G_SUPPLICANT_STATE_DISCONNECTED:
2775 case G_SUPPLICANT_STATE_INACTIVE:
2776 case G_SUPPLICANT_STATE_SCANNING:
2777 case G_SUPPLICANT_STATE_ASSOCIATED:
2779 case G_SUPPLICANT_STATE_AUTHENTICATING:
2780 case G_SUPPLICANT_STATE_ASSOCIATING:
2781 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2782 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2783 case G_SUPPLICANT_STATE_COMPLETED:
2790 static bool handle_wps_completion(GSupplicantInterface *interface,
2791 struct connman_network *network,
2792 struct connman_device *device,
2793 struct wifi_data *wifi)
2797 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2799 const unsigned char *ssid, *wps_ssid;
2800 unsigned int ssid_len, wps_ssid_len;
2801 const char *wps_key;
2803 /* Checking if we got associated with requested
2805 ssid = connman_network_get_blob(network, "WiFi.SSID",
2808 wps_ssid = g_supplicant_interface_get_wps_ssid(
2809 interface, &wps_ssid_len);
2811 if (!wps_ssid || wps_ssid_len != ssid_len ||
2812 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2813 connman_network_set_associating(network, false);
2814 #if defined TIZEN_EXT
2815 g_supplicant_interface_disconnect(wifi->interface,
2816 disconnect_callback, wifi->network);
2818 connman_network_set_bool(network, "WiFi.UseWPS", false);
2819 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2821 g_supplicant_interface_disconnect(wifi->interface,
2822 disconnect_callback, wifi);
2827 wps_key = g_supplicant_interface_get_wps_key(interface);
2828 #if defined TIZEN_EXT
2829 /* Check the passphrase and encrypt it
2832 gchar *passphrase = g_strdup(wps_key);
2834 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2836 if (check_passphrase_ext(network, passphrase) < 0) {
2837 DBG("[WPS] Invalid passphrase");
2842 ret = send_encryption_request(passphrase, network);
2847 DBG("[WPS] Encryption request succeeded");
2849 DBG("[WPS] Encryption request failed %d", ret);
2852 connman_network_set_string(network, "WiFi.Passphrase",
2855 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2862 static bool handle_assoc_status_code(GSupplicantInterface *interface,
2863 struct wifi_data *wifi)
2865 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
2866 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
2867 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
2868 wifi->load_shaping_retries ++;
2871 wifi->load_shaping_retries = 0;
2875 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2876 struct connman_network *network,
2877 struct wifi_data *wifi)
2879 #if defined TIZEN_EXT
2880 const char *security;
2881 struct connman_service *service;
2883 if (wifi->connected)
2886 security = connman_network_get_string(network, "WiFi.Security");
2888 if (security && g_str_equal(security, "ieee8021x") == true &&
2889 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2891 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2896 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2899 struct connman_service *service;
2901 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2904 if (wifi->connected)
2908 service = connman_service_lookup_from_network(network);
2914 if (connman_service_get_favorite(service)) {
2915 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2920 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2925 #if defined TIZEN_EXT
2926 static bool handle_wifi_assoc_retry(struct connman_network *network,
2927 struct wifi_data *wifi)
2929 const char *security;
2931 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2932 connman_network_get_connecting(network) != true) {
2933 wifi->assoc_retry_count = 0;
2937 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2938 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2939 wifi->assoc_retry_count = 0;
2943 security = connman_network_get_string(network, "WiFi.Security");
2944 if (security && g_str_equal(security, "ieee8021x") == true &&
2945 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2946 wifi->assoc_retry_count = 0;
2950 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2951 wifi->assoc_retry_count = 0;
2953 /* Honestly it's not an invalid-key error,
2954 * however QA team recommends that the invalid-key error
2955 * might be better to display for user experience.
2957 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2966 static void interface_state(GSupplicantInterface *interface)
2968 struct connman_network *network;
2969 struct connman_device *device;
2970 struct wifi_data *wifi;
2971 GSupplicantState state = g_supplicant_interface_get_state(interface);
2975 wifi = g_supplicant_interface_get_data(interface);
2977 DBG("wifi %p interface state %d", wifi, state);
2982 if (state == G_SUPPLICANT_STATE_COMPLETED) {
2983 if (wifi->tethering_param) {
2984 g_free(wifi->tethering_param->ssid);
2985 g_free(wifi->tethering_param);
2986 wifi->tethering_param = NULL;
2990 device = wifi->device;
2994 if (g_supplicant_interface_get_ready(interface) &&
2995 !wifi->interface_ready) {
2996 wifi->interface_ready = true;
2997 finalize_interface_creation(wifi);
3000 network = wifi->network;
3005 case G_SUPPLICANT_STATE_SCANNING:
3006 if (wifi->connected)
3007 connman_network_set_connected(network, false);
3011 case G_SUPPLICANT_STATE_AUTHENTICATING:
3012 case G_SUPPLICANT_STATE_ASSOCIATING:
3013 #if defined TIZEN_EXT
3014 reset_autoscan(device);
3016 stop_autoscan(device);
3019 if (!wifi->connected)
3020 connman_network_set_associating(network, true);
3024 case G_SUPPLICANT_STATE_COMPLETED:
3025 #if defined TIZEN_EXT
3026 /* though it should be already reset: */
3027 reset_autoscan(device);
3029 wifi->assoc_retry_count = 0;
3031 wifi->scan_pending_network = NULL;
3033 /* should be cleared scanning flag */
3034 bool scanning = connman_device_get_scanning(device);
3036 connman_device_set_scanning(device,
3037 CONNMAN_SERVICE_TYPE_WIFI, false);
3038 connman_device_unref(device);
3041 /* though it should be already stopped: */
3042 stop_autoscan(device);
3045 if (!handle_wps_completion(interface, network, device, wifi))
3048 connman_network_set_connected(network, true);
3050 wifi->disconnect_code = 0;
3051 wifi->assoc_code = 0;
3052 wifi->load_shaping_retries = 0;
3055 case G_SUPPLICANT_STATE_DISCONNECTED:
3057 * If we're in one of the idle modes, we have
3058 * not started association yet and thus setting
3059 * those ones to FALSE could cancel an association
3062 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3064 if (is_idle_wps(interface, wifi))
3070 if (handle_assoc_status_code(interface, wifi))
3073 /* If previous state was 4way-handshake, then
3074 * it's either: psk was incorrect and thus we retry
3075 * or if we reach the maximum retries we declare the
3077 if (handle_4way_handshake_failure(interface,
3081 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3082 switch (wifi->disconnect_code) {
3083 case 1: /* Unspecified reason */
3084 /* Let's assume it's because we got blocked */
3086 case 6: /* Class 2 frame received from nonauthenticated STA */
3087 connman_network_set_error(network,
3088 CONNMAN_NETWORK_ERROR_BLOCKED);
3095 #if defined TIZEN_EXT
3098 err = g_supplicant_interface_remove_network(wifi->interface);
3100 DBG("Failed to remove network(%d)", err);
3103 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3104 * Retry association until its retry count is expired */
3105 if (handle_wifi_assoc_retry(network, wifi) == true) {
3106 throw_wifi_scan(wifi->device, scan_callback);
3107 wifi->scan_pending_network = wifi->network;
3111 if(wifi->disconnect_code > 0){
3112 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3113 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3116 /* To avoid unnecessary repeated association in wpa_supplicant,
3117 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
3118 if (wps != true && wifi->network && wifi->disconnecting == false) {
3119 wifi->disconnecting = true;
3120 err = g_supplicant_interface_disconnect(wifi->interface,
3121 disconnect_callback, wifi->network);
3123 wifi->disconnecting = false;
3125 connman_network_set_connected(network, false);
3126 connman_network_set_associating(network, false);
3128 start_autoscan(device);
3134 connman_network_set_connected(network, false);
3135 connman_network_set_associating(network, false);
3136 wifi->disconnecting = false;
3138 start_autoscan(device);
3142 case G_SUPPLICANT_STATE_INACTIVE:
3143 #if defined TIZEN_EXT
3144 if (handle_wps_completion(interface, network, device, wifi) == false)
3147 connman_network_set_associating(network, false);
3148 start_autoscan(device);
3152 case G_SUPPLICANT_STATE_UNKNOWN:
3153 case G_SUPPLICANT_STATE_DISABLED:
3154 case G_SUPPLICANT_STATE_ASSOCIATED:
3155 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3156 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3160 old_connected = wifi->connected;
3161 wifi->state = state;
3163 /* Saving wpa_s state policy:
3164 * If connected and if the state changes are roaming related:
3165 * --> We stay connected
3167 * --> We are connected
3169 * --> We are not connected
3172 case G_SUPPLICANT_STATE_AUTHENTICATING:
3173 case G_SUPPLICANT_STATE_ASSOCIATING:
3174 case G_SUPPLICANT_STATE_ASSOCIATED:
3175 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3176 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3177 if (wifi->connected)
3178 connman_warn("Probably roaming right now!"
3179 " Staying connected...");
3181 case G_SUPPLICANT_STATE_SCANNING:
3182 wifi->connected = false;
3185 start_autoscan(device);
3187 case G_SUPPLICANT_STATE_COMPLETED:
3188 wifi->connected = true;
3191 wifi->connected = false;
3198 static void interface_removed(GSupplicantInterface *interface)
3200 const char *ifname = g_supplicant_interface_get_ifname(interface);
3201 struct wifi_data *wifi;
3203 DBG("ifname %s", ifname);
3205 wifi = g_supplicant_interface_get_data(interface);
3208 wifi->interface = NULL;
3210 if (wifi && wifi->tethering)
3213 if (!wifi || !wifi->device) {
3214 DBG("wifi interface already removed");
3218 connman_device_set_powered(wifi->device, false);
3220 check_p2p_technology();
3223 static void set_device_type(const char *type, char dev_type[17])
3225 const char *oui = "0050F204";
3226 const char *category = "0001";
3227 const char *sub_category = "0000";
3229 if (!g_strcmp0(type, "handset")) {
3231 sub_category = "0005";
3232 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
3233 sub_category = "0001";
3234 else if (!g_strcmp0(type, "server"))
3235 sub_category = "0002";
3236 else if (!g_strcmp0(type, "laptop"))
3237 sub_category = "0005";
3238 else if (!g_strcmp0(type, "desktop"))
3239 sub_category = "0006";
3240 else if (!g_strcmp0(type, "tablet"))
3241 sub_category = "0009";
3242 else if (!g_strcmp0(type, "watch"))
3245 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
3248 static void p2p_support(GSupplicantInterface *interface)
3250 char dev_type[17] = {};
3251 const char *hostname;
3258 if (!g_supplicant_interface_has_p2p(interface))
3261 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3262 DBG("Could not register P2P technology driver");
3266 hostname = connman_utsname_get_hostname();
3268 hostname = "ConnMan";
3270 set_device_type(connman_machine_get_type(), dev_type);
3271 g_supplicant_interface_set_p2p_device_config(interface,
3272 hostname, dev_type);
3273 connman_peer_driver_register(&peer_driver);
3276 static void scan_started(GSupplicantInterface *interface)
3281 static void scan_finished(GSupplicantInterface *interface)
3283 #if defined TIZEN_EXT
3284 struct wifi_data *wifi;
3285 bool is_associating = false;
3286 static bool is_scanning = true;
3291 #if defined TIZEN_EXT
3292 wifi = g_supplicant_interface_get_data(interface);
3293 if (wifi && wifi->scan_pending_network) {
3294 network_connect(wifi->scan_pending_network);
3295 wifi->scan_pending_network = NULL;
3298 //service state - associating
3299 if(!wifi || !wifi->network)
3302 is_associating = connman_network_get_associating(wifi->network);
3303 if(is_associating && is_scanning){
3304 is_scanning = false;
3305 DBG("send scan for connecting");
3306 throw_wifi_scan(wifi->device, scan_callback);
3317 static void ap_create_fail(GSupplicantInterface *interface)
3319 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3322 if ((wifi->tethering) && (wifi->tethering_param)) {
3323 DBG("%s create AP fail \n",
3324 g_supplicant_interface_get_ifname(wifi->interface));
3326 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
3327 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
3328 wifi->tethering = false;
3330 ret = tech_set_tethering(wifi->tethering_param->technology,
3331 wifi->tethering_param->ssid->ssid,
3332 wifi->tethering_param->ssid->passphrase,
3333 wifi->bridge, true);
3335 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
3336 connman_technology_tethering_notify(wifi_technology,false);
3339 g_free(wifi->tethering_param->ssid);
3340 g_free(wifi->tethering_param);
3341 wifi->tethering_param = NULL;
3347 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3349 unsigned char strength;
3351 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3353 #if !defined TIZEN_EXT
3360 static void network_added(GSupplicantNetwork *supplicant_network)
3362 struct connman_network *network;
3363 GSupplicantInterface *interface;
3364 struct wifi_data *wifi;
3365 const char *name, *identifier, *security, *group, *mode;
3366 const unsigned char *ssid;
3367 unsigned int ssid_len;
3371 bool wps_advertizing;
3373 #if defined TIZEN_EXT
3374 GSList *vsie_list = NULL;
3377 mode = g_supplicant_network_get_mode(supplicant_network);
3378 identifier = g_supplicant_network_get_identifier(supplicant_network);
3380 DBG("%s", identifier);
3382 if (!g_strcmp0(mode, "adhoc"))
3385 interface = g_supplicant_network_get_interface(supplicant_network);
3386 wifi = g_supplicant_interface_get_data(interface);
3387 name = g_supplicant_network_get_name(supplicant_network);
3388 security = g_supplicant_network_get_security(supplicant_network);
3389 group = g_supplicant_network_get_identifier(supplicant_network);
3390 wps = g_supplicant_network_get_wps(supplicant_network);
3391 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3392 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3393 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3394 supplicant_network);
3399 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3401 network = connman_device_get_network(wifi->device, identifier);
3404 network = connman_network_create(identifier,
3405 CONNMAN_NETWORK_TYPE_WIFI);
3409 connman_network_set_index(network, wifi->index);
3411 if (connman_device_add_network(wifi->device, network) < 0) {
3412 connman_network_unref(network);
3416 wifi->networks = g_slist_prepend(wifi->networks, network);
3419 if (name && name[0] != '\0')
3420 connman_network_set_name(network, name);
3422 connman_network_set_blob(network, "WiFi.SSID",
3424 #if defined TIZEN_EXT
3425 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
3427 connman_network_set_vsie_list(network, vsie_list);
3429 DBG("vsie_list is NULL");
3431 connman_network_set_string(network, "WiFi.Security", security);
3432 connman_network_set_strength(network,
3433 calculate_strength(supplicant_network));
3434 connman_network_set_bool(network, "WiFi.WPS", wps);
3437 /* Is AP advertizing for WPS association?
3438 * If so, we decide to use WPS by default */
3439 if (wps_ready && wps_pbc &&
3441 #if !defined TIZEN_EXT
3442 connman_network_set_bool(network, "WiFi.UseWPS", true);
3444 DBG("wps is activating by ap but ignore it.");
3449 connman_network_set_frequency(network,
3450 g_supplicant_network_get_frequency(supplicant_network));
3451 #if defined TIZEN_EXT
3452 connman_network_set_bssid(network,
3453 g_supplicant_network_get_bssid(supplicant_network));
3454 connman_network_set_maxrate(network,
3455 g_supplicant_network_get_maxrate(supplicant_network));
3456 connman_network_set_enc_mode(network,
3457 g_supplicant_network_get_enc_mode(supplicant_network));
3458 connman_network_set_rsn_mode(network,
3459 g_supplicant_network_get_rsn_mode(supplicant_network));
3460 connman_network_set_keymgmt(network,
3461 g_supplicant_network_get_keymgmt(supplicant_network));
3462 connman_network_set_bool(network, "WiFi.HS20AP",
3463 g_supplicant_network_is_hs20AP(supplicant_network));
3465 connman_network_set_available(network, true);
3466 connman_network_set_string(network, "WiFi.Mode", mode);
3468 #if defined TIZEN_EXT
3473 connman_network_set_group(network, group);
3475 #if defined TIZEN_EXT
3476 if (wifi_first_scan == true)
3477 found_with_first_scan = true;
3480 if (wifi->hidden && ssid) {
3481 #if defined TIZEN_EXT
3482 if (network_security(wifi->hidden->security) ==
3483 network_security(security) &&
3485 if (!g_strcmp0(wifi->hidden->security, security) &&
3487 wifi->hidden->ssid_len == ssid_len &&
3488 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3489 connman_network_connect_hidden(network,
3490 wifi->hidden->identity,
3491 wifi->hidden->passphrase,
3492 wifi->hidden->user_data);
3493 wifi->hidden->user_data = NULL;
3494 hidden_free(wifi->hidden);
3495 wifi->hidden = NULL;
3500 static void network_removed(GSupplicantNetwork *network)
3502 GSupplicantInterface *interface;
3503 struct wifi_data *wifi;
3504 const char *name, *identifier;
3505 struct connman_network *connman_network;
3507 interface = g_supplicant_network_get_interface(network);
3508 wifi = g_supplicant_interface_get_data(interface);
3509 identifier = g_supplicant_network_get_identifier(network);
3510 name = g_supplicant_network_get_name(network);
3512 DBG("name %s", name);
3517 connman_network = connman_device_get_network(wifi->device, identifier);
3518 if (!connman_network)
3521 #if defined TIZEN_EXT
3522 if (connman_network == wifi->scan_pending_network)
3523 wifi->scan_pending_network = NULL;
3525 if (connman_network == wifi->pending_network)
3526 wifi->pending_network = NULL;
3528 if(connman_network_get_connecting(connman_network) == true){
3529 connman_network_set_connected(connman_network, false);
3533 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3535 connman_device_remove_network(wifi->device, connman_network);
3536 connman_network_unref(connman_network);
3539 static void network_changed(GSupplicantNetwork *network, const char *property)
3541 GSupplicantInterface *interface;
3542 struct wifi_data *wifi;
3543 const char *name, *identifier;
3544 struct connman_network *connman_network;
3546 #if defined TIZEN_EXT
3547 const unsigned char *bssid;
3548 unsigned int maxrate;
3553 interface = g_supplicant_network_get_interface(network);
3554 wifi = g_supplicant_interface_get_data(interface);
3555 identifier = g_supplicant_network_get_identifier(network);
3556 name = g_supplicant_network_get_name(network);
3558 DBG("name %s", name);
3563 connman_network = connman_device_get_network(wifi->device, identifier);
3564 if (!connman_network)
3567 if (g_str_equal(property, "Signal")) {
3568 connman_network_set_strength(connman_network,
3569 calculate_strength(network));
3570 connman_network_update(connman_network);
3573 #if defined TIZEN_EXT
3574 bssid = g_supplicant_network_get_bssid(network);
3575 maxrate = g_supplicant_network_get_maxrate(network);
3576 frequency = g_supplicant_network_get_frequency(network);
3577 wps = g_supplicant_network_get_wps(network);
3579 connman_network_set_bssid(connman_network, bssid);
3580 connman_network_set_maxrate(connman_network, maxrate);
3581 connman_network_set_frequency(connman_network, frequency);
3582 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3586 static void network_associated(GSupplicantNetwork *network)
3588 GSupplicantInterface *interface;
3589 struct wifi_data *wifi;
3590 struct connman_network *connman_network;
3591 const char *identifier;
3595 interface = g_supplicant_network_get_interface(network);
3599 wifi = g_supplicant_interface_get_data(interface);
3603 identifier = g_supplicant_network_get_identifier(network);
3605 connman_network = connman_device_get_network(wifi->device, identifier);
3606 if (!connman_network)
3609 if (wifi->network) {
3610 if (wifi->network == connman_network)
3614 * This should never happen, we got associated with
3615 * a network different than the one we were expecting.
3617 DBG("Associated to %p while expecting %p",
3618 connman_network, wifi->network);
3620 connman_network_set_associating(wifi->network, false);
3623 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
3625 wifi->network = connman_network_ref(connman_network);
3629 * Interface state changes callback (interface_state) is always
3630 * called before network_associated callback thus we need to call
3631 * interface_state again in order to process the new state now that
3632 * we have the network properly set.
3634 interface_state(interface);
3637 static void apply_peer_services(GSupplicantPeer *peer,
3638 struct connman_peer *connman_peer)
3640 const unsigned char *data;
3645 connman_peer_reset_services(connman_peer);
3647 data = g_supplicant_peer_get_widi_ies(peer, &length);
3649 connman_peer_add_service(connman_peer,
3650 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3654 static void add_station(const char *mac)
3656 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3660 static void remove_station(const char *mac)
3662 connman_technology_tethering_remove_station(mac);
3665 static void peer_found(GSupplicantPeer *peer)
3667 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3668 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3669 struct connman_peer *connman_peer;
3670 const char *identifier, *name;
3672 #if defined TIZEN_EXT
3676 identifier = g_supplicant_peer_get_identifier(peer);
3677 name = g_supplicant_peer_get_name(peer);
3679 DBG("ident: %s", identifier);
3681 connman_peer = connman_peer_get(wifi->device, identifier);
3685 connman_peer = connman_peer_create(identifier);
3686 connman_peer_set_name(connman_peer, name);
3687 connman_peer_set_device(connman_peer, wifi->device);
3688 apply_peer_services(peer, connman_peer);
3690 ret = connman_peer_register(connman_peer);
3691 if (ret < 0 && ret != -EALREADY)
3692 connman_peer_unref(connman_peer);
3694 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
3697 static void peer_lost(GSupplicantPeer *peer)
3699 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3700 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3701 struct connman_peer *connman_peer;
3702 const char *identifier;
3707 identifier = g_supplicant_peer_get_identifier(peer);
3709 DBG("ident: %s", identifier);
3711 connman_peer = connman_peer_get(wifi->device, identifier);
3713 if (wifi->p2p_connecting &&
3714 wifi->pending_peer == connman_peer) {
3715 peer_connect_timeout(wifi);
3717 connman_peer_unregister(connman_peer);
3718 connman_peer_unref(connman_peer);
3721 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
3724 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3726 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3727 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3728 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3729 struct connman_peer *connman_peer;
3730 const char *identifier;
3732 #if defined TIZEN_EXT
3737 identifier = g_supplicant_peer_get_identifier(peer);
3739 DBG("ident: %s", identifier);
3744 connman_peer = connman_peer_get(wifi->device, identifier);
3749 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3750 apply_peer_services(peer, connman_peer);
3751 connman_peer_services_changed(connman_peer);
3753 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3754 if (!g_supplicant_peer_is_in_a_group(peer))
3755 p_state = CONNMAN_PEER_STATE_IDLE;
3757 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3759 case G_SUPPLICANT_PEER_GROUP_STARTED:
3761 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3762 p_state = CONNMAN_PEER_STATE_IDLE;
3764 case G_SUPPLICANT_PEER_GROUP_JOINED:
3765 connman_peer_set_iface_address(connman_peer,
3766 g_supplicant_peer_get_iface_address(peer));
3768 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3769 p_state = CONNMAN_PEER_STATE_IDLE;
3771 case G_SUPPLICANT_PEER_GROUP_FAILED:
3772 if (g_supplicant_peer_has_requested_connection(peer))
3773 p_state = CONNMAN_PEER_STATE_IDLE;
3775 p_state = CONNMAN_PEER_STATE_FAILURE;
3779 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3780 p_state == CONNMAN_PEER_STATE_FAILURE) {
3781 if (wifi->p2p_connecting
3782 && connman_peer == wifi->pending_peer)
3783 peer_cancel_timeout(wifi);
3785 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3788 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3791 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3792 GSupplicantInterface *g_iface;
3793 struct wifi_data *g_wifi;
3795 g_iface = g_supplicant_peer_get_group_interface(peer);
3799 g_wifi = g_supplicant_interface_get_data(g_iface);
3803 connman_peer_set_as_master(connman_peer,
3804 !g_supplicant_peer_is_client(peer));
3805 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3808 * If wpa_supplicant didn't create a dedicated p2p-group
3809 * interface then mark this interface as p2p_device to avoid
3810 * scan and auto-scan are launched on it while P2P is connected.
3812 if (!g_list_find(p2p_iface_list, g_wifi))
3813 wifi->p2p_device = true;
3816 connman_peer_set_state(connman_peer, p_state);
3819 static void peer_request(GSupplicantPeer *peer)
3821 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3822 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3823 struct connman_peer *connman_peer;
3824 const char *identifier;
3826 #if defined TIZEN_EXT
3831 identifier = g_supplicant_peer_get_identifier(peer);
3833 DBG("ident: %s", identifier);
3835 connman_peer = connman_peer_get(wifi->device, identifier);
3839 connman_peer_request_connection(connman_peer);
3842 #if defined TIZEN_EXT
3843 static void system_power_off(void)
3846 struct wifi_data *wifi;
3847 struct connman_service *service;
3848 struct connman_ipconfig *ipconfig_ipv4;
3850 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3851 for (list = iface_list; list; list = list->next) {
3854 if (wifi->network != NULL) {
3855 service = connman_service_lookup_from_network(wifi->network);
3856 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3857 __connman_dhcp_stop(ipconfig_ipv4);
3863 static void network_merged(GSupplicantNetwork *network)
3865 GSupplicantInterface *interface;
3866 GSupplicantState state;
3867 struct wifi_data *wifi;
3868 const char *identifier;
3869 struct connman_network *connman_network;
3873 interface = g_supplicant_network_get_interface(network);
3877 state = g_supplicant_interface_get_state(interface);
3878 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3881 wifi = g_supplicant_interface_get_data(interface);
3885 identifier = g_supplicant_network_get_identifier(network);
3887 connman_network = connman_device_get_network(wifi->device, identifier);
3888 if (!connman_network)
3891 DBG("merged identifier %s", identifier);
3893 if (wifi->connected == FALSE) {
3895 case G_SUPPLICANT_STATE_AUTHENTICATING:
3896 case G_SUPPLICANT_STATE_ASSOCIATING:
3897 case G_SUPPLICANT_STATE_ASSOCIATED:
3898 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3899 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3900 connman_network_set_associating(connman_network, TRUE);
3902 case G_SUPPLICANT_STATE_COMPLETED:
3903 connman_network_set_connected(connman_network, TRUE);
3906 DBG("Not handled the state : %d", state);
3911 ishs20AP = g_supplicant_network_is_hs20AP(network);
3914 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3915 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3916 connman_network_set_string(connman_network, "WiFi.EAP",
3918 connman_network_set_string(connman_network, "WiFi.Identity",
3919 g_supplicant_network_get_identity(network));
3920 connman_network_set_string(connman_network, "WiFi.Phase2",
3921 g_supplicant_network_get_phase2(network));
3926 wifi->network = connman_network;
3929 static void assoc_failed(void *user_data)
3931 struct connman_network *network = user_data;
3932 connman_network_set_associating(network, false);
3936 static void debug(const char *str)
3938 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3939 connman_debug("%s", str);
3942 static void disconnect_reasoncode(GSupplicantInterface *interface,
3945 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3948 wifi->disconnect_code = reasoncode;
3952 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
3954 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3957 wifi->assoc_code = status_code;
3961 static const GSupplicantCallbacks callbacks = {
3962 .system_ready = system_ready,
3963 .system_killed = system_killed,
3964 .interface_added = interface_added,
3965 .interface_state = interface_state,
3966 .interface_removed = interface_removed,
3967 .p2p_support = p2p_support,
3968 .scan_started = scan_started,
3969 .scan_finished = scan_finished,
3970 .ap_create_fail = ap_create_fail,
3971 .network_added = network_added,
3972 .network_removed = network_removed,
3973 .network_changed = network_changed,
3974 .network_associated = network_associated,
3975 .add_station = add_station,
3976 .remove_station = remove_station,
3977 .peer_found = peer_found,
3978 .peer_lost = peer_lost,
3979 .peer_changed = peer_changed,
3980 .peer_request = peer_request,
3981 #if defined TIZEN_EXT
3982 .system_power_off = system_power_off,
3983 .network_merged = network_merged,
3984 .assoc_failed = assoc_failed,
3987 .disconnect_reasoncode = disconnect_reasoncode,
3988 .assoc_status_code = assoc_status_code,
3992 static int tech_probe(struct connman_technology *technology)
3994 wifi_technology = technology;
3999 static void tech_remove(struct connman_technology *technology)
4001 wifi_technology = NULL;
4004 static GSupplicantSSID *ssid_ap_init(const char *ssid,
4005 const char *passphrase)
4007 GSupplicantSSID *ap;
4009 ap = g_try_malloc0(sizeof(GSupplicantSSID));
4013 ap->mode = G_SUPPLICANT_MODE_MASTER;
4015 ap->ssid_len = strlen(ssid);
4019 if (!passphrase || strlen(passphrase) == 0) {
4020 ap->security = G_SUPPLICANT_SECURITY_NONE;
4021 ap->passphrase = NULL;
4023 ap->security = G_SUPPLICANT_SECURITY_PSK;
4024 ap->protocol = G_SUPPLICANT_PROTO_RSN;
4025 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
4026 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
4027 ap->passphrase = passphrase;
4033 static void ap_start_callback(int result, GSupplicantInterface *interface,
4036 struct wifi_tethering_info *info = user_data;
4038 DBG("result %d index %d bridge %s",
4039 result, info->wifi->index, info->wifi->bridge);
4041 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4042 connman_inet_remove_from_bridge(info->wifi->index,
4043 info->wifi->bridge);
4045 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4046 connman_technology_tethering_notify(info->technology, false);
4047 g_free(info->wifi->tethering_param->ssid);
4048 g_free(info->wifi->tethering_param);
4049 info->wifi->tethering_param = NULL;
4053 g_free(info->ifname);
4057 static void ap_create_callback(int result,
4058 GSupplicantInterface *interface,
4061 struct wifi_tethering_info *info = user_data;
4063 DBG("result %d ifname %s", result,
4064 g_supplicant_interface_get_ifname(interface));
4066 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4067 connman_inet_remove_from_bridge(info->wifi->index,
4068 info->wifi->bridge);
4070 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4071 connman_technology_tethering_notify(info->technology, false);
4072 g_free(info->wifi->tethering_param->ssid);
4073 g_free(info->wifi->tethering_param);
4074 info->wifi->tethering_param = NULL;
4078 g_free(info->ifname);
4084 info->wifi->interface = interface;
4085 g_supplicant_interface_set_data(interface, info->wifi);
4087 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
4088 connman_error("Failed to set interface ap_scan property");
4090 g_supplicant_interface_connect(interface, info->ssid,
4091 ap_start_callback, info);
4094 static void sta_remove_callback(int result,
4095 GSupplicantInterface *interface,
4098 struct wifi_tethering_info *info = user_data;
4099 const char *driver = connman_option_get_string("wifi");
4101 DBG("ifname %s result %d ", info->ifname, result);
4103 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4104 info->wifi->tethering = false;
4105 connman_technology_tethering_notify(info->technology, false);
4107 g_free(info->ifname);
4111 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4112 g_free(info->wifi->tethering_param->ssid);
4113 g_free(info->wifi->tethering_param);
4114 info->wifi->tethering_param = NULL;
4119 info->wifi->interface = NULL;
4121 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
4126 static int enable_wifi_tethering(struct connman_technology *technology,
4127 const char *bridge, const char *identifier,
4128 const char *passphrase, bool available)
4131 GSupplicantInterface *interface;
4132 struct wifi_data *wifi;
4133 struct wifi_tethering_info *info;
4138 for (list = iface_list; list; list = list->next) {
4141 DBG("wifi %p network %p pending_network %p", wifi,
4142 wifi->network, wifi->pending_network);
4144 interface = wifi->interface;
4149 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
4152 ifname = g_supplicant_interface_get_ifname(wifi->interface);
4154 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
4155 DBG("%s does not support AP mode (detected)", ifname);
4159 mode = g_supplicant_interface_get_mode(interface);
4160 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
4161 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4162 DBG("%s does not support AP mode (capability)", ifname);
4166 if (wifi->network && available)
4169 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
4173 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
4174 if (!wifi->tethering_param) {
4180 info->technology = technology;
4181 info->wifi->bridge = bridge;
4182 info->ssid = ssid_ap_init(identifier, passphrase);
4186 info->ifname = g_strdup(ifname);
4190 wifi->tethering_param->technology = technology;
4191 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
4192 if (!wifi->tethering_param->ssid)
4195 info->wifi->tethering = true;
4196 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
4198 berr = connman_technology_tethering_notify(technology, true);
4202 err = g_supplicant_interface_remove(interface,
4203 sta_remove_callback,
4206 DBG("tethering wifi %p ifname %s", wifi, ifname);
4211 g_free(info->ifname);
4214 g_free(wifi->tethering_param);
4215 wifi->tethering_param = NULL;
4218 * Remove bridge if it was correctly created but remove
4219 * operation failed. Instead, if bridge creation failed then
4220 * break out and do not try again on another interface,
4221 * bridge set-up does not depend on it.
4224 connman_technology_tethering_notify(technology, false);
4232 static int tech_set_tethering(struct connman_technology *technology,
4233 const char *identifier, const char *passphrase,
4234 const char *bridge, bool enabled)
4237 struct wifi_data *wifi;
4243 for (list = iface_list; list; list = list->next) {
4246 if (wifi->tethering) {
4247 wifi->tethering = false;
4249 connman_inet_remove_from_bridge(wifi->index,
4251 wifi->bridged = false;
4255 connman_technology_tethering_notify(technology, false);
4260 DBG("trying tethering for available devices");
4261 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
4265 DBG("trying tethering for any device");
4266 err = enable_wifi_tethering(technology, bridge, identifier,
4273 static void regdom_callback(int result, const char *alpha2, void *user_data)
4277 if (!wifi_technology)
4283 connman_technology_regdom_notify(wifi_technology, alpha2);
4286 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
4288 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
4291 static struct connman_technology_driver tech_driver = {
4293 .type = CONNMAN_SERVICE_TYPE_WIFI,
4294 .probe = tech_probe,
4295 .remove = tech_remove,
4296 .set_tethering = tech_set_tethering,
4297 .set_regdom = tech_set_regdom,
4300 static int wifi_init(void)
4304 err = connman_network_driver_register(&network_driver);
4308 err = g_supplicant_register(&callbacks);
4310 connman_network_driver_unregister(&network_driver);
4314 err = connman_technology_driver_register(&tech_driver);
4316 g_supplicant_unregister(&callbacks);
4317 connman_network_driver_unregister(&network_driver);
4324 static void wifi_exit(void)
4328 connman_technology_driver_unregister(&tech_driver);
4330 g_supplicant_unregister(&callbacks);
4332 connman_network_driver_unregister(&network_driver);
4335 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
4336 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)