5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <linux/if_arp.h>
34 #include <linux/wireless.h>
35 #include <net/ethernet.h>
38 #define IFF_LOWER_UP 0x10000
41 #include <dbus/dbus.h>
44 #define CONNMAN_API_SUBJECT_TO_CHANGE
45 #include <connman/plugin.h>
46 #include <connman/inet.h>
47 #include <connman/device.h>
48 #include <connman/rtnl.h>
49 #include <connman/technology.h>
50 #include <connman/service.h>
51 #include <connman/peer.h>
52 #include <connman/log.h>
53 #include <connman/option.h>
54 #include <connman/storage.h>
55 #include <include/setting.h>
56 #include <connman/provision.h>
57 #include <connman/utsname.h>
58 #include <connman/machine.h>
60 #include <gsupplicant/gsupplicant.h>
62 #define CLEANUP_TIMEOUT 8 /* in seconds */
63 #define INACTIVE_TIMEOUT 12 /* in seconds */
64 #define FAVORITE_MAXIMUM_RETRIES 2
66 #define BGSCAN_DEFAULT "simple:30:-45:300"
67 #define AUTOSCAN_DEFAULT "exponential:3:300"
69 #define P2P_FIND_TIMEOUT 30
70 #define P2P_CONNECTION_TIMEOUT 100
71 #define P2P_LISTEN_PERIOD 500
72 #define P2P_LISTEN_INTERVAL 2000
74 #define ASSOC_STATUS_NO_CLIENT 17
75 #define LOAD_SHAPING_MAX_RETRIES 3
78 #define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
81 static struct connman_technology *wifi_technology = NULL;
82 static struct connman_technology *p2p_technology = NULL;
84 enum wifi_ap_capability{
86 WIFI_AP_SUPPORTED = 1,
87 WIFI_AP_NOT_SUPPORTED = 2,
90 struct hidden_params {
92 unsigned int ssid_len;
94 char *anonymous_identity;
96 char *altsubject_match;
97 char *domain_suffix_match;
101 GSupplicantScanParams *scan_params;
106 * Used for autoscan "emulation".
107 * Should be removed when wpa_s autoscan support will be by default.
109 struct autoscan_params {
113 unsigned int timeout;
116 struct wifi_tethering_info {
117 struct wifi_data *wifi;
118 struct connman_technology *technology;
120 GSupplicantSSID *ssid;
125 struct connman_device *device;
126 struct connman_network *network;
127 struct connman_network *pending_network;
129 GSupplicantInterface *interface;
130 GSupplicantState state;
134 enum wifi_ap_capability ap_supported;
136 bool interface_ready;
142 int load_shaping_retries;
143 struct hidden_params *hidden;
144 bool postpone_hidden;
145 struct wifi_tethering_info *tethering_param;
147 * autoscan "emulation".
149 struct autoscan_params *autoscan;
151 GSupplicantScanParams *scan_params;
152 unsigned int p2p_find_timeout;
153 unsigned int p2p_connection_timeout;
154 struct connman_peer *pending_peer;
159 #if defined TIZEN_EXT
160 int assoc_retry_count;
161 struct connman_network *scan_pending_network;
162 bool allow_full_scan;
168 #if defined TIZEN_EXT
172 #define TIZEN_ASSOC_RETRY_COUNT 4
174 static gboolean wifi_first_scan = false;
175 static gboolean found_with_first_scan = false;
176 static gboolean is_wifi_notifier_registered = false;
180 static GList *iface_list = NULL;
182 static GList *pending_wifi_device = NULL;
183 static GList *p2p_iface_list = NULL;
184 bool wfd_service_registered = false;
186 static void start_autoscan(struct connman_device *device);
188 static int tech_set_tethering(struct connman_technology *technology,
189 const char *identifier, const char *passphrase,
190 const char *bridge, bool enabled);
192 #if defined TIZEN_EXT
193 #define NETCONFIG_SERVICE "net.netconfig"
194 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
195 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
197 struct enc_method_call_data {
198 DBusConnection *connection;
199 struct connman_network *network;
202 static struct enc_method_call_data encrypt_request_data;
204 static void encryption_request_reply(DBusPendingCall *call,
209 DBusMessageIter args;
211 struct connman_service *service;
212 gchar* encrypted_value = NULL;
213 struct connman_network *network = encrypt_request_data.network;
217 reply = dbus_pending_call_steal_reply(call);
219 dbus_error_init(&error);
220 if (dbus_set_error_from_message(&error, reply)) {
221 DBG("send_encryption_request() %s %s", error.name, error.message);
222 dbus_error_free(&error);
226 if (dbus_message_iter_init(reply, &args) == FALSE)
229 dbus_message_iter_get_basic(&args, &out_data);
231 encrypted_value = g_strdup((const gchar *)out_data);
232 service = connman_service_lookup_from_network(network);
235 DBG("encryption result: no service");
239 if (connman_service_get_favorite(service)) {
240 __connman_service_set_passphrase(service, encrypted_value);
241 __connman_service_save(service);
243 connman_network_set_string(network, "WiFi.Passphrase",
246 DBG("encryption result: succeeded");
249 dbus_message_unref(reply);
250 dbus_pending_call_unref(call);
251 dbus_connection_unref(encrypt_request_data.connection);
252 g_free(encrypted_value);
254 encrypt_request_data.connection = NULL;
255 encrypt_request_data.network = NULL;
258 static int send_encryption_request(const char *passphrase,
259 struct connman_network *network)
261 DBusConnection *connection = NULL;
262 DBusMessage *msg = NULL;
263 DBusPendingCall *call;
266 DBG("Invalid parameter");
270 connection = connman_dbus_get_connection();
272 DBG("dbus connection does not exist");
276 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
277 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
279 dbus_connection_unref(connection);
283 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
286 if (!dbus_connection_send_with_reply(connection, msg,
287 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
288 dbus_message_unref(msg);
289 dbus_connection_unref(connection);
294 dbus_message_unref(msg);
295 dbus_connection_unref(connection);
299 encrypt_request_data.connection = connection;
300 encrypt_request_data.network = network;
302 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
303 dbus_message_unref(msg);
309 static int p2p_tech_probe(struct connman_technology *technology)
311 p2p_technology = technology;
316 static void p2p_tech_remove(struct connman_technology *technology)
318 p2p_technology = NULL;
321 static struct connman_technology_driver p2p_tech_driver = {
323 .type = CONNMAN_SERVICE_TYPE_P2P,
324 .probe = p2p_tech_probe,
325 .remove = p2p_tech_remove,
328 static bool is_p2p_connecting(void)
332 for (list = iface_list; list; list = list->next) {
333 struct wifi_data *wifi = list->data;
335 if (wifi->p2p_connecting)
342 static void add_pending_wifi_device(struct wifi_data *wifi)
344 if (g_list_find(pending_wifi_device, wifi))
347 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
350 static struct wifi_data *get_pending_wifi_data(const char *ifname)
354 for (list = pending_wifi_device; list; list = list->next) {
355 struct wifi_data *wifi;
356 const char *dev_name;
359 if (!wifi || !wifi->device)
362 dev_name = connman_device_get_string(wifi->device, "Interface");
363 if (!g_strcmp0(ifname, dev_name)) {
364 pending_wifi_device = g_list_delete_link(
365 pending_wifi_device, list);
373 static void remove_pending_wifi_device(struct wifi_data *wifi)
377 link = g_list_find(pending_wifi_device, wifi);
382 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
385 static void peer_cancel_timeout(struct wifi_data *wifi)
387 if (wifi->p2p_connection_timeout > 0)
388 g_source_remove(wifi->p2p_connection_timeout);
390 wifi->p2p_connection_timeout = 0;
391 wifi->p2p_connecting = false;
393 if (wifi->pending_peer) {
394 connman_peer_unref(wifi->pending_peer);
395 wifi->pending_peer = NULL;
399 static gboolean peer_connect_timeout(gpointer data)
401 struct wifi_data *wifi = data;
405 if (wifi->p2p_connecting) {
406 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
407 GSupplicantPeer *gs_peer =
408 g_supplicant_interface_peer_lookup(wifi->interface,
409 connman_peer_get_identifier(wifi->pending_peer));
411 if (g_supplicant_peer_has_requested_connection(gs_peer))
412 state = CONNMAN_PEER_STATE_IDLE;
414 connman_peer_set_state(wifi->pending_peer, state);
417 peer_cancel_timeout(wifi);
422 static void peer_connect_callback(int result, GSupplicantInterface *interface,
425 struct wifi_data *wifi = user_data;
426 struct connman_peer *peer = wifi->pending_peer;
428 DBG("peer %p - %d", peer, result);
434 peer_connect_timeout(wifi);
438 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
440 wifi->p2p_connection_timeout = g_timeout_add_seconds(
441 P2P_CONNECTION_TIMEOUT,
442 peer_connect_timeout, wifi);
445 static int peer_connect(struct connman_peer *peer,
446 enum connman_peer_wps_method wps_method,
449 struct connman_device *device = connman_peer_get_device(peer);
450 GSupplicantPeerParams *peer_params;
451 GSupplicantPeer *gs_peer;
452 struct wifi_data *wifi;
456 DBG("peer %p", peer);
461 wifi = connman_device_get_data(device);
462 if (!wifi || !wifi->interface)
465 if (wifi->p2p_connecting)
468 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
469 connman_peer_get_identifier(peer));
473 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
474 pin = g_supplicant_peer_is_wps_pin(gs_peer);
476 switch (wps_method) {
477 case CONNMAN_PEER_WPS_UNKNOWN:
478 if ((pbc && pin) || pin)
481 case CONNMAN_PEER_WPS_PBC:
486 case CONNMAN_PEER_WPS_PIN:
487 if (!pin || !wps_pin)
492 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
496 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
498 peer_params->wps_pin = g_strdup(wps_pin);
500 peer_params->master = connman_peer_service_is_master();
502 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
503 peer_connect_callback, wifi);
504 if (ret == -EINPROGRESS) {
505 wifi->pending_peer = connman_peer_ref(peer);
506 wifi->p2p_connecting = true;
507 } else if (ret < 0) {
508 g_free(peer_params->path);
509 g_free(peer_params->wps_pin);
516 static int peer_disconnect(struct connman_peer *peer)
518 struct connman_device *device = connman_peer_get_device(peer);
519 GSupplicantPeerParams peer_params = {};
520 GSupplicantPeer *gs_peer;
521 struct wifi_data *wifi;
524 DBG("peer %p", peer);
529 wifi = connman_device_get_data(device);
533 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
534 connman_peer_get_identifier(peer));
538 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
540 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
542 g_free(peer_params.path);
544 if (ret == -EINPROGRESS) {
545 peer_cancel_timeout(wifi);
546 wifi->p2p_device = false;
552 struct peer_service_registration {
553 peer_service_registration_cb_t callback;
557 static bool is_service_wfd(const unsigned char *specs, int length)
559 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
565 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
567 struct wifi_data *wifi = data;
569 if (!wifi->interface ||
570 !g_supplicant_interface_has_p2p(wifi->interface))
573 if (!wifi->servicing) {
574 g_supplicant_interface_p2p_listen(wifi->interface,
575 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
581 static void register_wfd_service_cb(int result,
582 GSupplicantInterface *iface, void *user_data)
584 struct peer_service_registration *reg_data = user_data;
589 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
591 if (reg_data && reg_data->callback) {
592 reg_data->callback(result, reg_data->user_data);
597 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
598 const unsigned char *spec,
599 int spec_length, const unsigned char *query,
600 int query_length, int version)
602 GSupplicantP2PServiceParams *params;
604 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
609 params->version = version;
610 params->service = g_memdup(spec, spec_length);
611 } else if (query_length > 0 && spec_length > 0) {
612 params->query = g_memdup(query, query_length);
613 params->query_length = query_length;
615 params->response = g_memdup(spec, spec_length);
616 params->response_length = spec_length;
618 params->wfd_ies = g_memdup(spec, spec_length);
619 params->wfd_ies_length = spec_length;
625 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
630 g_free(params->service);
631 g_free(params->query);
632 g_free(params->response);
633 g_free(params->wfd_ies);
638 static int peer_register_wfd_service(const unsigned char *specification,
639 int specification_length,
640 peer_service_registration_cb_t callback,
643 struct peer_service_registration *reg_data = NULL;
644 static GSupplicantP2PServiceParams *params;
649 if (wfd_service_registered)
652 params = fill_in_peer_service_params(specification,
653 specification_length, NULL, 0, 0);
657 reg_data = g_try_malloc0(sizeof(*reg_data));
663 reg_data->callback = callback;
664 reg_data->user_data = user_data;
666 ret = g_supplicant_set_widi_ies(params,
667 register_wfd_service_cb, reg_data);
668 if (ret < 0 && ret != -EINPROGRESS)
671 wfd_service_registered = true;
675 free_peer_service_params(params);
681 static void register_peer_service_cb(int result,
682 GSupplicantInterface *iface, void *user_data)
684 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
685 struct peer_service_registration *reg_data = user_data;
687 #if defined TIZEN_EXT
695 apply_p2p_listen_on_iface(wifi, NULL);
697 if (reg_data->callback)
698 reg_data->callback(result, reg_data->user_data);
703 static int peer_register_service(const unsigned char *specification,
704 int specification_length,
705 const unsigned char *query,
706 int query_length, int version,
707 peer_service_registration_cb_t callback,
710 struct peer_service_registration *reg_data;
711 GSupplicantP2PServiceParams *params;
718 if (specification && !version && !query &&
719 is_service_wfd(specification, specification_length)) {
720 return peer_register_wfd_service(specification,
721 specification_length, callback, user_data);
724 reg_data = g_try_malloc0(sizeof(*reg_data));
728 reg_data->callback = callback;
729 reg_data->user_data = user_data;
733 for (list = iface_list; list; list = list->next) {
734 struct wifi_data *wifi = list->data;
735 GSupplicantInterface *iface = wifi->interface;
737 if (!g_supplicant_interface_has_p2p(iface))
740 params = fill_in_peer_service_params(specification,
741 specification_length, query,
742 query_length, version);
749 ret_f = g_supplicant_interface_p2p_add_service(iface,
750 register_peer_service_cb, params, reg_data);
751 if (ret_f == 0 || ret_f == -EINPROGRESS)
755 ret = g_supplicant_interface_p2p_add_service(iface,
756 register_peer_service_cb, params, NULL);
757 if (ret != 0 && ret != -EINPROGRESS)
758 free_peer_service_params(params);
761 if (ret_f != 0 && ret_f != -EINPROGRESS)
767 static int peer_unregister_wfd_service(void)
769 GSupplicantP2PServiceParams *params;
772 if (!wfd_service_registered)
775 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
779 wfd_service_registered = false;
781 g_supplicant_set_widi_ies(params, NULL, NULL);
783 for (list = iface_list; list; list = list->next) {
784 struct wifi_data *wifi = list->data;
786 if (!g_supplicant_interface_has_p2p(wifi->interface))
790 if (!wifi->servicing || wifi->servicing < 0) {
791 g_supplicant_interface_p2p_listen(wifi->interface,
800 static int peer_unregister_service(const unsigned char *specification,
801 int specification_length,
802 const unsigned char *query,
803 int query_length, int version)
805 GSupplicantP2PServiceParams *params;
810 if (specification && !version && !query &&
811 is_service_wfd(specification, specification_length)) {
812 ret = peer_unregister_wfd_service();
813 if (ret != 0 && ret != -EINPROGRESS)
818 for (list = iface_list; list; list = list->next) {
819 struct wifi_data *wifi = list->data;
820 GSupplicantInterface *iface = wifi->interface;
825 if (!g_supplicant_interface_has_p2p(iface))
828 params = fill_in_peer_service_params(specification,
829 specification_length, query,
830 query_length, version);
836 ret = g_supplicant_interface_p2p_del_service(iface, params);
837 if (ret != 0 && ret != -EINPROGRESS)
838 free_peer_service_params(params);
841 if (!wifi->servicing || wifi->servicing < 0) {
842 g_supplicant_interface_p2p_listen(iface, 0, 0);
850 static struct connman_peer_driver peer_driver = {
851 .connect = peer_connect,
852 .disconnect = peer_disconnect,
853 .register_service = peer_register_service,
854 .unregister_service = peer_unregister_service,
857 static void handle_tethering(struct wifi_data *wifi)
859 if (!wifi->tethering)
868 DBG("index %d bridge %s", wifi->index, wifi->bridge);
870 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
873 wifi->bridged = true;
876 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
878 struct connman_device *device = user_data;
879 struct wifi_data *wifi = connman_device_get_data(device);
884 DBG("index %d flags %d change %d", wifi->index, flags, change);
886 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
890 DBG("interface down");
893 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
894 if (flags & IFF_LOWER_UP) {
897 handle_tethering(wifi);
905 static int wifi_probe(struct connman_device *device)
907 struct wifi_data *wifi;
909 DBG("device %p", device);
911 wifi = g_try_new0(struct wifi_data, 1);
915 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
916 wifi->ap_supported = WIFI_AP_UNKNOWN;
917 wifi->tethering_param = NULL;
919 connman_device_set_data(device, wifi);
920 wifi->device = connman_device_ref(device);
922 wifi->index = connman_device_get_index(device);
925 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
926 wifi_newlink, device);
927 if (is_p2p_connecting())
928 add_pending_wifi_device(wifi);
930 iface_list = g_list_append(iface_list, wifi);
935 static void remove_networks(struct connman_device *device,
936 struct wifi_data *wifi)
940 for (list = wifi->networks; list; list = list->next) {
941 struct connman_network *network = list->data;
943 connman_device_remove_network(device, network);
944 connman_network_unref(network);
947 g_slist_free(wifi->networks);
948 wifi->networks = NULL;
951 static void remove_peers(struct wifi_data *wifi)
955 for (list = wifi->peers; list; list = list->next) {
956 struct connman_peer *peer = list->data;
958 connman_peer_unregister(peer);
959 connman_peer_unref(peer);
962 g_slist_free(wifi->peers);
966 static void reset_autoscan(struct connman_device *device)
968 struct wifi_data *wifi = connman_device_get_data(device);
969 struct autoscan_params *autoscan;
973 if (!wifi || !wifi->autoscan)
976 autoscan = wifi->autoscan;
978 if (autoscan->timeout == 0 && autoscan->interval == 0)
981 g_source_remove(autoscan->timeout);
983 autoscan->timeout = 0;
984 autoscan->interval = 0;
986 connman_device_unref(device);
989 static void stop_autoscan(struct connman_device *device)
991 const struct wifi_data *wifi = connman_device_get_data(device);
993 if (!wifi || !wifi->autoscan)
996 reset_autoscan(device);
998 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
1001 static void check_p2p_technology(void)
1003 bool p2p_exists = false;
1006 for (list = iface_list; list; list = list->next) {
1007 struct wifi_data *w = list->data;
1010 g_supplicant_interface_has_p2p(w->interface))
1015 connman_technology_driver_unregister(&p2p_tech_driver);
1016 connman_peer_driver_unregister(&peer_driver);
1020 static void wifi_remove(struct connman_device *device)
1022 struct wifi_data *wifi = connman_device_get_data(device);
1024 DBG("device %p wifi %p", device, wifi);
1029 stop_autoscan(device);
1031 if (wifi->p2p_device)
1032 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1034 iface_list = g_list_remove(iface_list, wifi);
1036 check_p2p_technology();
1038 remove_pending_wifi_device(wifi);
1040 if (wifi->p2p_find_timeout) {
1041 g_source_remove(wifi->p2p_find_timeout);
1042 connman_device_unref(wifi->device);
1045 if (wifi->p2p_connection_timeout)
1046 g_source_remove(wifi->p2p_connection_timeout);
1048 remove_networks(device, wifi);
1051 connman_device_set_powered(device, false);
1052 connman_device_set_data(device, NULL);
1053 connman_device_unref(wifi->device);
1054 connman_rtnl_remove_watch(wifi->watch);
1056 g_supplicant_interface_set_data(wifi->interface, NULL);
1058 g_supplicant_interface_cancel(wifi->interface);
1060 if (wifi->scan_params)
1061 g_supplicant_free_scan_params(wifi->scan_params);
1063 g_free(wifi->autoscan);
1064 g_free(wifi->identifier);
1068 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1072 for (iter = list; iter; iter = g_slist_next(iter)) {
1073 struct scan_ssid *scan_ssid = iter->data;
1075 if (ssid_len == scan_ssid->ssid_len &&
1076 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1083 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1084 int freq, GSupplicantScanParams *scan_data,
1085 int driver_max_scan_ssids, char *ssid_name)
1088 struct scan_ssid *scan_ssid;
1090 if ((driver_max_scan_ssids == 0 ||
1091 driver_max_scan_ssids > scan_data->num_ssids) &&
1092 (hex_ssid || raw_ssid)) {
1094 unsigned int j = 0, hex;
1097 size_t hex_ssid_len = strlen(hex_ssid);
1099 ssid = g_try_malloc0(hex_ssid_len / 2);
1103 for (i = 0; i < hex_ssid_len; i += 2) {
1104 sscanf(hex_ssid + i, "%02x", &hex);
1113 * If we have already added hidden AP to the list,
1114 * then do not do it again. This might happen if you have
1115 * used or are using multiple wifi cards, so in that case
1116 * you might have multiple service files for same AP.
1118 if (is_duplicate(scan_data->ssids, ssid, j)) {
1124 scan_ssid = g_try_new(struct scan_ssid, 1);
1131 memcpy(scan_ssid->ssid, ssid, j);
1132 scan_ssid->ssid_len = j;
1133 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1136 scan_data->num_ssids++;
1138 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1139 scan_data->num_ssids);
1146 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1148 if (!scan_data->freqs) {
1149 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1150 if (!scan_data->freqs) {
1151 g_slist_free_full(scan_data->ssids, g_free);
1155 scan_data->num_freqs = 1;
1156 scan_data->freqs[0] = freq;
1158 bool duplicate = false;
1160 /* Don't add duplicate entries */
1161 for (i = 0; i < scan_data->num_freqs; i++) {
1162 if (scan_data->freqs[i] == freq) {
1169 scan_data->num_freqs++;
1170 scan_data->freqs = g_try_realloc(scan_data->freqs,
1171 sizeof(uint16_t) * scan_data->num_freqs);
1172 if (!scan_data->freqs) {
1173 g_slist_free_full(scan_data->ssids, g_free);
1176 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1183 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1185 struct connman_config_entry **entries;
1191 int num_ssids = 0, add_param_failed = 0;
1193 services = connman_storage_get_services();
1194 for (i = 0; services && services[i]; i++) {
1195 if (strncmp(services[i], "wifi_", 5) != 0)
1198 keyfile = connman_storage_load_service(services[i]);
1202 value = g_key_file_get_boolean(keyfile,
1203 services[i], "Hidden", NULL);
1205 g_key_file_free(keyfile);
1209 value = g_key_file_get_boolean(keyfile,
1210 services[i], "Favorite", NULL);
1212 g_key_file_free(keyfile);
1216 #if defined TIZEN_EXT
1217 value = g_key_file_get_boolean(keyfile,
1218 services[i], "AutoConnect", NULL);
1220 g_key_file_free(keyfile);
1225 ssid = g_key_file_get_string(keyfile,
1226 services[i], "SSID", NULL);
1228 name = g_key_file_get_string(keyfile, services[i], "Name",
1231 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1239 g_key_file_free(keyfile);
1243 * Check if there are any hidden AP that needs to be provisioned.
1245 entries = connman_config_get_entries("wifi");
1246 for (i = 0; entries && entries[i]; i++) {
1249 if (!entries[i]->hidden)
1252 if (!entries[i]->ssid) {
1253 ssid = entries[i]->name;
1256 ssid = entries[i]->ssid;
1257 len = entries[i]->ssid_len;
1263 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1270 connman_config_free_entries(entries);
1272 if (add_param_failed > 0)
1273 DBG("Unable to scan %d out of %d SSIDs",
1274 add_param_failed, num_ssids);
1276 g_strfreev(services);
1281 static int get_hidden_connections_params(struct wifi_data *wifi,
1282 GSupplicantScanParams *scan_params)
1284 int driver_max_ssids, i;
1285 GSupplicantScanParams *orig_params;
1288 * Scan hidden networks so that we can autoconnect to them.
1289 * We will assume 1 as a default number of ssid to scan.
1291 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1293 if (driver_max_ssids == 0)
1294 driver_max_ssids = 1;
1296 DBG("max ssids %d", driver_max_ssids);
1298 if (!wifi->scan_params) {
1299 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1300 if (!wifi->scan_params)
1303 if (get_hidden_connections(wifi->scan_params) == 0) {
1304 g_supplicant_free_scan_params(wifi->scan_params);
1305 wifi->scan_params = NULL;
1311 orig_params = wifi->scan_params;
1313 /* Let's transfer driver_max_ssids params */
1314 for (i = 0; i < driver_max_ssids; i++) {
1315 struct scan_ssid *ssid;
1317 if (!wifi->scan_params->ssids)
1320 ssid = orig_params->ssids->data;
1321 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1322 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1326 scan_params->num_ssids = i;
1327 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1329 scan_params->freqs = g_memdup(orig_params->freqs,
1330 sizeof(uint16_t) * orig_params->num_freqs);
1331 if (!scan_params->freqs)
1334 scan_params->num_freqs = orig_params->num_freqs;
1339 orig_params->num_ssids -= scan_params->num_ssids;
1341 return scan_params->num_ssids;
1344 g_slist_free_full(scan_params->ssids, g_free);
1345 g_supplicant_free_scan_params(wifi->scan_params);
1346 wifi->scan_params = NULL;
1351 static int throw_wifi_scan(struct connman_device *device,
1352 GSupplicantInterfaceCallback callback)
1354 struct wifi_data *wifi = connman_device_get_data(device);
1360 DBG("device %p %p", device, wifi->interface);
1362 if (wifi->tethering)
1364 #if defined TIZEN_EXT
1365 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1367 if (connman_device_get_scanning(device))
1371 connman_device_ref(device);
1373 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1376 connman_device_set_scanning(device,
1377 CONNMAN_SERVICE_TYPE_WIFI, true);
1379 connman_device_unref(device);
1384 static void hidden_free(struct hidden_params *hidden)
1389 if (hidden->scan_params)
1390 g_supplicant_free_scan_params(hidden->scan_params);
1391 g_free(hidden->identity);
1392 g_free(hidden->passphrase);
1393 g_free(hidden->security);
1397 #if defined TIZEN_EXT
1398 static void service_state_changed(struct connman_service *service,
1399 enum connman_service_state state);
1401 static int network_connect(struct connman_network *network);
1403 static struct connman_notifier notifier = {
1405 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1406 .service_state_changed = service_state_changed,
1409 static void service_state_changed(struct connman_service *service,
1410 enum connman_service_state state)
1412 enum connman_service_type type;
1414 type = connman_service_get_type(service);
1415 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1418 DBG("service %p state %d", service, state);
1421 case CONNMAN_SERVICE_STATE_READY:
1422 case CONNMAN_SERVICE_STATE_ONLINE:
1423 case CONNMAN_SERVICE_STATE_FAILURE:
1424 connman_notifier_unregister(¬ifier);
1425 is_wifi_notifier_registered = FALSE;
1427 __connman_device_request_scan(type);
1436 static void scan_callback(int result, GSupplicantInterface *interface,
1439 struct connman_device *device = user_data;
1440 struct wifi_data *wifi = connman_device_get_data(device);
1443 DBG("result %d wifi %p", result, wifi);
1446 if (wifi->hidden && !wifi->postpone_hidden) {
1447 connman_network_clear_hidden(wifi->hidden->user_data);
1448 hidden_free(wifi->hidden);
1449 wifi->hidden = NULL;
1452 if (wifi->scan_params) {
1453 g_supplicant_free_scan_params(wifi->scan_params);
1454 wifi->scan_params = NULL;
1459 connman_device_reset_scanning(device);
1461 /* User is connecting to a hidden AP, let's wait for finished event */
1462 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1463 GSupplicantScanParams *scan_params;
1466 wifi->postpone_hidden = false;
1467 scan_params = wifi->hidden->scan_params;
1468 wifi->hidden->scan_params = NULL;
1470 reset_autoscan(device);
1472 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1473 scan_callback, device);
1477 /* On error, let's recall scan_callback, which will cleanup */
1478 return scan_callback(ret, interface, user_data);
1481 #if defined TIZEN_EXT
1482 if (wifi && wifi->allow_full_scan) {
1484 DBG("Trigger Full Channel Scan");
1485 wifi->allow_full_scan = FALSE;
1487 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1488 scan_callback, device);
1492 /* On error, let's recall scan_callback, which will cleanup */
1493 return scan_callback(ret, interface, user_data);
1497 scanning = connman_device_get_scanning(device);
1499 connman_device_set_scanning(device,
1500 CONNMAN_SERVICE_TYPE_WIFI, false);
1502 if (result != -ENOLINK)
1503 #if defined TIZEN_EXT
1506 start_autoscan(device);
1509 * If we are here then we were scanning; however, if we are
1510 * also mid-flight disabling the interface, then wifi_disable
1511 * has already cleared the device scanning state and
1512 * unreferenced the device, obviating the need to do it here.
1516 connman_device_unref(device);
1518 #if defined TIZEN_EXT
1519 if (wifi && wifi->scan_pending_network && result != -EIO) {
1520 network_connect(wifi->scan_pending_network);
1521 wifi->scan_pending_network = NULL;
1522 connman_network_set_connecting(wifi->network);
1525 if (is_wifi_notifier_registered != true &&
1526 wifi_first_scan == true && found_with_first_scan == true) {
1527 wifi_first_scan = false;
1528 found_with_first_scan = false;
1530 connman_notifier_register(¬ifier);
1531 is_wifi_notifier_registered = true;
1536 static void scan_callback_hidden(int result,
1537 GSupplicantInterface *interface, void *user_data)
1539 struct connman_device *device = user_data;
1540 struct wifi_data *wifi = connman_device_get_data(device);
1541 GSupplicantScanParams *scan_params;
1544 DBG("result %d wifi %p", result, wifi);
1549 /* User is trying to connect to a hidden AP */
1550 if (wifi->hidden && wifi->postpone_hidden)
1553 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1557 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1558 ret = g_supplicant_interface_scan(wifi->interface,
1560 scan_callback_hidden,
1566 g_supplicant_free_scan_params(scan_params);
1569 scan_callback(result, interface, user_data);
1572 static gboolean autoscan_timeout(gpointer data)
1574 struct connman_device *device = data;
1575 struct wifi_data *wifi = connman_device_get_data(device);
1576 struct autoscan_params *autoscan;
1582 autoscan = wifi->autoscan;
1584 if (autoscan->interval <= 0) {
1585 interval = autoscan->base;
1588 interval = autoscan->interval * autoscan->base;
1590 #if defined TIZEN_EXT
1591 if (autoscan->interval >= autoscan->limit)
1593 if (interval > autoscan->limit)
1595 interval = autoscan->limit;
1597 throw_wifi_scan(wifi->device, scan_callback_hidden);
1600 DBG("interval %d", interval);
1602 autoscan->interval = interval;
1604 autoscan->timeout = g_timeout_add_seconds(interval,
1605 autoscan_timeout, device);
1610 static void start_autoscan(struct connman_device *device)
1612 struct wifi_data *wifi = connman_device_get_data(device);
1613 struct autoscan_params *autoscan;
1620 if (wifi->p2p_device)
1623 if (wifi->connected)
1626 autoscan = wifi->autoscan;
1630 if (autoscan->timeout > 0 || autoscan->interval > 0)
1633 connman_device_ref(device);
1635 autoscan_timeout(device);
1638 static struct autoscan_params *parse_autoscan_params(const char *params)
1640 struct autoscan_params *autoscan;
1645 DBG("Emulating autoscan");
1647 list_params = g_strsplit(params, ":", 0);
1648 if (list_params == 0)
1651 if (g_strv_length(list_params) < 3) {
1652 g_strfreev(list_params);
1656 base = atoi(list_params[1]);
1657 limit = atoi(list_params[2]);
1659 g_strfreev(list_params);
1661 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1663 DBG("Could not allocate memory for autoscan");
1667 DBG("base %d - limit %d", base, limit);
1668 autoscan->base = base;
1669 autoscan->limit = limit;
1674 static void setup_autoscan(struct wifi_data *wifi)
1676 if (!wifi->autoscan)
1677 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1679 start_autoscan(wifi->device);
1682 static void finalize_interface_creation(struct wifi_data *wifi)
1684 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1686 if (!wifi->device) {
1687 connman_error("WiFi device not set");
1691 connman_device_set_powered(wifi->device, true);
1693 if (!connman_setting_get_bool("BackgroundScanning"))
1696 if (wifi->p2p_device)
1699 setup_autoscan(wifi);
1702 static void interface_create_callback(int result,
1703 GSupplicantInterface *interface,
1706 struct wifi_data *wifi = user_data;
1708 DBG("result %d ifname %s, wifi %p", result,
1709 g_supplicant_interface_get_ifname(interface),
1712 if (result < 0 || !wifi)
1715 wifi->interface = interface;
1716 g_supplicant_interface_set_data(interface, wifi);
1718 if (g_supplicant_interface_get_ready(interface)) {
1719 wifi->interface_ready = true;
1720 finalize_interface_creation(wifi);
1724 static int wifi_enable(struct connman_device *device)
1726 struct wifi_data *wifi = connman_device_get_data(device);
1729 const char *driver = connman_option_get_string("wifi");
1732 DBG("device %p %p", device, wifi);
1734 index = connman_device_get_index(device);
1735 if (!wifi || index < 0)
1738 if (is_p2p_connecting())
1739 return -EINPROGRESS;
1741 interface = connman_inet_ifname(index);
1742 ret = g_supplicant_interface_create(interface, driver, NULL,
1743 interface_create_callback,
1750 return -EINPROGRESS;
1753 static int wifi_disable(struct connman_device *device)
1755 struct wifi_data *wifi = connman_device_get_data(device);
1758 DBG("device %p wifi %p", device, wifi);
1763 wifi->connected = false;
1764 wifi->disconnecting = false;
1766 if (wifi->pending_network)
1767 wifi->pending_network = NULL;
1769 stop_autoscan(device);
1771 if (wifi->p2p_find_timeout) {
1772 g_source_remove(wifi->p2p_find_timeout);
1773 wifi->p2p_find_timeout = 0;
1774 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1775 connman_device_unref(wifi->device);
1778 /* In case of a user scan, device is still referenced */
1779 if (connman_device_get_scanning(device)) {
1780 connman_device_set_scanning(device,
1781 CONNMAN_SERVICE_TYPE_WIFI, false);
1782 connman_device_unref(wifi->device);
1785 remove_networks(device, wifi);
1788 #if defined TIZEN_EXT
1789 wifi->scan_pending_network = NULL;
1791 if (is_wifi_notifier_registered == true) {
1792 connman_notifier_unregister(¬ifier);
1793 is_wifi_notifier_registered = false;
1797 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1801 return -EINPROGRESS;
1804 struct last_connected {
1810 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1812 GTimeVal *aval = (GTimeVal *)a;
1813 GTimeVal *bval = (GTimeVal *)b;
1815 /* Note that the sort order is descending */
1816 if (aval->tv_sec < bval->tv_sec)
1819 if (aval->tv_sec > bval->tv_sec)
1825 static void free_entry(gpointer data)
1827 struct last_connected *entry = data;
1829 g_free(entry->ssid);
1833 static int get_latest_connections(int max_ssids,
1834 GSupplicantScanParams *scan_data)
1836 GSequenceIter *iter;
1837 GSequence *latest_list;
1838 struct last_connected *entry;
1847 latest_list = g_sequence_new(free_entry);
1851 services = connman_storage_get_services();
1852 for (i = 0; services && services[i]; i++) {
1853 if (strncmp(services[i], "wifi_", 5) != 0)
1856 keyfile = connman_storage_load_service(services[i]);
1860 str = g_key_file_get_string(keyfile,
1861 services[i], "Favorite", NULL);
1862 if (!str || g_strcmp0(str, "true")) {
1864 g_key_file_free(keyfile);
1869 str = g_key_file_get_string(keyfile,
1870 services[i], "AutoConnect", NULL);
1871 if (!str || g_strcmp0(str, "true")) {
1873 g_key_file_free(keyfile);
1878 str = g_key_file_get_string(keyfile,
1879 services[i], "Modified", NULL);
1881 g_key_file_free(keyfile);
1884 g_time_val_from_iso8601(str, &modified);
1887 ssid = g_key_file_get_string(keyfile,
1888 services[i], "SSID", NULL);
1890 freq = g_key_file_get_integer(keyfile, services[i],
1893 entry = g_try_new(struct last_connected, 1);
1895 g_sequence_free(latest_list);
1896 g_key_file_free(keyfile);
1902 entry->modified = modified;
1905 g_sequence_insert_sorted(latest_list, entry,
1911 g_key_file_free(keyfile);
1914 g_strfreev(services);
1916 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1918 iter = g_sequence_get_begin_iter(latest_list);
1920 for (i = 0; i < num_ssids; i++) {
1921 entry = g_sequence_get(iter);
1923 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1924 entry->modified.tv_sec);
1926 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1927 max_ssids, entry->ssid);
1929 iter = g_sequence_iter_next(iter);
1932 g_sequence_free(latest_list);
1936 static int wifi_scan_simple(struct connman_device *device)
1938 reset_autoscan(device);
1940 return throw_wifi_scan(device, scan_callback_hidden);
1943 static gboolean p2p_find_stop(gpointer data)
1945 struct connman_device *device = data;
1946 struct wifi_data *wifi = connman_device_get_data(device);
1951 wifi->p2p_find_timeout = 0;
1953 g_supplicant_interface_p2p_stop_find(wifi->interface);
1956 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1958 connman_device_unref(device);
1959 reset_autoscan(device);
1964 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1967 struct connman_device *device = user_data;
1968 struct wifi_data *wifi = connman_device_get_data(device);
1970 DBG("result %d wifi %p", result, wifi);
1975 if (wifi->p2p_find_timeout) {
1976 g_source_remove(wifi->p2p_find_timeout);
1977 wifi->p2p_find_timeout = 0;
1983 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1984 p2p_find_stop, device);
1985 if (!wifi->p2p_find_timeout)
1990 p2p_find_stop(device);
1993 static int p2p_find(struct connman_device *device)
1995 struct wifi_data *wifi;
2000 if (!p2p_technology)
2003 wifi = connman_device_get_data(device);
2005 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2008 reset_autoscan(device);
2009 connman_device_ref(device);
2011 ret = g_supplicant_interface_p2p_find(wifi->interface,
2012 p2p_find_callback, device);
2014 connman_device_unref(device);
2015 start_autoscan(device);
2017 connman_device_set_scanning(device,
2018 CONNMAN_SERVICE_TYPE_P2P, true);
2024 #if defined TIZEN_EXT
2025 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2028 struct connman_device *device = user_data;
2029 struct wifi_data *wifi = connman_device_get_data(device);
2032 DBG("result %d wifi %p", result, wifi);
2034 if (wifi && wifi->scan_params) {
2035 g_supplicant_free_scan_params(wifi->scan_params);
2036 wifi->scan_params = NULL;
2039 scanning = connman_device_get_scanning(device);
2041 connman_device_set_scanning(device,
2042 CONNMAN_SERVICE_TYPE_WIFI, false);
2043 connman_device_unref(device);
2047 static int wifi_specific_scan(enum connman_service_type type,
2048 struct connman_device *device, int scan_type,
2049 GSList *specific_scan_list, void *user_data)
2051 GSList *list = NULL;
2053 struct wifi_data *wifi = connman_device_get_data(device);
2054 GSupplicantScanParams *scan_params = NULL;
2055 struct scan_ssid *scan_ssid = NULL;
2064 if (wifi->p2p_device)
2067 if (type == CONNMAN_SERVICE_TYPE_P2P)
2068 return p2p_find(device);
2070 if (wifi->tethering)
2073 scanning = connman_device_get_scanning(device);
2077 DBG("scan_type: %d", scan_type);
2078 if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
2079 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2081 DBG("Failed to allocate memory.");
2085 for (list = specific_scan_list; list; list = list->next) {
2086 ssid = (char *)list->data;
2087 int ssid_len = strlen(ssid);
2089 scan_ssid = g_try_new0(struct scan_ssid, 1);
2091 DBG("Failed to allocate memory.");
2092 g_supplicant_free_scan_params(scan_params);
2096 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2097 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
2098 scan_ssid->ssid_len = ssid_len;
2099 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2102 scan_params->num_ssids = count;
2104 } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
2106 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2108 DBG("Failed to allocate memory.");
2112 guint num_freqs = g_slist_length(specific_scan_list);
2113 DBG("num_freqs: %d", num_freqs);
2115 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2116 if (!scan_params->freqs) {
2117 DBG("Failed to allocate memory.");
2118 g_free(scan_params);
2123 for (list = specific_scan_list; list; list = list->next) {
2124 freq = (int)list->data;
2126 scan_params->freqs[count] = freq;
2127 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2130 scan_params->num_freqs = count;
2132 } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
2133 int freq_count, ap_count;
2134 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2136 DBG("Failed to allocate memory.");
2140 guint size = g_slist_length(specific_scan_list);
2142 scan_params->freqs = g_try_new0(uint16_t, size/2);
2143 if (!scan_params->freqs) {
2144 DBG("Failed to allocate memory.");
2145 g_free(scan_params);
2149 ap_count = freq_count = 0;
2150 for (list = specific_scan_list; list; list = list->next) {
2151 if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
2152 ssid = ((connman_multi_scan_ap_s *)list->data)->str;
2153 int ssid_len = strlen(ssid);
2155 scan_ssid = g_try_new0(struct scan_ssid, 1);
2157 DBG("Failed to allocate memory.");
2158 g_supplicant_free_scan_params(scan_params);
2162 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2163 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
2164 scan_ssid->ssid_len = ssid_len;
2165 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2169 freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
2170 scan_params->freqs[freq_count] = freq;
2171 DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
2175 scan_params->num_ssids = ap_count;
2176 scan_params->num_freqs = freq_count;
2178 DBG("Invalid scan");
2182 reset_autoscan(device);
2183 connman_device_ref(device);
2185 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2186 specific_scan_callback, device);
2189 connman_device_set_scanning(device,
2190 CONNMAN_SERVICE_TYPE_WIFI, true);
2192 g_supplicant_free_scan_params(scan_params);
2193 connman_device_unref(device);
2201 * Note that the hidden scan is only used when connecting to this specific
2202 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2204 static int wifi_scan(enum connman_service_type type,
2205 struct connman_device *device,
2206 const char *ssid, unsigned int ssid_len,
2207 const char *identity, const char* passphrase,
2208 const char *security, void *user_data)
2210 struct wifi_data *wifi = connman_device_get_data(device);
2211 GSupplicantScanParams *scan_params = NULL;
2212 struct scan_ssid *scan_ssid;
2213 struct hidden_params *hidden;
2215 int driver_max_ssids = 0;
2222 if (wifi->p2p_device)
2225 if (wifi->tethering)
2228 if (type == CONNMAN_SERVICE_TYPE_P2P)
2229 return p2p_find(device);
2231 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2233 scanning = connman_device_get_scanning(device);
2235 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2239 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2241 DBG("max ssids %d", driver_max_ssids);
2242 if (driver_max_ssids == 0)
2243 return wifi_scan_simple(device);
2247 if (scanning && wifi->hidden && wifi->postpone_hidden)
2253 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2258 scan_ssid = g_try_new(struct scan_ssid, 1);
2260 g_free(scan_params);
2264 memcpy(scan_ssid->ssid, ssid, ssid_len);
2265 scan_ssid->ssid_len = ssid_len;
2266 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2268 scan_params->num_ssids = 1;
2270 hidden = g_try_new0(struct hidden_params, 1);
2272 g_supplicant_free_scan_params(scan_params);
2277 hidden_free(wifi->hidden);
2278 wifi->hidden = NULL;
2281 memcpy(hidden->ssid, ssid, ssid_len);
2282 hidden->ssid_len = ssid_len;
2283 hidden->identity = g_strdup(identity);
2284 hidden->passphrase = g_strdup(passphrase);
2285 hidden->security = g_strdup(security);
2286 hidden->user_data = user_data;
2287 wifi->hidden = hidden;
2290 /* Let's keep this active scan for later,
2291 * when current scan will be over. */
2292 wifi->postpone_hidden = TRUE;
2293 hidden->scan_params = scan_params;
2297 } else if (wifi->connected) {
2298 g_supplicant_free_scan_params(scan_params);
2299 return wifi_scan_simple(device);
2301 ret = get_latest_connections(driver_max_ssids, scan_params);
2303 g_supplicant_free_scan_params(scan_params);
2304 return wifi_scan_simple(device);
2308 connman_device_ref(device);
2310 reset_autoscan(device);
2312 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2313 scan_callback, device);
2316 connman_device_set_scanning(device,
2317 CONNMAN_SERVICE_TYPE_WIFI, true);
2318 #if defined TIZEN_EXT
2319 /*To allow the Full Scan after ssid based scan, set the flag here
2320 It is required because Tizen does not use the ConnMan specific
2321 backgroung Scan feature.Tizen has added the BG Scan feature in
2322 net-config. To sync with up ConnMan, we need to issue the Full Scan
2323 after SSID specific scan.*/
2324 wifi->allow_full_scan = TRUE;
2327 g_supplicant_free_scan_params(scan_params);
2328 connman_device_unref(device);
2331 hidden_free(wifi->hidden);
2332 wifi->hidden = NULL;
2339 static void wifi_regdom_callback(int result,
2343 struct connman_device *device = user_data;
2345 connman_device_regdom_notify(device, result, alpha2);
2347 connman_device_unref(device);
2350 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2352 struct wifi_data *wifi = connman_device_get_data(device);
2358 connman_device_ref(device);
2360 ret = g_supplicant_interface_set_country(wifi->interface,
2361 wifi_regdom_callback,
2364 connman_device_unref(device);
2369 static struct connman_device_driver wifi_ng_driver = {
2371 .type = CONNMAN_DEVICE_TYPE_WIFI,
2372 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2373 .probe = wifi_probe,
2374 .remove = wifi_remove,
2375 .enable = wifi_enable,
2376 .disable = wifi_disable,
2378 .set_regdom = wifi_set_regdom,
2379 #if defined TIZEN_EXT
2380 .specific_scan = wifi_specific_scan,
2384 static void system_ready(void)
2388 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2389 connman_error("Failed to register WiFi driver");
2392 static void system_killed(void)
2396 connman_device_driver_unregister(&wifi_ng_driver);
2399 static int network_probe(struct connman_network *network)
2401 DBG("network %p", network);
2406 static void network_remove(struct connman_network *network)
2408 struct connman_device *device = connman_network_get_device(network);
2409 struct wifi_data *wifi;
2411 DBG("network %p", network);
2413 wifi = connman_device_get_data(device);
2417 if (wifi->network != network)
2420 wifi->network = NULL;
2422 #if defined TIZEN_EXT
2423 wifi->disconnecting = false;
2425 if (wifi->pending_network == network)
2426 wifi->pending_network = NULL;
2428 if (wifi->scan_pending_network == network)
2429 wifi->scan_pending_network = NULL;
2433 static void connect_callback(int result, GSupplicantInterface *interface,
2436 #if defined TIZEN_EXT
2438 struct wifi_data *wifi;
2440 struct connman_network *network = user_data;
2442 DBG("network %p result %d", network, result);
2444 #if defined TIZEN_EXT
2445 set_connman_bssid(RESET_BSSID, NULL);
2447 for (list = iface_list; list; list = list->next) {
2450 if (wifi && wifi->network == network)
2454 /* wifi_data may be invalid because wifi is already disabled */
2459 if (result == -ENOKEY) {
2460 connman_network_set_error(network,
2461 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2462 } else if (result < 0) {
2463 connman_network_set_error(network,
2464 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2467 connman_network_unref(network);
2470 static GSupplicantSecurity network_security(const char *security)
2472 if (g_str_equal(security, "none"))
2473 return G_SUPPLICANT_SECURITY_NONE;
2474 else if (g_str_equal(security, "wep"))
2475 return G_SUPPLICANT_SECURITY_WEP;
2476 else if (g_str_equal(security, "psk"))
2477 return G_SUPPLICANT_SECURITY_PSK;
2478 else if (g_str_equal(security, "wpa"))
2479 return G_SUPPLICANT_SECURITY_PSK;
2480 else if (g_str_equal(security, "rsn"))
2481 return G_SUPPLICANT_SECURITY_PSK;
2482 else if (g_str_equal(security, "ieee8021x"))
2483 return G_SUPPLICANT_SECURITY_IEEE8021X;
2484 #if defined TIZEN_EXT
2485 else if (g_str_equal(security, "ft_psk") == TRUE)
2486 return G_SUPPLICANT_SECURITY_FT_PSK;
2487 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2488 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2491 return G_SUPPLICANT_SECURITY_UNKNOWN;
2494 #if defined TIZEN_EXT
2495 static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
2497 if (security == NULL)
2498 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
2500 if (g_str_equal(security, "FT") == TRUE)
2501 return G_SUPPLICANT_EAP_KEYMGMT_FT;
2502 else if (g_str_equal(security, "CCKM") == TRUE)
2503 return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
2505 return G_SUPPLICANT_EAP_KEYMGMT_NONE;
2509 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2511 const char *security;
2513 memset(ssid, 0, sizeof(*ssid));
2514 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2515 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2517 ssid->scan_ssid = 1;
2518 security = connman_network_get_string(network, "WiFi.Security");
2519 ssid->security = network_security(security);
2520 ssid->passphrase = connman_network_get_string(network,
2522 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2525 * If our private key password is unset,
2526 * we use the supplied passphrase. That is needed
2527 * for PEAP where 2 passphrases (identity and client
2528 * cert may have to be provided.
2530 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2531 connman_network_set_string(network,
2532 "WiFi.PrivateKeyPassphrase",
2534 /* We must have an identity for both PEAP and TLS */
2535 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2537 /* Use agent provided identity as a fallback */
2538 if (!ssid->identity || strlen(ssid->identity) == 0)
2539 ssid->identity = connman_network_get_string(network,
2540 "WiFi.AgentIdentity");
2542 ssid->anonymous_identity = connman_network_get_string(network,
2543 "WiFi.AnonymousIdentity");
2544 ssid->ca_cert_path = connman_network_get_string(network,
2546 ssid->subject_match = connman_network_get_string(network,
2547 "WiFi.SubjectMatch");
2548 ssid->altsubject_match = connman_network_get_string(network,
2549 "WiFi.AltSubjectMatch");
2550 ssid->domain_suffix_match = connman_network_get_string(network,
2551 "WiFi.DomainSuffixMatch");
2552 ssid->domain_match = connman_network_get_string(network,
2553 "WiFi.DomainMatch");
2554 ssid->client_cert_path = connman_network_get_string(network,
2555 "WiFi.ClientCertFile");
2556 ssid->private_key_path = connman_network_get_string(network,
2557 "WiFi.PrivateKeyFile");
2558 ssid->private_key_passphrase = connman_network_get_string(network,
2559 "WiFi.PrivateKeyPassphrase");
2560 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2562 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2563 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2565 #if defined TIZEN_EXT
2566 ssid->bssid = connman_network_get_bssid(network);
2568 ssid->eap_keymgmt = network_eap_keymgmt(
2569 connman_network_get_string(network, "WiFi.KeymgmtType"));
2570 ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
2572 if(g_strcmp0(ssid->eap, "fast") == 0)
2573 ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
2575 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
2576 ssid->bssid_for_connect_len = 6;
2577 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
2578 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
2579 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
2580 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
2581 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
2583 ssid->freq = connman_network_get_frequency(network);
2587 if (connman_setting_get_bool("BackgroundScanning"))
2588 ssid->bgscan = BGSCAN_DEFAULT;
2591 static int network_connect(struct connman_network *network)
2593 struct connman_device *device = connman_network_get_device(network);
2594 struct wifi_data *wifi;
2595 GSupplicantInterface *interface;
2596 GSupplicantSSID *ssid;
2598 DBG("network %p", network);
2603 wifi = connman_device_get_data(device);
2607 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2611 interface = wifi->interface;
2613 ssid_init(ssid, network);
2615 if (wifi->disconnecting) {
2616 wifi->pending_network = network;
2619 wifi->network = connman_network_ref(network);
2621 #if defined TIZEN_EXT
2622 wifi->scan_pending_network = NULL;
2625 return g_supplicant_interface_connect(interface, ssid,
2626 connect_callback, network);
2629 return -EINPROGRESS;
2632 static void disconnect_callback(int result, GSupplicantInterface *interface,
2635 #if defined TIZEN_EXT
2637 struct wifi_data *wifi;
2638 struct connman_network *network = user_data;
2640 DBG("network %p result %d", network, result);
2642 for (list = iface_list; list; list = list->next) {
2645 if (wifi->network == NULL && wifi->disconnecting == true)
2646 wifi->disconnecting = false;
2648 if (wifi->network == network)
2652 /* wifi_data may be invalid because wifi is already disabled */
2657 struct wifi_data *wifi = user_data;
2660 DBG("result %d supplicant interface %p wifi %p",
2661 result, interface, wifi);
2663 if (result == -ECONNABORTED) {
2664 DBG("wifi interface no longer available");
2668 if (wifi->network) {
2669 connman_network_set_connected(wifi->network, false);
2670 wifi->network = NULL;
2673 wifi->disconnecting = false;
2674 wifi->connected = false;
2676 if (wifi->pending_network) {
2677 network_connect(wifi->pending_network);
2678 wifi->pending_network = NULL;
2681 start_autoscan(wifi->device);
2684 static int network_disconnect(struct connman_network *network)
2686 struct connman_device *device = connman_network_get_device(network);
2687 struct wifi_data *wifi;
2689 #if defined TIZEN_EXT
2690 struct connman_service *service;
2693 DBG("network %p", network);
2695 wifi = connman_device_get_data(device);
2696 if (!wifi || !wifi->interface)
2699 #if defined TIZEN_EXT
2700 if (connman_network_get_associating(network) == true) {
2701 connman_network_clear_associating(network);
2702 connman_network_set_bool(network, "WiFi.UseWPS", false);
2704 service = connman_service_lookup_from_network(network);
2706 if (service != NULL &&
2707 (__connman_service_is_connected_state(service,
2708 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2709 __connman_service_is_connected_state(service,
2710 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2711 (connman_service_get_favorite(service) == false))
2712 __connman_service_set_passphrase(service, NULL);
2715 if (wifi->pending_network == network)
2716 wifi->pending_network = NULL;
2718 if (wifi->scan_pending_network == network)
2719 wifi->scan_pending_network = NULL;
2722 connman_network_set_associating(network, false);
2724 if (wifi->disconnecting)
2727 wifi->disconnecting = true;
2729 #if defined TIZEN_EXT
2730 err = g_supplicant_interface_disconnect(wifi->interface,
2731 disconnect_callback, network);
2733 err = g_supplicant_interface_disconnect(wifi->interface,
2734 disconnect_callback, wifi);
2738 wifi->disconnecting = false;
2743 static struct connman_network_driver network_driver = {
2745 .type = CONNMAN_NETWORK_TYPE_WIFI,
2746 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2747 .probe = network_probe,
2748 .remove = network_remove,
2749 .connect = network_connect,
2750 .disconnect = network_disconnect,
2753 static void interface_added(GSupplicantInterface *interface)
2755 const char *ifname = g_supplicant_interface_get_ifname(interface);
2756 const char *driver = g_supplicant_interface_get_driver(interface);
2757 struct wifi_data *wifi;
2759 wifi = g_supplicant_interface_get_data(interface);
2761 wifi = get_pending_wifi_data(ifname);
2765 wifi->interface = interface;
2766 g_supplicant_interface_set_data(interface, wifi);
2767 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2768 wifi->p2p_device = true;
2771 DBG("ifname %s driver %s wifi %p tethering %d",
2772 ifname, driver, wifi, wifi->tethering);
2774 if (!wifi->device) {
2775 connman_error("WiFi device not set");
2779 connman_device_set_powered(wifi->device, true);
2782 static bool is_idle(struct wifi_data *wifi)
2784 DBG("state %d", wifi->state);
2786 switch (wifi->state) {
2787 case G_SUPPLICANT_STATE_UNKNOWN:
2788 case G_SUPPLICANT_STATE_DISABLED:
2789 case G_SUPPLICANT_STATE_DISCONNECTED:
2790 case G_SUPPLICANT_STATE_INACTIVE:
2791 case G_SUPPLICANT_STATE_SCANNING:
2794 case G_SUPPLICANT_STATE_AUTHENTICATING:
2795 case G_SUPPLICANT_STATE_ASSOCIATING:
2796 case G_SUPPLICANT_STATE_ASSOCIATED:
2797 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2798 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2799 case G_SUPPLICANT_STATE_COMPLETED:
2806 static bool is_idle_wps(GSupplicantInterface *interface,
2807 struct wifi_data *wifi)
2809 /* First, let's check if WPS processing did not went wrong */
2810 if (g_supplicant_interface_get_wps_state(interface) ==
2811 G_SUPPLICANT_WPS_STATE_FAIL)
2814 /* Unlike normal connection, being associated while processing wps
2815 * actually means that we are idling. */
2816 switch (wifi->state) {
2817 case G_SUPPLICANT_STATE_UNKNOWN:
2818 case G_SUPPLICANT_STATE_DISABLED:
2819 case G_SUPPLICANT_STATE_DISCONNECTED:
2820 case G_SUPPLICANT_STATE_INACTIVE:
2821 case G_SUPPLICANT_STATE_SCANNING:
2822 case G_SUPPLICANT_STATE_ASSOCIATED:
2824 case G_SUPPLICANT_STATE_AUTHENTICATING:
2825 case G_SUPPLICANT_STATE_ASSOCIATING:
2826 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2827 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2828 case G_SUPPLICANT_STATE_COMPLETED:
2835 static bool handle_wps_completion(GSupplicantInterface *interface,
2836 struct connman_network *network,
2837 struct connman_device *device,
2838 struct wifi_data *wifi)
2842 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2844 const unsigned char *ssid, *wps_ssid;
2845 unsigned int ssid_len, wps_ssid_len;
2846 const char *wps_key;
2848 /* Checking if we got associated with requested
2850 ssid = connman_network_get_blob(network, "WiFi.SSID",
2853 wps_ssid = g_supplicant_interface_get_wps_ssid(
2854 interface, &wps_ssid_len);
2856 if (!wps_ssid || wps_ssid_len != ssid_len ||
2857 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2858 connman_network_set_associating(network, false);
2859 #if defined TIZEN_EXT
2860 g_supplicant_interface_disconnect(wifi->interface,
2861 disconnect_callback, wifi->network);
2863 connman_network_set_bool(network, "WiFi.UseWPS", false);
2864 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2866 g_supplicant_interface_disconnect(wifi->interface,
2867 disconnect_callback, wifi);
2872 wps_key = g_supplicant_interface_get_wps_key(interface);
2873 #if defined TIZEN_EXT
2874 /* Check the passphrase and encrypt it
2877 gchar *passphrase = g_strdup(wps_key);
2879 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2881 if (check_passphrase_ext(network, passphrase) < 0) {
2882 DBG("[WPS] Invalid passphrase");
2887 ret = send_encryption_request(passphrase, network);
2892 DBG("[WPS] Encryption request succeeded");
2894 DBG("[WPS] Encryption request failed %d", ret);
2897 connman_network_set_string(network, "WiFi.Passphrase",
2900 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2907 static bool handle_assoc_status_code(GSupplicantInterface *interface,
2908 struct wifi_data *wifi)
2910 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
2911 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
2912 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
2913 wifi->load_shaping_retries ++;
2916 wifi->load_shaping_retries = 0;
2920 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2921 struct connman_network *network,
2922 struct wifi_data *wifi)
2924 #if defined TIZEN_EXT
2925 const char *security;
2926 struct connman_service *service;
2928 if (wifi->connected)
2931 security = connman_network_get_string(network, "WiFi.Security");
2933 if (security && g_str_equal(security, "ieee8021x") == true &&
2934 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2936 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2941 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2944 struct connman_service *service;
2946 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2949 if (wifi->connected)
2953 service = connman_service_lookup_from_network(network);
2959 if (connman_service_get_favorite(service)) {
2960 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2965 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2970 #if defined TIZEN_EXT
2971 static bool handle_wifi_assoc_retry(struct connman_network *network,
2972 struct wifi_data *wifi)
2974 const char *security;
2976 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2977 connman_network_get_connecting(network) != true) {
2978 wifi->assoc_retry_count = 0;
2982 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2983 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2984 wifi->assoc_retry_count = 0;
2988 security = connman_network_get_string(network, "WiFi.Security");
2989 if (security && g_str_equal(security, "ieee8021x") == true &&
2990 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2991 wifi->assoc_retry_count = 0;
2995 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2996 wifi->assoc_retry_count = 0;
2998 /* Honestly it's not an invalid-key error,
2999 * however QA team recommends that the invalid-key error
3000 * might be better to display for user experience.
3002 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
3011 static void interface_state(GSupplicantInterface *interface)
3013 struct connman_network *network;
3014 struct connman_device *device;
3015 struct wifi_data *wifi;
3016 GSupplicantState state = g_supplicant_interface_get_state(interface);
3020 wifi = g_supplicant_interface_get_data(interface);
3022 DBG("wifi %p interface state %d", wifi, state);
3027 if (state == G_SUPPLICANT_STATE_COMPLETED) {
3028 if (wifi->tethering_param) {
3029 g_free(wifi->tethering_param->ssid);
3030 g_free(wifi->tethering_param);
3031 wifi->tethering_param = NULL;
3035 device = wifi->device;
3039 if (g_supplicant_interface_get_ready(interface) &&
3040 !wifi->interface_ready) {
3041 wifi->interface_ready = true;
3042 finalize_interface_creation(wifi);
3045 network = wifi->network;
3050 case G_SUPPLICANT_STATE_SCANNING:
3051 if (wifi->connected)
3052 connman_network_set_connected(network, false);
3056 case G_SUPPLICANT_STATE_AUTHENTICATING:
3057 case G_SUPPLICANT_STATE_ASSOCIATING:
3058 #if defined TIZEN_EXT
3059 reset_autoscan(device);
3061 stop_autoscan(device);
3064 if (!wifi->connected)
3065 connman_network_set_associating(network, true);
3069 case G_SUPPLICANT_STATE_COMPLETED:
3070 #if defined TIZEN_EXT
3071 /* though it should be already reset: */
3072 reset_autoscan(device);
3074 wifi->assoc_retry_count = 0;
3076 wifi->scan_pending_network = NULL;
3078 /* should be cleared scanning flag */
3079 bool scanning = connman_device_get_scanning(device);
3081 connman_device_set_scanning(device,
3082 CONNMAN_SERVICE_TYPE_WIFI, false);
3083 connman_device_unref(device);
3086 /* though it should be already stopped: */
3087 stop_autoscan(device);
3090 if (!handle_wps_completion(interface, network, device, wifi))
3093 connman_network_set_connected(network, true);
3095 wifi->disconnect_code = 0;
3096 wifi->assoc_code = 0;
3097 wifi->load_shaping_retries = 0;
3100 case G_SUPPLICANT_STATE_DISCONNECTED:
3102 * If we're in one of the idle modes, we have
3103 * not started association yet and thus setting
3104 * those ones to FALSE could cancel an association
3107 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3109 if (is_idle_wps(interface, wifi))
3115 if (handle_assoc_status_code(interface, wifi))
3118 /* If previous state was 4way-handshake, then
3119 * it's either: psk was incorrect and thus we retry
3120 * or if we reach the maximum retries we declare the
3122 if (handle_4way_handshake_failure(interface,
3126 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3127 switch (wifi->disconnect_code) {
3128 case 1: /* Unspecified reason */
3129 /* Let's assume it's because we got blocked */
3131 case 6: /* Class 2 frame received from nonauthenticated STA */
3132 connman_network_set_error(network,
3133 CONNMAN_NETWORK_ERROR_BLOCKED);
3140 #if defined TIZEN_EXT
3143 err = g_supplicant_interface_remove_network(wifi->interface);
3145 DBG("Failed to remove network(%d)", err);
3148 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3149 * Retry association until its retry count is expired */
3150 if (handle_wifi_assoc_retry(network, wifi) == true) {
3151 throw_wifi_scan(wifi->device, scan_callback);
3152 wifi->scan_pending_network = wifi->network;
3156 if(wifi->disconnect_code > 0){
3157 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3158 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3161 /* To avoid unnecessary repeated association in wpa_supplicant,
3162 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
3163 if (wps != true && wifi->network && wifi->disconnecting == false) {
3164 wifi->disconnecting = true;
3165 err = g_supplicant_interface_disconnect(wifi->interface,
3166 disconnect_callback, wifi->network);
3168 wifi->disconnecting = false;
3170 connman_network_set_connected(network, false);
3171 connman_network_set_associating(network, false);
3173 start_autoscan(device);
3179 connman_network_set_connected(network, false);
3180 connman_network_set_associating(network, false);
3181 wifi->disconnecting = false;
3183 start_autoscan(device);
3187 case G_SUPPLICANT_STATE_INACTIVE:
3188 #if defined TIZEN_EXT
3189 if (handle_wps_completion(interface, network, device, wifi) == false)
3192 connman_network_set_associating(network, false);
3193 start_autoscan(device);
3197 case G_SUPPLICANT_STATE_UNKNOWN:
3198 case G_SUPPLICANT_STATE_DISABLED:
3199 case G_SUPPLICANT_STATE_ASSOCIATED:
3200 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3201 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3205 old_connected = wifi->connected;
3206 wifi->state = state;
3208 /* Saving wpa_s state policy:
3209 * If connected and if the state changes are roaming related:
3210 * --> We stay connected
3212 * --> We are connected
3214 * --> We are not connected
3217 case G_SUPPLICANT_STATE_AUTHENTICATING:
3218 case G_SUPPLICANT_STATE_ASSOCIATING:
3219 case G_SUPPLICANT_STATE_ASSOCIATED:
3220 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3221 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3222 if (wifi->connected)
3223 connman_warn("Probably roaming right now!"
3224 " Staying connected...");
3226 case G_SUPPLICANT_STATE_SCANNING:
3227 wifi->connected = false;
3230 start_autoscan(device);
3232 case G_SUPPLICANT_STATE_COMPLETED:
3233 wifi->connected = true;
3236 wifi->connected = false;
3243 static void interface_removed(GSupplicantInterface *interface)
3245 const char *ifname = g_supplicant_interface_get_ifname(interface);
3246 struct wifi_data *wifi;
3248 DBG("ifname %s", ifname);
3250 wifi = g_supplicant_interface_get_data(interface);
3253 wifi->interface = NULL;
3255 if (wifi && wifi->tethering)
3258 if (!wifi || !wifi->device) {
3259 DBG("wifi interface already removed");
3263 connman_device_set_powered(wifi->device, false);
3265 check_p2p_technology();
3268 static void set_device_type(const char *type, char dev_type[17])
3270 const char *oui = "0050F204";
3271 const char *category = "0001";
3272 const char *sub_category = "0000";
3274 if (!g_strcmp0(type, "handset")) {
3276 sub_category = "0005";
3277 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
3278 sub_category = "0001";
3279 else if (!g_strcmp0(type, "server"))
3280 sub_category = "0002";
3281 else if (!g_strcmp0(type, "laptop"))
3282 sub_category = "0005";
3283 else if (!g_strcmp0(type, "desktop"))
3284 sub_category = "0006";
3285 else if (!g_strcmp0(type, "tablet"))
3286 sub_category = "0009";
3287 else if (!g_strcmp0(type, "watch"))
3290 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
3293 static void p2p_support(GSupplicantInterface *interface)
3295 char dev_type[17] = {};
3296 const char *hostname;
3303 if (!g_supplicant_interface_has_p2p(interface))
3306 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3307 DBG("Could not register P2P technology driver");
3311 hostname = connman_utsname_get_hostname();
3313 hostname = "ConnMan";
3315 set_device_type(connman_machine_get_type(), dev_type);
3316 g_supplicant_interface_set_p2p_device_config(interface,
3317 hostname, dev_type);
3318 connman_peer_driver_register(&peer_driver);
3321 static void scan_started(GSupplicantInterface *interface)
3326 static void scan_finished(GSupplicantInterface *interface)
3328 #if defined TIZEN_EXT
3329 struct wifi_data *wifi;
3330 bool is_associating = false;
3331 static bool is_scanning = true;
3336 #if defined TIZEN_EXT
3337 wifi = g_supplicant_interface_get_data(interface);
3338 if (wifi && wifi->scan_pending_network) {
3339 network_connect(wifi->scan_pending_network);
3340 wifi->scan_pending_network = NULL;
3343 //service state - associating
3344 if(!wifi || !wifi->network)
3347 is_associating = connman_network_get_associating(wifi->network);
3348 if(is_associating && is_scanning){
3349 is_scanning = false;
3350 DBG("send scan for connecting");
3351 throw_wifi_scan(wifi->device, scan_callback);
3362 static void ap_create_fail(GSupplicantInterface *interface)
3364 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3367 if ((wifi->tethering) && (wifi->tethering_param)) {
3368 DBG("%s create AP fail \n",
3369 g_supplicant_interface_get_ifname(wifi->interface));
3371 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
3372 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
3373 wifi->tethering = false;
3375 ret = tech_set_tethering(wifi->tethering_param->technology,
3376 wifi->tethering_param->ssid->ssid,
3377 wifi->tethering_param->ssid->passphrase,
3378 wifi->bridge, true);
3380 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
3381 connman_technology_tethering_notify(wifi_technology,false);
3384 g_free(wifi->tethering_param->ssid);
3385 g_free(wifi->tethering_param);
3386 wifi->tethering_param = NULL;
3392 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3394 unsigned char strength;
3396 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3398 #if !defined TIZEN_EXT
3405 static void network_added(GSupplicantNetwork *supplicant_network)
3407 struct connman_network *network;
3408 GSupplicantInterface *interface;
3409 struct wifi_data *wifi;
3410 const char *name, *identifier, *security, *group, *mode;
3411 const unsigned char *ssid;
3412 unsigned int ssid_len;
3416 bool wps_advertizing;
3418 #if defined TIZEN_EXT
3419 GSList *vsie_list = NULL;
3420 const unsigned char *country_code;
3423 mode = g_supplicant_network_get_mode(supplicant_network);
3424 identifier = g_supplicant_network_get_identifier(supplicant_network);
3426 DBG("%s", identifier);
3428 if (!g_strcmp0(mode, "adhoc"))
3431 interface = g_supplicant_network_get_interface(supplicant_network);
3432 wifi = g_supplicant_interface_get_data(interface);
3433 name = g_supplicant_network_get_name(supplicant_network);
3434 security = g_supplicant_network_get_security(supplicant_network);
3435 group = g_supplicant_network_get_identifier(supplicant_network);
3436 wps = g_supplicant_network_get_wps(supplicant_network);
3437 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3438 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3439 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3440 supplicant_network);
3445 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3447 network = connman_device_get_network(wifi->device, identifier);
3450 network = connman_network_create(identifier,
3451 CONNMAN_NETWORK_TYPE_WIFI);
3455 connman_network_set_index(network, wifi->index);
3457 if (connman_device_add_network(wifi->device, network) < 0) {
3458 connman_network_unref(network);
3462 wifi->networks = g_slist_prepend(wifi->networks, network);
3465 if (name && name[0] != '\0')
3466 connman_network_set_name(network, name);
3468 connman_network_set_blob(network, "WiFi.SSID",
3470 #if defined TIZEN_EXT
3471 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
3473 connman_network_set_vsie_list(network, vsie_list);
3475 DBG("vsie_list is NULL");
3476 country_code = g_supplicant_network_get_countrycode(supplicant_network);
3477 connman_network_set_countrycode(network, country_code);
3479 connman_network_set_string(network, "WiFi.Security", security);
3480 connman_network_set_strength(network,
3481 calculate_strength(supplicant_network));
3482 connman_network_set_bool(network, "WiFi.WPS", wps);
3485 /* Is AP advertizing for WPS association?
3486 * If so, we decide to use WPS by default */
3487 if (wps_ready && wps_pbc &&
3489 #if !defined TIZEN_EXT
3490 connman_network_set_bool(network, "WiFi.UseWPS", true);
3492 DBG("wps is activating by ap but ignore it.");
3497 connman_network_set_frequency(network,
3498 g_supplicant_network_get_frequency(supplicant_network));
3499 #if defined TIZEN_EXT
3500 connman_network_set_bssid(network,
3501 g_supplicant_network_get_bssid(supplicant_network));
3502 connman_network_set_maxrate(network,
3503 g_supplicant_network_get_maxrate(supplicant_network));
3504 connman_network_set_enc_mode(network,
3505 g_supplicant_network_get_enc_mode(supplicant_network));
3506 connman_network_set_rsn_mode(network,
3507 g_supplicant_network_get_rsn_mode(supplicant_network));
3508 connman_network_set_keymgmt(network,
3509 g_supplicant_network_get_keymgmt(supplicant_network));
3510 connman_network_set_bool(network, "WiFi.HS20AP",
3511 g_supplicant_network_is_hs20AP(supplicant_network));
3512 connman_network_set_bssid_list(network,
3513 (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
3515 connman_network_set_available(network, true);
3516 connman_network_set_string(network, "WiFi.Mode", mode);
3518 #if defined TIZEN_EXT
3523 connman_network_set_group(network, group);
3525 #if defined TIZEN_EXT
3526 if (wifi_first_scan == true)
3527 found_with_first_scan = true;
3530 if (wifi->hidden && ssid) {
3531 #if defined TIZEN_EXT
3532 if (network_security(wifi->hidden->security) ==
3533 network_security(security) &&
3535 if (!g_strcmp0(wifi->hidden->security, security) &&
3537 wifi->hidden->ssid_len == ssid_len &&
3538 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3539 connman_network_connect_hidden(network,
3540 wifi->hidden->identity,
3541 wifi->hidden->passphrase,
3542 wifi->hidden->user_data);
3543 wifi->hidden->user_data = NULL;
3544 hidden_free(wifi->hidden);
3545 wifi->hidden = NULL;
3550 static void network_removed(GSupplicantNetwork *network)
3552 GSupplicantInterface *interface;
3553 struct wifi_data *wifi;
3554 const char *name, *identifier;
3555 struct connman_network *connman_network;
3557 interface = g_supplicant_network_get_interface(network);
3558 wifi = g_supplicant_interface_get_data(interface);
3559 identifier = g_supplicant_network_get_identifier(network);
3560 name = g_supplicant_network_get_name(network);
3562 DBG("name %s", name);
3567 connman_network = connman_device_get_network(wifi->device, identifier);
3568 if (!connman_network)
3571 #if defined TIZEN_EXT
3572 if (connman_network == wifi->scan_pending_network)
3573 wifi->scan_pending_network = NULL;
3575 if (connman_network == wifi->pending_network)
3576 wifi->pending_network = NULL;
3578 if(connman_network_get_connecting(connman_network) == true){
3579 connman_network_set_connected(connman_network, false);
3583 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3585 connman_device_remove_network(wifi->device, connman_network);
3586 connman_network_unref(connman_network);
3589 static void network_changed(GSupplicantNetwork *network, const char *property)
3591 GSupplicantInterface *interface;
3592 struct wifi_data *wifi;
3593 const char *name, *identifier;
3594 struct connman_network *connman_network;
3596 #if defined TIZEN_EXT
3597 const unsigned char *bssid;
3598 unsigned int maxrate;
3601 const unsigned char *country_code;
3605 interface = g_supplicant_network_get_interface(network);
3606 wifi = g_supplicant_interface_get_data(interface);
3607 identifier = g_supplicant_network_get_identifier(network);
3608 name = g_supplicant_network_get_name(network);
3610 DBG("name %s", name);
3615 connman_network = connman_device_get_network(wifi->device, identifier);
3616 if (!connman_network)
3619 if (g_str_equal(property, "Signal")) {
3620 connman_network_set_strength(connman_network,
3621 calculate_strength(network));
3622 connman_network_update(connman_network);
3625 #if defined TIZEN_EXT
3626 bssid = g_supplicant_network_get_bssid(network);
3627 maxrate = g_supplicant_network_get_maxrate(network);
3628 frequency = g_supplicant_network_get_frequency(network);
3629 wps = g_supplicant_network_get_wps(network);
3631 connman_network_set_bssid(connman_network, bssid);
3632 connman_network_set_maxrate(connman_network, maxrate);
3633 connman_network_set_frequency(connman_network, frequency);
3634 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3635 country_code = g_supplicant_network_get_countrycode(network);
3636 connman_network_set_countrycode(connman_network, country_code);
3637 bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
3638 connman_network_set_bssid_list(connman_network, bssid_list);
3642 static void network_associated(GSupplicantNetwork *network)
3644 GSupplicantInterface *interface;
3645 struct wifi_data *wifi;
3646 struct connman_network *connman_network;
3647 const char *identifier;
3651 interface = g_supplicant_network_get_interface(network);
3655 wifi = g_supplicant_interface_get_data(interface);
3659 identifier = g_supplicant_network_get_identifier(network);
3661 connman_network = connman_device_get_network(wifi->device, identifier);
3662 if (!connman_network)
3665 if (wifi->network) {
3666 if (wifi->network == connman_network)
3670 * This should never happen, we got associated with
3671 * a network different than the one we were expecting.
3673 DBG("Associated to %p while expecting %p",
3674 connman_network, wifi->network);
3676 connman_network_set_associating(wifi->network, false);
3679 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
3681 wifi->network = connman_network_ref(connman_network);
3685 * Interface state changes callback (interface_state) is always
3686 * called before network_associated callback thus we need to call
3687 * interface_state again in order to process the new state now that
3688 * we have the network properly set.
3690 interface_state(interface);
3693 static void apply_peer_services(GSupplicantPeer *peer,
3694 struct connman_peer *connman_peer)
3696 const unsigned char *data;
3701 connman_peer_reset_services(connman_peer);
3703 data = g_supplicant_peer_get_widi_ies(peer, &length);
3705 connman_peer_add_service(connman_peer,
3706 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3710 static void add_station(const char *mac)
3712 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3716 static void remove_station(const char *mac)
3718 connman_technology_tethering_remove_station(mac);
3721 static void peer_found(GSupplicantPeer *peer)
3723 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3724 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3725 struct connman_peer *connman_peer;
3726 const char *identifier, *name;
3728 #if defined TIZEN_EXT
3732 identifier = g_supplicant_peer_get_identifier(peer);
3733 name = g_supplicant_peer_get_name(peer);
3735 DBG("ident: %s", identifier);
3737 connman_peer = connman_peer_get(wifi->device, identifier);
3741 connman_peer = connman_peer_create(identifier);
3742 connman_peer_set_name(connman_peer, name);
3743 connman_peer_set_device(connman_peer, wifi->device);
3744 apply_peer_services(peer, connman_peer);
3746 ret = connman_peer_register(connman_peer);
3747 if (ret < 0 && ret != -EALREADY)
3748 connman_peer_unref(connman_peer);
3750 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
3753 static void peer_lost(GSupplicantPeer *peer)
3755 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3756 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3757 struct connman_peer *connman_peer;
3758 const char *identifier;
3763 identifier = g_supplicant_peer_get_identifier(peer);
3765 DBG("ident: %s", identifier);
3767 connman_peer = connman_peer_get(wifi->device, identifier);
3769 if (wifi->p2p_connecting &&
3770 wifi->pending_peer == connman_peer) {
3771 peer_connect_timeout(wifi);
3773 connman_peer_unregister(connman_peer);
3774 connman_peer_unref(connman_peer);
3777 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
3780 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3782 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3783 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3784 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3785 struct connman_peer *connman_peer;
3786 const char *identifier;
3788 identifier = g_supplicant_peer_get_identifier(peer);
3790 DBG("ident: %s", identifier);
3795 connman_peer = connman_peer_get(wifi->device, identifier);
3800 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3801 apply_peer_services(peer, connman_peer);
3802 connman_peer_services_changed(connman_peer);
3804 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3805 if (!g_supplicant_peer_is_in_a_group(peer))
3806 p_state = CONNMAN_PEER_STATE_IDLE;
3808 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3810 case G_SUPPLICANT_PEER_GROUP_STARTED:
3812 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3813 p_state = CONNMAN_PEER_STATE_IDLE;
3815 case G_SUPPLICANT_PEER_GROUP_JOINED:
3816 connman_peer_set_iface_address(connman_peer,
3817 g_supplicant_peer_get_iface_address(peer));
3819 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3820 p_state = CONNMAN_PEER_STATE_IDLE;
3822 case G_SUPPLICANT_PEER_GROUP_FAILED:
3823 if (g_supplicant_peer_has_requested_connection(peer))
3824 p_state = CONNMAN_PEER_STATE_IDLE;
3826 p_state = CONNMAN_PEER_STATE_FAILURE;
3830 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3831 p_state == CONNMAN_PEER_STATE_FAILURE) {
3832 if (wifi->p2p_connecting
3833 && connman_peer == wifi->pending_peer)
3834 peer_cancel_timeout(wifi);
3836 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3839 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3842 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3843 GSupplicantInterface *g_iface;
3844 struct wifi_data *g_wifi;
3846 g_iface = g_supplicant_peer_get_group_interface(peer);
3850 g_wifi = g_supplicant_interface_get_data(g_iface);
3854 connman_peer_set_as_master(connman_peer,
3855 !g_supplicant_peer_is_client(peer));
3856 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3859 * If wpa_supplicant didn't create a dedicated p2p-group
3860 * interface then mark this interface as p2p_device to avoid
3861 * scan and auto-scan are launched on it while P2P is connected.
3863 if (!g_list_find(p2p_iface_list, g_wifi))
3864 wifi->p2p_device = true;
3867 connman_peer_set_state(connman_peer, p_state);
3870 static void peer_request(GSupplicantPeer *peer)
3872 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3873 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3874 struct connman_peer *connman_peer;
3875 const char *identifier;
3877 #if defined TIZEN_EXT
3882 identifier = g_supplicant_peer_get_identifier(peer);
3884 DBG("ident: %s", identifier);
3886 connman_peer = connman_peer_get(wifi->device, identifier);
3890 connman_peer_request_connection(connman_peer);
3893 #if defined TIZEN_EXT
3894 static void system_power_off(void)
3897 struct wifi_data *wifi;
3898 struct connman_service *service;
3899 struct connman_ipconfig *ipconfig_ipv4;
3901 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3902 for (list = iface_list; list; list = list->next) {
3905 if (wifi->network != NULL) {
3906 service = connman_service_lookup_from_network(wifi->network);
3907 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3908 __connman_dhcp_stop(ipconfig_ipv4);
3914 static void network_merged(GSupplicantNetwork *network)
3916 GSupplicantInterface *interface;
3917 GSupplicantState state;
3918 struct wifi_data *wifi;
3919 const char *identifier;
3920 struct connman_network *connman_network;
3924 interface = g_supplicant_network_get_interface(network);
3928 state = g_supplicant_interface_get_state(interface);
3929 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3932 wifi = g_supplicant_interface_get_data(interface);
3936 identifier = g_supplicant_network_get_identifier(network);
3938 connman_network = connman_device_get_network(wifi->device, identifier);
3939 if (!connman_network)
3942 DBG("merged identifier %s", identifier);
3944 if (wifi->connected == FALSE) {
3946 case G_SUPPLICANT_STATE_AUTHENTICATING:
3947 case G_SUPPLICANT_STATE_ASSOCIATING:
3948 case G_SUPPLICANT_STATE_ASSOCIATED:
3949 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3950 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3951 connman_network_set_associating(connman_network, TRUE);
3953 case G_SUPPLICANT_STATE_COMPLETED:
3954 connman_network_set_connected(connman_network, TRUE);
3957 DBG("Not handled the state : %d", state);
3962 ishs20AP = g_supplicant_network_is_hs20AP(network);
3965 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3966 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3967 connman_network_set_string(connman_network, "WiFi.EAP",
3969 connman_network_set_string(connman_network, "WiFi.Identity",
3970 g_supplicant_network_get_identity(network));
3971 connman_network_set_string(connman_network, "WiFi.Phase2",
3972 g_supplicant_network_get_phase2(network));
3977 wifi->network = connman_network;
3980 static void assoc_failed(void *user_data)
3982 struct connman_network *network = user_data;
3983 connman_network_set_associating(network, false);
3987 static void debug(const char *str)
3989 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3990 connman_debug("%s", str);
3993 static void disconnect_reasoncode(GSupplicantInterface *interface,
3996 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3999 wifi->disconnect_code = reasoncode;
4003 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
4005 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
4008 wifi->assoc_code = status_code;
4012 static const GSupplicantCallbacks callbacks = {
4013 .system_ready = system_ready,
4014 .system_killed = system_killed,
4015 .interface_added = interface_added,
4016 .interface_state = interface_state,
4017 .interface_removed = interface_removed,
4018 .p2p_support = p2p_support,
4019 .scan_started = scan_started,
4020 .scan_finished = scan_finished,
4021 .ap_create_fail = ap_create_fail,
4022 .network_added = network_added,
4023 .network_removed = network_removed,
4024 .network_changed = network_changed,
4025 .network_associated = network_associated,
4026 .add_station = add_station,
4027 .remove_station = remove_station,
4028 .peer_found = peer_found,
4029 .peer_lost = peer_lost,
4030 .peer_changed = peer_changed,
4031 .peer_request = peer_request,
4032 #if defined TIZEN_EXT
4033 .system_power_off = system_power_off,
4034 .network_merged = network_merged,
4035 .assoc_failed = assoc_failed,
4038 .disconnect_reasoncode = disconnect_reasoncode,
4039 .assoc_status_code = assoc_status_code,
4043 static int tech_probe(struct connman_technology *technology)
4045 wifi_technology = technology;
4050 static void tech_remove(struct connman_technology *technology)
4052 wifi_technology = NULL;
4055 static GSupplicantSSID *ssid_ap_init(const char *ssid,
4056 const char *passphrase)
4058 GSupplicantSSID *ap;
4060 ap = g_try_malloc0(sizeof(GSupplicantSSID));
4064 ap->mode = G_SUPPLICANT_MODE_MASTER;
4066 ap->ssid_len = strlen(ssid);
4070 if (!passphrase || strlen(passphrase) == 0) {
4071 ap->security = G_SUPPLICANT_SECURITY_NONE;
4072 ap->passphrase = NULL;
4074 ap->security = G_SUPPLICANT_SECURITY_PSK;
4075 ap->protocol = G_SUPPLICANT_PROTO_RSN;
4076 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
4077 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
4078 ap->passphrase = passphrase;
4084 static void ap_start_callback(int result, GSupplicantInterface *interface,
4087 struct wifi_tethering_info *info = user_data;
4089 DBG("result %d index %d bridge %s",
4090 result, info->wifi->index, info->wifi->bridge);
4092 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4093 connman_inet_remove_from_bridge(info->wifi->index,
4094 info->wifi->bridge);
4096 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4097 connman_technology_tethering_notify(info->technology, false);
4098 g_free(info->wifi->tethering_param->ssid);
4099 g_free(info->wifi->tethering_param);
4100 info->wifi->tethering_param = NULL;
4104 g_free(info->ifname);
4108 static void ap_create_callback(int result,
4109 GSupplicantInterface *interface,
4112 struct wifi_tethering_info *info = user_data;
4114 DBG("result %d ifname %s", result,
4115 g_supplicant_interface_get_ifname(interface));
4117 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4118 connman_inet_remove_from_bridge(info->wifi->index,
4119 info->wifi->bridge);
4121 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4122 connman_technology_tethering_notify(info->technology, false);
4123 g_free(info->wifi->tethering_param->ssid);
4124 g_free(info->wifi->tethering_param);
4125 info->wifi->tethering_param = NULL;
4129 g_free(info->ifname);
4135 info->wifi->interface = interface;
4136 g_supplicant_interface_set_data(interface, info->wifi);
4138 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
4139 connman_error("Failed to set interface ap_scan property");
4141 g_supplicant_interface_connect(interface, info->ssid,
4142 ap_start_callback, info);
4145 static void sta_remove_callback(int result,
4146 GSupplicantInterface *interface,
4149 struct wifi_tethering_info *info = user_data;
4150 const char *driver = connman_option_get_string("wifi");
4152 DBG("ifname %s result %d ", info->ifname, result);
4154 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4155 info->wifi->tethering = false;
4156 connman_technology_tethering_notify(info->technology, false);
4158 g_free(info->ifname);
4162 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4163 g_free(info->wifi->tethering_param->ssid);
4164 g_free(info->wifi->tethering_param);
4165 info->wifi->tethering_param = NULL;
4170 info->wifi->interface = NULL;
4172 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
4177 static int enable_wifi_tethering(struct connman_technology *technology,
4178 const char *bridge, const char *identifier,
4179 const char *passphrase, bool available)
4182 GSupplicantInterface *interface;
4183 struct wifi_data *wifi;
4184 struct wifi_tethering_info *info;
4189 for (list = iface_list; list; list = list->next) {
4192 DBG("wifi %p network %p pending_network %p", wifi,
4193 wifi->network, wifi->pending_network);
4195 interface = wifi->interface;
4200 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
4203 ifname = g_supplicant_interface_get_ifname(wifi->interface);
4205 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
4206 DBG("%s does not support AP mode (detected)", ifname);
4210 mode = g_supplicant_interface_get_mode(interface);
4211 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
4212 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4213 DBG("%s does not support AP mode (capability)", ifname);
4217 if (wifi->network && available)
4220 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
4224 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
4225 if (!wifi->tethering_param) {
4231 info->technology = technology;
4232 info->wifi->bridge = bridge;
4233 info->ssid = ssid_ap_init(identifier, passphrase);
4237 info->ifname = g_strdup(ifname);
4241 wifi->tethering_param->technology = technology;
4242 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
4243 if (!wifi->tethering_param->ssid)
4246 info->wifi->tethering = true;
4247 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
4249 berr = connman_technology_tethering_notify(technology, true);
4253 err = g_supplicant_interface_remove(interface,
4254 sta_remove_callback,
4257 DBG("tethering wifi %p ifname %s", wifi, ifname);
4262 g_free(info->ifname);
4265 g_free(wifi->tethering_param);
4266 wifi->tethering_param = NULL;
4269 * Remove bridge if it was correctly created but remove
4270 * operation failed. Instead, if bridge creation failed then
4271 * break out and do not try again on another interface,
4272 * bridge set-up does not depend on it.
4275 connman_technology_tethering_notify(technology, false);
4283 static int tech_set_tethering(struct connman_technology *technology,
4284 const char *identifier, const char *passphrase,
4285 const char *bridge, bool enabled)
4288 struct wifi_data *wifi;
4294 for (list = iface_list; list; list = list->next) {
4297 if (wifi->tethering) {
4298 wifi->tethering = false;
4300 connman_inet_remove_from_bridge(wifi->index,
4302 wifi->bridged = false;
4306 connman_technology_tethering_notify(technology, false);
4311 DBG("trying tethering for available devices");
4312 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
4316 DBG("trying tethering for any device");
4317 err = enable_wifi_tethering(technology, bridge, identifier,
4324 static void regdom_callback(int result, const char *alpha2, void *user_data)
4328 if (!wifi_technology)
4334 connman_technology_regdom_notify(wifi_technology, alpha2);
4337 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
4339 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
4342 static struct connman_technology_driver tech_driver = {
4344 .type = CONNMAN_SERVICE_TYPE_WIFI,
4345 .probe = tech_probe,
4346 .remove = tech_remove,
4347 .set_tethering = tech_set_tethering,
4348 .set_regdom = tech_set_regdom,
4351 static int wifi_init(void)
4355 err = connman_network_driver_register(&network_driver);
4359 err = g_supplicant_register(&callbacks);
4361 connman_network_driver_unregister(&network_driver);
4365 err = connman_technology_driver_register(&tech_driver);
4367 g_supplicant_unregister(&callbacks);
4368 connman_network_driver_unregister(&network_driver);
4375 static void wifi_exit(void)
4379 connman_technology_driver_unregister(&tech_driver);
4381 g_supplicant_unregister(&callbacks);
4383 connman_network_driver_unregister(&network_driver);
4386 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
4387 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)