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 static struct connman_technology *wifi_technology = NULL;
75 static struct connman_technology *p2p_technology = NULL;
77 struct hidden_params {
79 unsigned int ssid_len;
83 GSupplicantScanParams *scan_params;
88 * Used for autoscan "emulation".
89 * Should be removed when wpa_s autoscan support will be by default.
91 struct autoscan_params {
100 struct connman_device *device;
101 struct connman_network *network;
102 struct connman_network *pending_network;
104 GSupplicantInterface *interface;
105 GSupplicantState state;
110 bool interface_ready;
116 struct hidden_params *hidden;
117 bool postpone_hidden;
119 * autoscan "emulation".
121 struct autoscan_params *autoscan;
123 GSupplicantScanParams *scan_params;
124 unsigned int p2p_find_timeout;
125 unsigned int p2p_connection_timeout;
126 struct connman_peer *pending_peer;
127 GSupplicantPeer *peer;
131 #if defined TIZEN_EXT
132 int assoc_retry_count;
133 struct connman_network *scan_pending_network;
134 bool allow_full_scan;
139 #if defined TIZEN_EXT
142 #define TIZEN_ASSOC_RETRY_COUNT 4
144 static gboolean wifi_first_scan = false;
145 static gboolean found_with_first_scan = false;
146 static gboolean is_wifi_notifier_registered = false;
150 static GList *iface_list = NULL;
152 static GList *pending_wifi_device = NULL;
153 static GList *p2p_iface_list = NULL;
154 bool wfd_service_registered = false;
156 static void start_autoscan(struct connman_device *device);
158 static int p2p_tech_probe(struct connman_technology *technology)
160 p2p_technology = technology;
165 static void p2p_tech_remove(struct connman_technology *technology)
167 p2p_technology = NULL;
170 static struct connman_technology_driver p2p_tech_driver = {
172 .type = CONNMAN_SERVICE_TYPE_P2P,
173 .probe = p2p_tech_probe,
174 .remove = p2p_tech_remove,
177 static bool is_p2p_connecting(void)
181 for (list = iface_list; list; list = list->next) {
182 struct wifi_data *wifi = list->data;
184 if (wifi->p2p_connecting)
191 static void add_pending_wifi_device(struct wifi_data *wifi)
193 if (g_list_find(pending_wifi_device, wifi))
196 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
199 static struct wifi_data *get_pending_wifi_data(const char *ifname)
203 for (list = pending_wifi_device; list; list = list->next) {
204 struct wifi_data *wifi;
205 const char *dev_name;
208 if (!wifi || !wifi->device)
211 dev_name = connman_device_get_string(wifi->device, "Interface");
212 if (!g_strcmp0(ifname, dev_name)) {
213 pending_wifi_device = g_list_delete_link(
214 pending_wifi_device, list);
222 static void remove_pending_wifi_device(struct wifi_data *wifi)
226 link = g_list_find(pending_wifi_device, wifi);
231 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
234 static void peer_cancel_timeout(struct wifi_data *wifi)
236 if (wifi->p2p_connection_timeout > 0)
237 g_source_remove(wifi->p2p_connection_timeout);
239 wifi->p2p_connection_timeout = 0;
240 wifi->p2p_connecting = false;
242 if (wifi->pending_peer) {
243 connman_peer_unref(wifi->pending_peer);
244 wifi->pending_peer = NULL;
250 static gboolean peer_connect_timeout(gpointer data)
252 struct wifi_data *wifi = data;
256 if (wifi->p2p_connecting) {
257 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
259 if (g_supplicant_peer_has_requested_connection(wifi->peer))
260 state = CONNMAN_PEER_STATE_IDLE;
262 connman_peer_set_state(wifi->pending_peer, state);
265 peer_cancel_timeout(wifi);
270 static void peer_connect_callback(int result, GSupplicantInterface *interface,
273 struct wifi_data *wifi = user_data;
274 struct connman_peer *peer = wifi->pending_peer;
276 DBG("peer %p - %d", peer, result);
282 peer_connect_timeout(wifi);
286 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
288 wifi->p2p_connection_timeout = g_timeout_add_seconds(
289 P2P_CONNECTION_TIMEOUT,
290 peer_connect_timeout, wifi);
293 static int peer_connect(struct connman_peer *peer,
294 enum connman_peer_wps_method wps_method,
297 struct connman_device *device = connman_peer_get_device(peer);
298 GSupplicantPeerParams *peer_params;
299 GSupplicantPeer *gs_peer;
300 struct wifi_data *wifi;
304 DBG("peer %p", peer);
309 wifi = connman_device_get_data(device);
313 if (wifi->p2p_connecting)
318 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
319 connman_peer_get_identifier(peer));
323 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
324 pin = g_supplicant_peer_is_wps_pin(gs_peer);
326 switch (wps_method) {
327 case CONNMAN_PEER_WPS_UNKNOWN:
328 if ((pbc && pin) || pin)
331 case CONNMAN_PEER_WPS_PBC:
336 case CONNMAN_PEER_WPS_PIN:
337 if (!pin || !wps_pin)
342 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
346 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
348 peer_params->wps_pin = g_strdup(wps_pin);
350 peer_params->master = connman_peer_service_is_master();
352 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
353 peer_connect_callback, wifi);
354 if (ret == -EINPROGRESS) {
355 wifi->pending_peer = connman_peer_ref(peer);
356 wifi->peer = gs_peer;
357 wifi->p2p_connecting = true;
364 static int peer_disconnect(struct connman_peer *peer)
366 struct connman_device *device = connman_peer_get_device(peer);
367 GSupplicantPeerParams peer_params = {};
368 GSupplicantPeer *gs_peer;
369 struct wifi_data *wifi;
372 DBG("peer %p", peer);
377 wifi = connman_device_get_data(device);
381 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
382 connman_peer_get_identifier(peer));
386 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
388 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
390 g_free(peer_params.path);
392 if (ret == -EINPROGRESS)
393 peer_cancel_timeout(wifi);
398 struct peer_service_registration {
399 peer_service_registration_cb_t callback;
403 static bool is_service_wfd(const unsigned char *specs, int length)
405 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
411 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
413 struct wifi_data *wifi = data;
415 if (!wifi->interface ||
416 !g_supplicant_interface_has_p2p(wifi->interface))
419 if (!wifi->servicing) {
420 g_supplicant_interface_p2p_listen(wifi->interface,
421 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
427 static void register_wfd_service_cb(int result,
428 GSupplicantInterface *iface, void *user_data)
430 struct peer_service_registration *reg_data = user_data;
435 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
437 if (reg_data && reg_data->callback) {
438 reg_data->callback(result, reg_data->user_data);
443 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
444 const unsigned char *spec,
445 int spec_length, const unsigned char *query,
446 int query_length, int version)
448 GSupplicantP2PServiceParams *params;
450 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
455 params->version = version;
456 params->service = g_memdup(spec, spec_length);
457 } else if (query_length > 0 && spec_length > 0) {
458 params->query = g_memdup(query, query_length);
459 params->query_length = query_length;
461 params->response = g_memdup(spec, spec_length);
462 params->response_length = spec_length;
464 params->wfd_ies = g_memdup(spec, spec_length);
465 params->wfd_ies_length = spec_length;
471 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
476 g_free(params->service);
477 g_free(params->query);
478 g_free(params->response);
479 g_free(params->wfd_ies);
484 static int peer_register_wfd_service(const unsigned char *specification,
485 int specification_length,
486 peer_service_registration_cb_t callback,
489 struct peer_service_registration *reg_data = NULL;
490 static GSupplicantP2PServiceParams *params;
495 if (wfd_service_registered)
498 params = fill_in_peer_service_params(specification,
499 specification_length, NULL, 0, 0);
503 reg_data = g_try_malloc0(sizeof(*reg_data));
509 reg_data->callback = callback;
510 reg_data->user_data = user_data;
512 ret = g_supplicant_set_widi_ies(params,
513 register_wfd_service_cb, reg_data);
514 if (ret < 0 && ret != -EINPROGRESS)
517 wfd_service_registered = true;
521 free_peer_service_params(params);
527 static void register_peer_service_cb(int result,
528 GSupplicantInterface *iface, void *user_data)
530 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
531 struct peer_service_registration *reg_data = user_data;
536 apply_p2p_listen_on_iface(wifi, NULL);
538 if (reg_data->callback)
539 reg_data->callback(result, reg_data->user_data);
544 static int peer_register_service(const unsigned char *specification,
545 int specification_length,
546 const unsigned char *query,
547 int query_length, int version,
548 peer_service_registration_cb_t callback,
551 struct peer_service_registration *reg_data;
552 GSupplicantP2PServiceParams *params;
559 if (specification && !version && !query &&
560 is_service_wfd(specification, specification_length)) {
561 return peer_register_wfd_service(specification,
562 specification_length, callback, user_data);
565 reg_data = g_try_malloc0(sizeof(*reg_data));
569 reg_data->callback = callback;
570 reg_data->user_data = user_data;
574 for (list = iface_list; list; list = list->next) {
575 struct wifi_data *wifi = list->data;
576 GSupplicantInterface *iface = wifi->interface;
578 if (!g_supplicant_interface_has_p2p(iface))
581 params = fill_in_peer_service_params(specification,
582 specification_length, query,
583 query_length, version);
590 ret_f = g_supplicant_interface_p2p_add_service(iface,
591 register_peer_service_cb, params, reg_data);
592 if (ret_f == 0 || ret_f == -EINPROGRESS)
596 ret = g_supplicant_interface_p2p_add_service(iface,
597 register_peer_service_cb, params, NULL);
598 if (ret != 0 && ret != -EINPROGRESS)
599 free_peer_service_params(params);
602 if (ret_f != 0 && ret_f != -EINPROGRESS)
608 static int peer_unregister_wfd_service(void)
610 GSupplicantP2PServiceParams *params;
613 if (!wfd_service_registered)
616 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
620 wfd_service_registered = false;
622 g_supplicant_set_widi_ies(params, NULL, NULL);
624 for (list = iface_list; list; list = list->next) {
625 struct wifi_data *wifi = list->data;
627 if (!g_supplicant_interface_has_p2p(wifi->interface))
631 if (!wifi->servicing || wifi->servicing < 0) {
632 g_supplicant_interface_p2p_listen(wifi->interface,
641 static int peer_unregister_service(const unsigned char *specification,
642 int specification_length,
643 const unsigned char *query,
644 int query_length, int version)
646 GSupplicantP2PServiceParams *params;
651 if (specification && !version && !query &&
652 is_service_wfd(specification, specification_length)) {
653 ret = peer_unregister_wfd_service();
654 if (ret != 0 && ret != -EINPROGRESS)
659 for (list = iface_list; list; list = list->next) {
660 struct wifi_data *wifi = list->data;
661 GSupplicantInterface *iface = wifi->interface;
666 if (!g_supplicant_interface_has_p2p(iface))
669 params = fill_in_peer_service_params(specification,
670 specification_length, query,
671 query_length, version);
677 ret = g_supplicant_interface_p2p_del_service(iface, params);
678 if (ret != 0 && ret != -EINPROGRESS)
679 free_peer_service_params(params);
682 if (!wifi->servicing || wifi->servicing < 0) {
683 g_supplicant_interface_p2p_listen(iface, 0, 0);
691 static struct connman_peer_driver peer_driver = {
692 .connect = peer_connect,
693 .disconnect = peer_disconnect,
694 .register_service = peer_register_service,
695 .unregister_service = peer_unregister_service,
698 static void handle_tethering(struct wifi_data *wifi)
700 if (!wifi->tethering)
709 DBG("index %d bridge %s", wifi->index, wifi->bridge);
711 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
714 wifi->bridged = true;
717 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
719 struct connman_device *device = user_data;
720 struct wifi_data *wifi = connman_device_get_data(device);
725 DBG("index %d flags %d change %d", wifi->index, flags, change);
727 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
731 DBG("interface down");
734 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
735 if (flags & IFF_LOWER_UP) {
738 handle_tethering(wifi);
746 static int wifi_probe(struct connman_device *device)
748 struct wifi_data *wifi;
750 DBG("device %p", device);
752 wifi = g_try_new0(struct wifi_data, 1);
756 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
758 connman_device_set_data(device, wifi);
759 wifi->device = connman_device_ref(device);
761 wifi->index = connman_device_get_index(device);
764 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
765 wifi_newlink, device);
766 if (is_p2p_connecting())
767 add_pending_wifi_device(wifi);
769 iface_list = g_list_append(iface_list, wifi);
774 static void remove_networks(struct connman_device *device,
775 struct wifi_data *wifi)
779 for (list = wifi->networks; list; list = list->next) {
780 struct connman_network *network = list->data;
782 connman_device_remove_network(device, network);
783 connman_network_unref(network);
786 g_slist_free(wifi->networks);
787 wifi->networks = NULL;
790 static void reset_autoscan(struct connman_device *device)
792 struct wifi_data *wifi = connman_device_get_data(device);
793 struct autoscan_params *autoscan;
797 if (!wifi || !wifi->autoscan)
800 autoscan = wifi->autoscan;
802 if (autoscan->timeout == 0 && autoscan->interval == 0)
805 g_source_remove(autoscan->timeout);
807 autoscan->timeout = 0;
808 autoscan->interval = 0;
810 connman_device_unref(device);
813 static void stop_autoscan(struct connman_device *device)
815 const struct wifi_data *wifi = connman_device_get_data(device);
817 if (!wifi || !wifi->autoscan)
820 reset_autoscan(device);
822 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
825 static void check_p2p_technology(void)
827 bool p2p_exists = false;
830 for (list = iface_list; list; list = list->next) {
831 struct wifi_data *w = list->data;
834 g_supplicant_interface_has_p2p(w->interface))
839 connman_technology_driver_unregister(&p2p_tech_driver);
840 connman_peer_driver_unregister(&peer_driver);
844 static void wifi_remove(struct connman_device *device)
846 struct wifi_data *wifi = connman_device_get_data(device);
848 DBG("device %p wifi %p", device, wifi);
853 stop_autoscan(device);
855 if (wifi->p2p_device)
856 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
858 iface_list = g_list_remove(iface_list, wifi);
860 check_p2p_technology();
862 remove_pending_wifi_device(wifi);
864 if (wifi->p2p_find_timeout) {
865 g_source_remove(wifi->p2p_find_timeout);
866 connman_device_unref(wifi->device);
869 if (wifi->p2p_connection_timeout)
870 g_source_remove(wifi->p2p_connection_timeout);
872 remove_networks(device, wifi);
874 connman_device_set_powered(device, false);
875 connman_device_set_data(device, NULL);
876 connman_device_unref(wifi->device);
877 connman_rtnl_remove_watch(wifi->watch);
879 g_supplicant_interface_set_data(wifi->interface, NULL);
881 g_supplicant_interface_cancel(wifi->interface);
883 if (wifi->scan_params)
884 g_supplicant_free_scan_params(wifi->scan_params);
886 g_free(wifi->autoscan);
887 g_free(wifi->identifier);
891 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
895 for (iter = list; iter; iter = g_slist_next(iter)) {
896 struct scan_ssid *scan_ssid = iter->data;
898 if (ssid_len == scan_ssid->ssid_len &&
899 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
906 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
907 int freq, GSupplicantScanParams *scan_data,
908 int driver_max_scan_ssids, char *ssid_name)
911 struct scan_ssid *scan_ssid;
913 if ((driver_max_scan_ssids == 0 ||
914 driver_max_scan_ssids > scan_data->num_ssids) &&
915 (hex_ssid || raw_ssid)) {
917 unsigned int j = 0, hex;
920 size_t hex_ssid_len = strlen(hex_ssid);
922 ssid = g_try_malloc0(hex_ssid_len / 2);
926 for (i = 0; i < hex_ssid_len; i += 2) {
927 sscanf(hex_ssid + i, "%02x", &hex);
936 * If we have already added hidden AP to the list,
937 * then do not do it again. This might happen if you have
938 * used or are using multiple wifi cards, so in that case
939 * you might have multiple service files for same AP.
941 if (is_duplicate(scan_data->ssids, ssid, j)) {
947 scan_ssid = g_try_new(struct scan_ssid, 1);
954 memcpy(scan_ssid->ssid, ssid, j);
955 scan_ssid->ssid_len = j;
956 scan_data->ssids = g_slist_prepend(scan_data->ssids,
959 scan_data->num_ssids++;
961 DBG("SSID %s added to scanned list of %d entries", ssid_name,
962 scan_data->num_ssids);
969 scan_data->ssids = g_slist_reverse(scan_data->ssids);
971 if (!scan_data->freqs) {
972 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
973 if (!scan_data->freqs) {
974 g_slist_free_full(scan_data->ssids, g_free);
978 scan_data->num_freqs = 1;
979 scan_data->freqs[0] = freq;
981 bool duplicate = false;
983 /* Don't add duplicate entries */
984 for (i = 0; i < scan_data->num_freqs; i++) {
985 if (scan_data->freqs[i] == freq) {
992 scan_data->num_freqs++;
993 scan_data->freqs = g_try_realloc(scan_data->freqs,
994 sizeof(uint16_t) * scan_data->num_freqs);
995 if (!scan_data->freqs) {
996 g_slist_free_full(scan_data->ssids, g_free);
999 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1006 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1008 struct connman_config_entry **entries;
1014 int num_ssids = 0, add_param_failed = 0;
1016 services = connman_storage_get_services();
1017 for (i = 0; services && services[i]; i++) {
1018 if (strncmp(services[i], "wifi_", 5) != 0)
1021 keyfile = connman_storage_load_service(services[i]);
1025 value = g_key_file_get_boolean(keyfile,
1026 services[i], "Hidden", NULL);
1028 g_key_file_free(keyfile);
1032 value = g_key_file_get_boolean(keyfile,
1033 services[i], "Favorite", NULL);
1035 g_key_file_free(keyfile);
1039 #if defined TIZEN_EXT
1040 value = g_key_file_get_boolean(keyfile,
1041 services[i], "AutoConnect", NULL);
1043 g_key_file_free(keyfile);
1048 ssid = g_key_file_get_string(keyfile,
1049 services[i], "SSID", NULL);
1051 name = g_key_file_get_string(keyfile, services[i], "Name",
1054 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1062 g_key_file_free(keyfile);
1066 * Check if there are any hidden AP that needs to be provisioned.
1068 entries = connman_config_get_entries("wifi");
1069 for (i = 0; entries && entries[i]; i++) {
1072 if (!entries[i]->hidden)
1075 if (!entries[i]->ssid) {
1076 ssid = entries[i]->name;
1079 ssid = entries[i]->ssid;
1080 len = entries[i]->ssid_len;
1086 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1093 connman_config_free_entries(entries);
1095 if (add_param_failed > 0)
1096 DBG("Unable to scan %d out of %d SSIDs",
1097 add_param_failed, num_ssids);
1099 g_strfreev(services);
1104 static int get_hidden_connections_params(struct wifi_data *wifi,
1105 GSupplicantScanParams *scan_params)
1107 int driver_max_ssids, i;
1108 GSupplicantScanParams *orig_params;
1111 * Scan hidden networks so that we can autoconnect to them.
1112 * We will assume 1 as a default number of ssid to scan.
1114 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1116 if (driver_max_ssids == 0)
1117 driver_max_ssids = 1;
1119 DBG("max ssids %d", driver_max_ssids);
1121 if (!wifi->scan_params) {
1122 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1123 if (!wifi->scan_params)
1126 if (get_hidden_connections(wifi->scan_params) == 0) {
1127 g_supplicant_free_scan_params(wifi->scan_params);
1128 wifi->scan_params = NULL;
1134 orig_params = wifi->scan_params;
1136 /* Let's transfer driver_max_ssids params */
1137 for (i = 0; i < driver_max_ssids; i++) {
1138 struct scan_ssid *ssid;
1140 if (!wifi->scan_params->ssids)
1143 ssid = orig_params->ssids->data;
1144 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1145 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1149 scan_params->num_ssids = i;
1150 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1152 scan_params->freqs = g_memdup(orig_params->freqs,
1153 sizeof(uint16_t) * orig_params->num_freqs);
1154 if (!scan_params->freqs)
1157 scan_params->num_freqs = orig_params->num_freqs;
1162 orig_params->num_ssids -= scan_params->num_ssids;
1164 return scan_params->num_ssids;
1167 g_slist_free_full(scan_params->ssids, g_free);
1168 g_supplicant_free_scan_params(wifi->scan_params);
1169 wifi->scan_params = NULL;
1174 static int throw_wifi_scan(struct connman_device *device,
1175 GSupplicantInterfaceCallback callback)
1177 struct wifi_data *wifi = connman_device_get_data(device);
1183 DBG("device %p %p", device, wifi->interface);
1185 if (wifi->tethering)
1187 #if defined TIZEN_EXT
1188 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1190 if (connman_device_get_scanning(device))
1194 connman_device_ref(device);
1196 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1199 connman_device_set_scanning(device,
1200 CONNMAN_SERVICE_TYPE_WIFI, true);
1202 connman_device_unref(device);
1207 static void hidden_free(struct hidden_params *hidden)
1212 if (hidden->scan_params)
1213 g_supplicant_free_scan_params(hidden->scan_params);
1214 g_free(hidden->identity);
1215 g_free(hidden->passphrase);
1216 g_free(hidden->security);
1220 #if defined TIZEN_EXT
1221 static void service_state_changed(struct connman_service *service,
1222 enum connman_service_state state);
1224 static int network_connect(struct connman_network *network);
1226 static struct connman_notifier notifier = {
1228 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1229 .service_state_changed = service_state_changed,
1232 static void service_state_changed(struct connman_service *service,
1233 enum connman_service_state state)
1235 enum connman_service_type type;
1237 type = connman_service_get_type(service);
1238 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1241 DBG("service %p state %d", service, state);
1244 case CONNMAN_SERVICE_STATE_READY:
1245 case CONNMAN_SERVICE_STATE_ONLINE:
1246 case CONNMAN_SERVICE_STATE_FAILURE:
1247 connman_notifier_unregister(¬ifier);
1248 is_wifi_notifier_registered = FALSE;
1250 __connman_device_request_scan(type);
1259 static void scan_callback(int result, GSupplicantInterface *interface,
1262 struct connman_device *device = user_data;
1263 struct wifi_data *wifi = connman_device_get_data(device);
1266 DBG("result %d wifi %p", result, wifi);
1269 if (wifi->hidden && !wifi->postpone_hidden) {
1270 connman_network_clear_hidden(wifi->hidden->user_data);
1271 hidden_free(wifi->hidden);
1272 wifi->hidden = NULL;
1275 if (wifi->scan_params) {
1276 g_supplicant_free_scan_params(wifi->scan_params);
1277 wifi->scan_params = NULL;
1282 connman_device_reset_scanning(device);
1284 /* User is connecting to a hidden AP, let's wait for finished event */
1285 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1286 GSupplicantScanParams *scan_params;
1289 wifi->postpone_hidden = false;
1290 scan_params = wifi->hidden->scan_params;
1291 wifi->hidden->scan_params = NULL;
1293 reset_autoscan(device);
1295 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1296 scan_callback, device);
1300 /* On error, let's recall scan_callback, which will cleanup */
1301 return scan_callback(ret, interface, user_data);
1304 #if defined TIZEN_EXT
1305 if (wifi && wifi->allow_full_scan) {
1307 DBG("Trigger Full Channel Scan");
1308 wifi->allow_full_scan = FALSE;
1310 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1311 scan_callback, device);
1315 /* On error, let's recall scan_callback, which will cleanup */
1316 return scan_callback(ret, interface, user_data);
1320 scanning = connman_device_get_scanning(device);
1322 connman_device_set_scanning(device,
1323 CONNMAN_SERVICE_TYPE_WIFI, false);
1325 if (result != -ENOLINK)
1326 #if defined TIZEN_EXT
1329 start_autoscan(device);
1332 * If we are here then we were scanning; however, if we are
1333 * also mid-flight disabling the interface, then wifi_disable
1334 * has already cleared the device scanning state and
1335 * unreferenced the device, obviating the need to do it here.
1339 connman_device_unref(device);
1341 #if defined TIZEN_EXT
1342 if (wifi && wifi->scan_pending_network && result != -EIO) {
1343 network_connect(wifi->scan_pending_network);
1344 wifi->scan_pending_network = NULL;
1345 connman_network_set_connecting(wifi->network);
1348 if (is_wifi_notifier_registered != true &&
1349 wifi_first_scan == true && found_with_first_scan == true) {
1350 wifi_first_scan = false;
1351 found_with_first_scan = false;
1353 connman_notifier_register(¬ifier);
1354 is_wifi_notifier_registered = true;
1359 static void scan_callback_hidden(int result,
1360 GSupplicantInterface *interface, void *user_data)
1362 struct connman_device *device = user_data;
1363 struct wifi_data *wifi = connman_device_get_data(device);
1364 GSupplicantScanParams *scan_params;
1367 DBG("result %d wifi %p", result, wifi);
1372 /* User is trying to connect to a hidden AP */
1373 if (wifi->hidden && wifi->postpone_hidden)
1376 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1380 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1381 ret = g_supplicant_interface_scan(wifi->interface,
1383 scan_callback_hidden,
1389 g_supplicant_free_scan_params(scan_params);
1392 scan_callback(result, interface, user_data);
1395 static gboolean autoscan_timeout(gpointer data)
1397 struct connman_device *device = data;
1398 struct wifi_data *wifi = connman_device_get_data(device);
1399 struct autoscan_params *autoscan;
1405 autoscan = wifi->autoscan;
1407 if (autoscan->interval <= 0) {
1408 interval = autoscan->base;
1411 interval = autoscan->interval * autoscan->base;
1413 #if defined TIZEN_EXT
1414 if (autoscan->interval >= autoscan->limit)
1416 if (interval > autoscan->limit)
1418 interval = autoscan->limit;
1420 throw_wifi_scan(wifi->device, scan_callback_hidden);
1423 DBG("interval %d", interval);
1425 autoscan->interval = interval;
1427 autoscan->timeout = g_timeout_add_seconds(interval,
1428 autoscan_timeout, device);
1433 static void start_autoscan(struct connman_device *device)
1435 struct wifi_data *wifi = connman_device_get_data(device);
1436 struct autoscan_params *autoscan;
1443 if (wifi->p2p_device)
1446 if (wifi->connected)
1449 autoscan = wifi->autoscan;
1453 if (autoscan->timeout > 0 || autoscan->interval > 0)
1456 connman_device_ref(device);
1458 autoscan_timeout(device);
1461 static struct autoscan_params *parse_autoscan_params(const char *params)
1463 struct autoscan_params *autoscan;
1468 DBG("Emulating autoscan");
1470 list_params = g_strsplit(params, ":", 0);
1471 if (list_params == 0)
1474 if (g_strv_length(list_params) < 3) {
1475 g_strfreev(list_params);
1479 base = atoi(list_params[1]);
1480 limit = atoi(list_params[2]);
1482 g_strfreev(list_params);
1484 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1486 DBG("Could not allocate memory for autoscan");
1490 DBG("base %d - limit %d", base, limit);
1491 autoscan->base = base;
1492 autoscan->limit = limit;
1497 static void setup_autoscan(struct wifi_data *wifi)
1499 if (!wifi->autoscan)
1500 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1502 start_autoscan(wifi->device);
1505 static void finalize_interface_creation(struct wifi_data *wifi)
1507 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1509 if (!wifi->device) {
1510 connman_error("WiFi device not set");
1514 connman_device_set_powered(wifi->device, true);
1516 if (!connman_setting_get_bool("BackgroundScanning"))
1519 if (wifi->p2p_device)
1522 setup_autoscan(wifi);
1525 static void interface_create_callback(int result,
1526 GSupplicantInterface *interface,
1529 struct wifi_data *wifi = user_data;
1531 DBG("result %d ifname %s, wifi %p", result,
1532 g_supplicant_interface_get_ifname(interface),
1535 if (result < 0 || !wifi)
1538 wifi->interface = interface;
1539 g_supplicant_interface_set_data(interface, wifi);
1541 if (g_supplicant_interface_get_ready(interface)) {
1542 wifi->interface_ready = true;
1543 finalize_interface_creation(wifi);
1547 static int wifi_enable(struct connman_device *device)
1549 struct wifi_data *wifi = connman_device_get_data(device);
1552 const char *driver = connman_option_get_string("wifi");
1555 DBG("device %p %p", device, wifi);
1557 index = connman_device_get_index(device);
1558 if (!wifi || index < 0)
1561 if (is_p2p_connecting())
1562 return -EINPROGRESS;
1564 interface = connman_inet_ifname(index);
1565 ret = g_supplicant_interface_create(interface, driver, NULL,
1566 interface_create_callback,
1573 return -EINPROGRESS;
1576 static int wifi_disable(struct connman_device *device)
1578 struct wifi_data *wifi = connman_device_get_data(device);
1581 DBG("device %p wifi %p", device, wifi);
1586 wifi->connected = false;
1587 wifi->disconnecting = false;
1589 if (wifi->pending_network)
1590 wifi->pending_network = NULL;
1592 stop_autoscan(device);
1594 if (wifi->p2p_find_timeout) {
1595 g_source_remove(wifi->p2p_find_timeout);
1596 wifi->p2p_find_timeout = 0;
1597 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1598 connman_device_unref(wifi->device);
1601 /* In case of a user scan, device is still referenced */
1602 if (connman_device_get_scanning(device)) {
1603 connman_device_set_scanning(device,
1604 CONNMAN_SERVICE_TYPE_WIFI, false);
1605 connman_device_unref(wifi->device);
1608 remove_networks(device, wifi);
1610 #if defined TIZEN_EXT
1611 wifi->scan_pending_network = NULL;
1613 if (is_wifi_notifier_registered == true) {
1614 connman_notifier_unregister(¬ifier);
1615 is_wifi_notifier_registered = false;
1619 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1623 return -EINPROGRESS;
1626 struct last_connected {
1632 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1634 GTimeVal *aval = (GTimeVal *)a;
1635 GTimeVal *bval = (GTimeVal *)b;
1637 /* Note that the sort order is descending */
1638 if (aval->tv_sec < bval->tv_sec)
1641 if (aval->tv_sec > bval->tv_sec)
1647 static void free_entry(gpointer data)
1649 struct last_connected *entry = data;
1651 g_free(entry->ssid);
1655 static int get_latest_connections(int max_ssids,
1656 GSupplicantScanParams *scan_data)
1658 GSequenceIter *iter;
1659 GSequence *latest_list;
1660 struct last_connected *entry;
1669 latest_list = g_sequence_new(free_entry);
1673 services = connman_storage_get_services();
1674 for (i = 0; services && services[i]; i++) {
1675 if (strncmp(services[i], "wifi_", 5) != 0)
1678 keyfile = connman_storage_load_service(services[i]);
1682 str = g_key_file_get_string(keyfile,
1683 services[i], "Favorite", NULL);
1684 if (!str || g_strcmp0(str, "true")) {
1686 g_key_file_free(keyfile);
1691 str = g_key_file_get_string(keyfile,
1692 services[i], "AutoConnect", NULL);
1693 if (!str || g_strcmp0(str, "true")) {
1695 g_key_file_free(keyfile);
1700 str = g_key_file_get_string(keyfile,
1701 services[i], "Modified", NULL);
1703 g_key_file_free(keyfile);
1706 g_time_val_from_iso8601(str, &modified);
1709 ssid = g_key_file_get_string(keyfile,
1710 services[i], "SSID", NULL);
1712 freq = g_key_file_get_integer(keyfile, services[i],
1715 entry = g_try_new(struct last_connected, 1);
1717 g_sequence_free(latest_list);
1718 g_key_file_free(keyfile);
1724 entry->modified = modified;
1727 g_sequence_insert_sorted(latest_list, entry,
1733 g_key_file_free(keyfile);
1736 g_strfreev(services);
1738 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1740 iter = g_sequence_get_begin_iter(latest_list);
1742 for (i = 0; i < num_ssids; i++) {
1743 entry = g_sequence_get(iter);
1745 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1746 entry->modified.tv_sec);
1748 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1749 max_ssids, entry->ssid);
1751 iter = g_sequence_iter_next(iter);
1754 g_sequence_free(latest_list);
1758 static int wifi_scan_simple(struct connman_device *device)
1760 reset_autoscan(device);
1762 return throw_wifi_scan(device, scan_callback_hidden);
1765 static gboolean p2p_find_stop(gpointer data)
1767 struct connman_device *device = data;
1768 struct wifi_data *wifi = connman_device_get_data(device);
1772 wifi->p2p_find_timeout = 0;
1774 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1776 g_supplicant_interface_p2p_stop_find(wifi->interface);
1778 connman_device_unref(device);
1779 reset_autoscan(device);
1784 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1787 struct connman_device *device = user_data;
1788 struct wifi_data *wifi = connman_device_get_data(device);
1790 DBG("result %d wifi %p", result, wifi);
1792 if (wifi->p2p_find_timeout) {
1793 g_source_remove(wifi->p2p_find_timeout);
1794 wifi->p2p_find_timeout = 0;
1800 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1801 p2p_find_stop, device);
1802 if (!wifi->p2p_find_timeout)
1807 p2p_find_stop(device);
1810 static int p2p_find(struct connman_device *device)
1812 struct wifi_data *wifi;
1817 if (!p2p_technology)
1820 wifi = connman_device_get_data(device);
1822 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1825 reset_autoscan(device);
1826 connman_device_ref(device);
1828 ret = g_supplicant_interface_p2p_find(wifi->interface,
1829 p2p_find_callback, device);
1831 connman_device_unref(device);
1832 start_autoscan(device);
1834 connman_device_set_scanning(device,
1835 CONNMAN_SERVICE_TYPE_P2P, true);
1841 #if defined TIZEN_EXT
1842 static void specific_scan_callback(int result, GSupplicantInterface *interface,
1845 struct connman_device *device = user_data;
1846 struct wifi_data *wifi = connman_device_get_data(device);
1849 DBG("result %d wifi %p", result, wifi);
1851 if (wifi && wifi->scan_params) {
1852 g_supplicant_free_scan_params(wifi->scan_params);
1853 wifi->scan_params = NULL;
1856 scanning = connman_device_get_scanning(device);
1858 connman_device_set_scanning(device,
1859 CONNMAN_SERVICE_TYPE_WIFI, false);
1860 connman_device_unref(device);
1864 static int wifi_specific_scan(enum connman_service_type type,
1865 struct connman_device *device, int scan_type,
1866 GSList *specific_scan_list, void *user_data)
1868 GSList *list = NULL;
1870 struct wifi_data *wifi = connman_device_get_data(device);
1871 GSupplicantScanParams *scan_params = NULL;
1872 struct scan_ssid *scan_ssid = NULL;
1881 if (wifi->p2p_device)
1884 if (type == CONNMAN_SERVICE_TYPE_P2P)
1885 return p2p_find(device);
1887 if (wifi->tethering)
1890 scanning = connman_device_get_scanning(device);
1894 DBG("scan_type: %d", scan_type);
1895 if (scan_type == 1) { /* ssid based scan */
1896 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1898 DBG("Failed to allocate memory.");
1902 for (list = specific_scan_list; list; list = list->next) {
1903 ssid = (char *)list->data;
1904 int ssid_len = strlen(ssid);
1906 scan_ssid = g_try_new0(struct scan_ssid, 1);
1908 DBG("Failed to allocate memory.");
1909 g_supplicant_free_scan_params(scan_params);
1913 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
1914 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
1915 scan_ssid->ssid_len = ssid_len;
1916 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
1919 scan_params->num_ssids = count;
1921 } else if (scan_type == 2) { /* frequency based scan */
1923 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1925 DBG("Failed to allocate memory.");
1929 guint num_freqs = g_slist_length(specific_scan_list);
1930 DBG("num_freqs: %d", num_freqs);
1932 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
1933 if (!scan_params->freqs) {
1934 DBG("Failed to allocate memory.");
1935 g_free(scan_params);
1940 for (list = specific_scan_list; list; list = list->next) {
1941 freq = (int)list->data;
1943 scan_params->freqs[count] = freq;
1944 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
1947 scan_params->num_freqs = count;
1950 DBG("Invalid scan");
1954 reset_autoscan(device);
1955 connman_device_ref(device);
1957 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1958 specific_scan_callback, device);
1961 connman_device_set_scanning(device,
1962 CONNMAN_SERVICE_TYPE_WIFI, true);
1964 g_supplicant_free_scan_params(scan_params);
1965 connman_device_unref(device);
1973 * Note that the hidden scan is only used when connecting to this specific
1974 * hidden AP first time. It is not used when system autoconnects to hidden AP.
1976 static int wifi_scan(enum connman_service_type type,
1977 struct connman_device *device,
1978 const char *ssid, unsigned int ssid_len,
1979 const char *identity, const char* passphrase,
1980 const char *security, void *user_data)
1982 struct wifi_data *wifi = connman_device_get_data(device);
1983 GSupplicantScanParams *scan_params = NULL;
1984 struct scan_ssid *scan_ssid;
1985 struct hidden_params *hidden;
1987 int driver_max_ssids = 0;
1994 if (wifi->p2p_device)
1997 if (type == CONNMAN_SERVICE_TYPE_P2P)
1998 return p2p_find(device);
2000 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2002 if (wifi->tethering)
2005 scanning = connman_device_get_scanning(device);
2007 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2011 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2013 DBG("max ssids %d", driver_max_ssids);
2014 if (driver_max_ssids == 0)
2015 return wifi_scan_simple(device);
2019 if (scanning && wifi->hidden && wifi->postpone_hidden)
2025 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2030 scan_ssid = g_try_new(struct scan_ssid, 1);
2032 g_free(scan_params);
2036 memcpy(scan_ssid->ssid, ssid, ssid_len);
2037 scan_ssid->ssid_len = ssid_len;
2038 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2040 scan_params->num_ssids = 1;
2042 hidden = g_try_new0(struct hidden_params, 1);
2044 g_supplicant_free_scan_params(scan_params);
2049 hidden_free(wifi->hidden);
2050 wifi->hidden = NULL;
2053 memcpy(hidden->ssid, ssid, ssid_len);
2054 hidden->ssid_len = ssid_len;
2055 hidden->identity = g_strdup(identity);
2056 hidden->passphrase = g_strdup(passphrase);
2057 hidden->security = g_strdup(security);
2058 hidden->user_data = user_data;
2059 wifi->hidden = hidden;
2062 /* Let's keep this active scan for later,
2063 * when current scan will be over. */
2064 wifi->postpone_hidden = TRUE;
2065 hidden->scan_params = scan_params;
2069 } else if (wifi->connected) {
2070 g_supplicant_free_scan_params(scan_params);
2071 return wifi_scan_simple(device);
2073 ret = get_latest_connections(driver_max_ssids, scan_params);
2075 g_supplicant_free_scan_params(scan_params);
2076 return wifi_scan_simple(device);
2080 connman_device_ref(device);
2082 reset_autoscan(device);
2084 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2085 scan_callback, device);
2088 connman_device_set_scanning(device,
2089 CONNMAN_SERVICE_TYPE_WIFI, true);
2090 #if defined TIZEN_EXT
2091 /*To allow the Full Scan after ssid based scan, set the flag here
2092 It is required because Tizen does not use the ConnMan specific
2093 backgroung Scan feature.Tizen has added the BG Scan feature in
2094 net-config. To sync with up ConnMan, we need to issue the Full Scan
2095 after SSID specific scan.*/
2096 wifi->allow_full_scan = TRUE;
2099 g_supplicant_free_scan_params(scan_params);
2100 connman_device_unref(device);
2103 hidden_free(wifi->hidden);
2104 wifi->hidden = NULL;
2111 static void wifi_regdom_callback(int result,
2115 struct connman_device *device = user_data;
2117 connman_device_regdom_notify(device, result, alpha2);
2119 connman_device_unref(device);
2122 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2124 struct wifi_data *wifi = connman_device_get_data(device);
2130 connman_device_ref(device);
2132 ret = g_supplicant_interface_set_country(wifi->interface,
2133 wifi_regdom_callback,
2136 connman_device_unref(device);
2141 static struct connman_device_driver wifi_ng_driver = {
2143 .type = CONNMAN_DEVICE_TYPE_WIFI,
2144 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2145 .probe = wifi_probe,
2146 .remove = wifi_remove,
2147 .enable = wifi_enable,
2148 .disable = wifi_disable,
2150 .set_regdom = wifi_set_regdom,
2151 #if defined TIZEN_EXT
2152 .specific_scan = wifi_specific_scan,
2156 static void system_ready(void)
2160 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2161 connman_error("Failed to register WiFi driver");
2164 static void system_killed(void)
2168 connman_device_driver_unregister(&wifi_ng_driver);
2171 static int network_probe(struct connman_network *network)
2173 DBG("network %p", network);
2178 static void network_remove(struct connman_network *network)
2180 struct connman_device *device = connman_network_get_device(network);
2181 struct wifi_data *wifi;
2183 DBG("network %p", network);
2185 wifi = connman_device_get_data(device);
2189 if (wifi->network != network)
2192 wifi->network = NULL;
2194 #if defined TIZEN_EXT
2195 wifi->disconnecting = false;
2197 if (wifi->pending_network == network)
2198 wifi->pending_network = NULL;
2200 if (wifi->scan_pending_network == network)
2201 wifi->scan_pending_network = NULL;
2205 static void connect_callback(int result, GSupplicantInterface *interface,
2208 #if defined TIZEN_EXT
2210 struct wifi_data *wifi;
2212 struct connman_network *network = user_data;
2214 DBG("network %p result %d", network, result);
2216 #if defined TIZEN_EXT
2217 for (list = iface_list; list; list = list->next) {
2220 if (wifi && wifi->network == network)
2224 /* wifi_data may be invalid because wifi is already disabled */
2229 if (result == -ENOKEY) {
2230 connman_network_set_error(network,
2231 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2232 } else if (result < 0) {
2233 connman_network_set_error(network,
2234 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2237 connman_network_unref(network);
2240 static GSupplicantSecurity network_security(const char *security)
2242 if (g_str_equal(security, "none"))
2243 return G_SUPPLICANT_SECURITY_NONE;
2244 else if (g_str_equal(security, "wep"))
2245 return G_SUPPLICANT_SECURITY_WEP;
2246 else if (g_str_equal(security, "psk"))
2247 return G_SUPPLICANT_SECURITY_PSK;
2248 else if (g_str_equal(security, "wpa"))
2249 return G_SUPPLICANT_SECURITY_PSK;
2250 else if (g_str_equal(security, "rsn"))
2251 return G_SUPPLICANT_SECURITY_PSK;
2252 else if (g_str_equal(security, "ieee8021x"))
2253 return G_SUPPLICANT_SECURITY_IEEE8021X;
2254 #if defined TIZEN_EXT
2255 else if (g_str_equal(security, "ft_psk") == TRUE)
2256 return G_SUPPLICANT_SECURITY_FT_PSK;
2257 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2258 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2261 return G_SUPPLICANT_SECURITY_UNKNOWN;
2264 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2266 const char *security;
2268 memset(ssid, 0, sizeof(*ssid));
2269 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2270 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2272 ssid->scan_ssid = 1;
2273 security = connman_network_get_string(network, "WiFi.Security");
2274 ssid->security = network_security(security);
2275 ssid->passphrase = connman_network_get_string(network,
2278 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2281 * If our private key password is unset,
2282 * we use the supplied passphrase. That is needed
2283 * for PEAP where 2 passphrases (identity and client
2284 * cert may have to be provided.
2286 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2287 connman_network_set_string(network,
2288 "WiFi.PrivateKeyPassphrase",
2290 /* We must have an identity for both PEAP and TLS */
2291 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2293 /* Use agent provided identity as a fallback */
2294 if (!ssid->identity || strlen(ssid->identity) == 0)
2295 ssid->identity = connman_network_get_string(network,
2296 "WiFi.AgentIdentity");
2298 ssid->ca_cert_path = connman_network_get_string(network,
2300 ssid->client_cert_path = connman_network_get_string(network,
2301 "WiFi.ClientCertFile");
2302 ssid->private_key_path = connman_network_get_string(network,
2303 "WiFi.PrivateKeyFile");
2304 ssid->private_key_passphrase = connman_network_get_string(network,
2305 "WiFi.PrivateKeyPassphrase");
2306 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2308 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2309 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2311 #if defined TIZEN_EXT
2312 ssid->bssid = connman_network_get_bssid(network);
2314 #if defined TIZEN_EXT
2315 ssid->freq = connman_network_get_frequency(network);
2318 if (connman_setting_get_bool("BackgroundScanning"))
2319 ssid->bgscan = BGSCAN_DEFAULT;
2322 static int network_connect(struct connman_network *network)
2324 struct connman_device *device = connman_network_get_device(network);
2325 struct wifi_data *wifi;
2326 GSupplicantInterface *interface;
2327 GSupplicantSSID *ssid;
2329 DBG("network %p", network);
2334 wifi = connman_device_get_data(device);
2338 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2342 interface = wifi->interface;
2344 ssid_init(ssid, network);
2346 if (wifi->disconnecting) {
2347 wifi->pending_network = network;
2350 wifi->network = connman_network_ref(network);
2352 #if defined TIZEN_EXT
2353 wifi->scan_pending_network = NULL;
2356 return g_supplicant_interface_connect(interface, ssid,
2357 connect_callback, network);
2360 return -EINPROGRESS;
2363 static void disconnect_callback(int result, GSupplicantInterface *interface,
2366 #if defined TIZEN_EXT
2368 struct wifi_data *wifi;
2369 struct connman_network *network = user_data;
2371 DBG("network %p result %d", network, result);
2373 for (list = iface_list; list; list = list->next) {
2376 if (wifi->network == NULL && wifi->disconnecting == true)
2377 wifi->disconnecting = false;
2379 if (wifi->network == network)
2383 /* wifi_data may be invalid because wifi is already disabled */
2388 struct wifi_data *wifi = user_data;
2391 DBG("result %d supplicant interface %p wifi %p",
2392 result, interface, wifi);
2394 if (result == -ECONNABORTED) {
2395 DBG("wifi interface no longer available");
2399 if (wifi->network) {
2401 * if result < 0 supplican return an error because
2402 * the network is not current.
2403 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2404 * failed, call connman_network_set_connected to report
2405 * disconnect is completed.
2408 connman_network_set_connected(wifi->network, false);
2411 wifi->network = NULL;
2413 wifi->disconnecting = false;
2415 if (wifi->pending_network) {
2416 network_connect(wifi->pending_network);
2417 wifi->pending_network = NULL;
2420 start_autoscan(wifi->device);
2423 static int network_disconnect(struct connman_network *network)
2425 struct connman_device *device = connman_network_get_device(network);
2426 struct wifi_data *wifi;
2428 #if defined TIZEN_EXT
2429 struct connman_service *service;
2432 DBG("network %p", network);
2434 wifi = connman_device_get_data(device);
2435 if (!wifi || !wifi->interface)
2438 #if defined TIZEN_EXT
2439 if (connman_network_get_associating(network) == true) {
2440 connman_network_clear_associating(network);
2441 connman_network_set_bool(network, "WiFi.UseWPS", false);
2443 service = connman_service_lookup_from_network(network);
2445 if (service != NULL &&
2446 (__connman_service_is_connected_state(service,
2447 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2448 __connman_service_is_connected_state(service,
2449 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2450 (connman_service_get_favorite(service) == false))
2451 __connman_service_set_passphrase(service, NULL);
2454 if (wifi->pending_network == network)
2455 wifi->pending_network = NULL;
2457 if (wifi->scan_pending_network == network)
2458 wifi->scan_pending_network = NULL;
2461 connman_network_set_associating(network, false);
2463 if (wifi->disconnecting)
2466 wifi->disconnecting = true;
2468 #if defined TIZEN_EXT
2469 err = g_supplicant_interface_disconnect(wifi->interface,
2470 disconnect_callback, network);
2472 err = g_supplicant_interface_disconnect(wifi->interface,
2473 disconnect_callback, wifi);
2477 wifi->disconnecting = false;
2482 static struct connman_network_driver network_driver = {
2484 .type = CONNMAN_NETWORK_TYPE_WIFI,
2485 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2486 .probe = network_probe,
2487 .remove = network_remove,
2488 .connect = network_connect,
2489 .disconnect = network_disconnect,
2492 static void interface_added(GSupplicantInterface *interface)
2494 const char *ifname = g_supplicant_interface_get_ifname(interface);
2495 const char *driver = g_supplicant_interface_get_driver(interface);
2496 struct wifi_data *wifi;
2498 wifi = g_supplicant_interface_get_data(interface);
2500 wifi = get_pending_wifi_data(ifname);
2504 g_supplicant_interface_set_data(interface, wifi);
2505 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2506 wifi->p2p_device = true;
2509 DBG("ifname %s driver %s wifi %p tethering %d",
2510 ifname, driver, wifi, wifi->tethering);
2512 if (!wifi->device) {
2513 connman_error("WiFi device not set");
2517 connman_device_set_powered(wifi->device, true);
2520 static bool is_idle(struct wifi_data *wifi)
2522 DBG("state %d", wifi->state);
2524 switch (wifi->state) {
2525 case G_SUPPLICANT_STATE_UNKNOWN:
2526 case G_SUPPLICANT_STATE_DISABLED:
2527 case G_SUPPLICANT_STATE_DISCONNECTED:
2528 case G_SUPPLICANT_STATE_INACTIVE:
2529 case G_SUPPLICANT_STATE_SCANNING:
2532 case G_SUPPLICANT_STATE_AUTHENTICATING:
2533 case G_SUPPLICANT_STATE_ASSOCIATING:
2534 case G_SUPPLICANT_STATE_ASSOCIATED:
2535 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2536 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2537 case G_SUPPLICANT_STATE_COMPLETED:
2544 static bool is_idle_wps(GSupplicantInterface *interface,
2545 struct wifi_data *wifi)
2547 /* First, let's check if WPS processing did not went wrong */
2548 if (g_supplicant_interface_get_wps_state(interface) ==
2549 G_SUPPLICANT_WPS_STATE_FAIL)
2552 /* Unlike normal connection, being associated while processing wps
2553 * actually means that we are idling. */
2554 switch (wifi->state) {
2555 case G_SUPPLICANT_STATE_UNKNOWN:
2556 case G_SUPPLICANT_STATE_DISABLED:
2557 case G_SUPPLICANT_STATE_DISCONNECTED:
2558 case G_SUPPLICANT_STATE_INACTIVE:
2559 case G_SUPPLICANT_STATE_SCANNING:
2560 case G_SUPPLICANT_STATE_ASSOCIATED:
2562 case G_SUPPLICANT_STATE_AUTHENTICATING:
2563 case G_SUPPLICANT_STATE_ASSOCIATING:
2564 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2565 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2566 case G_SUPPLICANT_STATE_COMPLETED:
2573 static bool handle_wps_completion(GSupplicantInterface *interface,
2574 struct connman_network *network,
2575 struct connman_device *device,
2576 struct wifi_data *wifi)
2580 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2582 const unsigned char *ssid, *wps_ssid;
2583 unsigned int ssid_len, wps_ssid_len;
2584 const char *wps_key;
2586 /* Checking if we got associated with requested
2588 ssid = connman_network_get_blob(network, "WiFi.SSID",
2591 wps_ssid = g_supplicant_interface_get_wps_ssid(
2592 interface, &wps_ssid_len);
2594 if (!wps_ssid || wps_ssid_len != ssid_len ||
2595 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2596 connman_network_set_associating(network, false);
2597 #if defined TIZEN_EXT
2598 g_supplicant_interface_disconnect(wifi->interface,
2599 disconnect_callback, wifi->network);
2601 connman_network_set_bool(network, "WiFi.UseWPS", false);
2602 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2604 g_supplicant_interface_disconnect(wifi->interface,
2605 disconnect_callback, wifi);
2610 wps_key = g_supplicant_interface_get_wps_key(interface);
2611 connman_network_set_string(network, "WiFi.Passphrase",
2614 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2620 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2621 struct connman_network *network,
2622 struct wifi_data *wifi)
2624 #if defined TIZEN_EXT
2625 const char *security;
2626 struct connman_service *service;
2628 if (wifi->connected)
2631 security = connman_network_get_string(network, "WiFi.Security");
2633 if (security && g_str_equal(security, "ieee8021x") == true &&
2634 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2636 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2641 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2644 struct connman_service *service;
2646 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2649 if (wifi->connected)
2653 service = connman_service_lookup_from_network(network);
2659 if (connman_service_get_favorite(service)) {
2660 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2665 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2670 #if defined TIZEN_EXT
2671 static bool handle_wifi_assoc_retry(struct connman_network *network,
2672 struct wifi_data *wifi)
2674 const char *security;
2676 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2677 connman_network_get_connecting(network) != true) {
2678 wifi->assoc_retry_count = 0;
2682 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2683 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2684 wifi->assoc_retry_count = 0;
2688 security = connman_network_get_string(network, "WiFi.Security");
2689 if (security && g_str_equal(security, "ieee8021x") == true &&
2690 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2691 wifi->assoc_retry_count = 0;
2695 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2696 wifi->assoc_retry_count = 0;
2698 /* Honestly it's not an invalid-key error,
2699 * however QA team recommends that the invalid-key error
2700 * might be better to display for user experience.
2702 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2711 static void interface_state(GSupplicantInterface *interface)
2713 struct connman_network *network;
2714 struct connman_device *device;
2715 struct wifi_data *wifi;
2716 GSupplicantState state = g_supplicant_interface_get_state(interface);
2719 wifi = g_supplicant_interface_get_data(interface);
2721 DBG("wifi %p interface state %d", wifi, state);
2726 device = wifi->device;
2730 if (g_supplicant_interface_get_ready(interface) &&
2731 !wifi->interface_ready) {
2732 wifi->interface_ready = true;
2733 finalize_interface_creation(wifi);
2736 network = wifi->network;
2741 case G_SUPPLICANT_STATE_SCANNING:
2744 case G_SUPPLICANT_STATE_AUTHENTICATING:
2745 case G_SUPPLICANT_STATE_ASSOCIATING:
2746 #if defined TIZEN_EXT
2747 reset_autoscan(device);
2749 stop_autoscan(device);
2752 if (!wifi->connected)
2753 connman_network_set_associating(network, true);
2757 case G_SUPPLICANT_STATE_COMPLETED:
2758 #if defined TIZEN_EXT
2759 /* though it should be already reset: */
2760 reset_autoscan(device);
2762 wifi->assoc_retry_count = 0;
2764 wifi->scan_pending_network = NULL;
2766 /* should be cleared scanning flag */
2767 bool scanning = connman_device_get_scanning(device);
2769 connman_device_set_scanning(device,
2770 CONNMAN_SERVICE_TYPE_WIFI, false);
2771 connman_device_unref(device);
2774 /* though it should be already stopped: */
2775 stop_autoscan(device);
2778 if (!handle_wps_completion(interface, network, device, wifi))
2781 connman_network_set_connected(network, true);
2782 wifi->disconnect_code = 0;
2785 case G_SUPPLICANT_STATE_DISCONNECTED:
2787 * If we're in one of the idle modes, we have
2788 * not started association yet and thus setting
2789 * those ones to FALSE could cancel an association
2792 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2794 if (is_idle_wps(interface, wifi))
2800 /* If previous state was 4way-handshake, then
2801 * it's either: psk was incorrect and thus we retry
2802 * or if we reach the maximum retries we declare the
2804 if (handle_4way_handshake_failure(interface,
2808 /* See table 8-36 Reason codes in IEEE Std 802.11 */
2809 switch (wifi->disconnect_code) {
2810 case 1: /* Unspecified reason */
2811 /* Let's assume it's because we got blocked */
2813 case 6: /* Class 2 frame received from nonauthenticated STA */
2814 connman_network_set_error(network,
2815 CONNMAN_NETWORK_ERROR_BLOCKED);
2823 /* We disable the selected network, if not then
2824 * wpa_supplicant will loop retrying */
2825 if (g_supplicant_interface_enable_selected_network(interface,
2827 DBG("Could not disables selected network");
2829 #if defined TIZEN_EXT
2832 err = g_supplicant_interface_remove_network(wifi->interface);
2834 DBG("Failed to remove network(%d)", err);
2837 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2838 * Retry association until its retry count is expired */
2839 if (handle_wifi_assoc_retry(network, wifi) == true) {
2840 throw_wifi_scan(wifi->device, scan_callback);
2841 wifi->scan_pending_network = wifi->network;
2845 if(wifi->disconnect_code > 0){
2846 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
2847 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
2850 /* To avoid unnecessary repeated association in wpa_supplicant,
2851 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2852 if (wps != true && wifi->network && wifi->disconnecting == false) {
2853 wifi->disconnecting = true;
2854 err = g_supplicant_interface_disconnect(wifi->interface,
2855 disconnect_callback, wifi->network);
2857 wifi->disconnecting = false;
2859 connman_network_set_connected(network, false);
2860 connman_network_set_associating(network, false);
2862 start_autoscan(device);
2868 connman_network_set_connected(network, false);
2869 connman_network_set_associating(network, false);
2870 wifi->disconnecting = false;
2872 start_autoscan(device);
2876 case G_SUPPLICANT_STATE_INACTIVE:
2877 #if defined TIZEN_EXT
2878 if (handle_wps_completion(interface, network, device, wifi) == false)
2881 connman_network_set_associating(network, false);
2882 start_autoscan(device);
2886 case G_SUPPLICANT_STATE_UNKNOWN:
2887 case G_SUPPLICANT_STATE_DISABLED:
2888 case G_SUPPLICANT_STATE_ASSOCIATED:
2889 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2890 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2894 wifi->state = state;
2896 /* Saving wpa_s state policy:
2897 * If connected and if the state changes are roaming related:
2898 * --> We stay connected
2900 * --> We are connected
2902 * --> We are not connected
2905 #if defined TIZEN_EXT
2906 case G_SUPPLICANT_STATE_SCANNING:
2909 case G_SUPPLICANT_STATE_AUTHENTICATING:
2910 case G_SUPPLICANT_STATE_ASSOCIATING:
2911 case G_SUPPLICANT_STATE_ASSOCIATED:
2912 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2913 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2914 if (wifi->connected)
2915 connman_warn("Probably roaming right now!"
2916 " Staying connected...");
2918 wifi->connected = false;
2920 case G_SUPPLICANT_STATE_COMPLETED:
2921 wifi->connected = true;
2924 wifi->connected = false;
2931 static void interface_removed(GSupplicantInterface *interface)
2933 const char *ifname = g_supplicant_interface_get_ifname(interface);
2934 struct wifi_data *wifi;
2936 DBG("ifname %s", ifname);
2938 wifi = g_supplicant_interface_get_data(interface);
2941 wifi->interface = NULL;
2943 if (wifi && wifi->tethering)
2946 if (!wifi || !wifi->device) {
2947 DBG("wifi interface already removed");
2951 connman_device_set_powered(wifi->device, false);
2953 check_p2p_technology();
2956 static void set_device_type(const char *type, char dev_type[17])
2958 const char *oui = "0050F204";
2959 const char *category = "0100";
2960 const char *sub_category = "0000";
2962 if (!g_strcmp0(type, "handset")) {
2964 sub_category = "0500";
2965 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2966 sub_category = "0100";
2967 else if (!g_strcmp0(type, "server"))
2968 sub_category = "0200";
2969 else if (!g_strcmp0(type, "laptop"))
2970 sub_category = "0500";
2971 else if (!g_strcmp0(type, "desktop"))
2972 sub_category = "0600";
2973 else if (!g_strcmp0(type, "tablet"))
2974 sub_category = "0900";
2975 else if (!g_strcmp0(type, "watch"))
2978 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2981 static void p2p_support(GSupplicantInterface *interface)
2983 char dev_type[17] = {};
2984 const char *hostname;
2988 if (!g_supplicant_interface_has_p2p(interface))
2991 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2992 DBG("Could not register P2P technology driver");
2996 hostname = connman_utsname_get_hostname();
2998 hostname = "ConnMan";
3000 set_device_type(connman_machine_get_type(), dev_type);
3001 g_supplicant_interface_set_p2p_device_config(interface,
3002 hostname, dev_type);
3003 connman_peer_driver_register(&peer_driver);
3006 static void scan_started(GSupplicantInterface *interface)
3011 static void scan_finished(GSupplicantInterface *interface)
3013 #if defined TIZEN_EXT
3014 struct wifi_data *wifi;
3015 bool is_associating = false;
3016 static bool is_scanning = true;
3021 #if defined TIZEN_EXT
3022 wifi = g_supplicant_interface_get_data(interface);
3023 if (wifi && wifi->scan_pending_network) {
3024 network_connect(wifi->scan_pending_network);
3025 wifi->scan_pending_network = NULL;
3028 //service state - associating
3029 if(!wifi || !wifi->network)
3032 is_associating = connman_network_get_associating(wifi->network);
3033 if(is_associating && is_scanning){
3034 is_scanning = false;
3035 DBG("send scan for connecting");
3036 throw_wifi_scan(wifi->device, scan_callback);
3047 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3049 unsigned char strength;
3051 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3053 #if !defined TIZEN_EXT
3060 static void network_added(GSupplicantNetwork *supplicant_network)
3062 struct connman_network *network;
3063 GSupplicantInterface *interface;
3064 struct wifi_data *wifi;
3065 const char *name, *identifier, *security, *group, *mode;
3066 const unsigned char *ssid;
3067 unsigned int ssid_len;
3071 bool wps_advertizing;
3073 #if defined TIZEN_EXT
3074 const char *wifi_vsie;
3075 unsigned int wifi_vsie_len;
3078 mode = g_supplicant_network_get_mode(supplicant_network);
3079 identifier = g_supplicant_network_get_identifier(supplicant_network);
3081 DBG("%s", identifier);
3083 if (!g_strcmp0(mode, "adhoc"))
3086 interface = g_supplicant_network_get_interface(supplicant_network);
3087 wifi = g_supplicant_interface_get_data(interface);
3088 name = g_supplicant_network_get_name(supplicant_network);
3089 security = g_supplicant_network_get_security(supplicant_network);
3090 group = g_supplicant_network_get_identifier(supplicant_network);
3091 wps = g_supplicant_network_get_wps(supplicant_network);
3092 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3093 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3094 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3095 supplicant_network);
3100 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3102 #if defined TIZEN_EXT
3103 wifi_vsie = g_supplicant_network_get_wifi_vsie(supplicant_network, &wifi_vsie_len);
3105 network = connman_device_get_network(wifi->device, identifier);
3108 network = connman_network_create(identifier,
3109 CONNMAN_NETWORK_TYPE_WIFI);
3113 connman_network_set_index(network, wifi->index);
3115 if (connman_device_add_network(wifi->device, network) < 0) {
3116 connman_network_unref(network);
3120 wifi->networks = g_slist_prepend(wifi->networks, network);
3123 if (name && name[0] != '\0')
3124 connman_network_set_name(network, name);
3126 connman_network_set_blob(network, "WiFi.SSID",
3128 #if defined TIZEN_EXT
3129 if(wifi_vsie_len > 0 && wifi_vsie)
3130 connman_network_set_blob(network, "WiFi.Vsie",
3131 wifi_vsie, wifi_vsie_len);
3133 connman_network_set_string(network, "WiFi.Security", security);
3134 connman_network_set_strength(network,
3135 calculate_strength(supplicant_network));
3136 connman_network_set_bool(network, "WiFi.WPS", wps);
3139 /* Is AP advertizing for WPS association?
3140 * If so, we decide to use WPS by default */
3141 if (wps_ready && wps_pbc &&
3143 #if !defined TIZEN_EXT
3144 connman_network_set_bool(network, "WiFi.UseWPS", true);
3146 DBG("wps is activating by ap but ignore it.");
3151 connman_network_set_frequency(network,
3152 g_supplicant_network_get_frequency(supplicant_network));
3153 #if defined TIZEN_EXT
3154 connman_network_set_bssid(network,
3155 g_supplicant_network_get_bssid(supplicant_network));
3156 connman_network_set_maxrate(network,
3157 g_supplicant_network_get_maxrate(supplicant_network));
3158 connman_network_set_enc_mode(network,
3159 g_supplicant_network_get_enc_mode(supplicant_network));
3160 connman_network_set_rsn_mode(network,
3161 g_supplicant_network_get_rsn_mode(supplicant_network));
3162 connman_network_set_keymgmt(network,
3163 g_supplicant_network_get_keymgmt(supplicant_network));
3165 connman_network_set_available(network, true);
3166 connman_network_set_string(network, "WiFi.Mode", mode);
3168 #if defined TIZEN_EXT
3173 connman_network_set_group(network, group);
3175 #if defined TIZEN_EXT
3176 if (wifi_first_scan == true)
3177 found_with_first_scan = true;
3180 if (wifi->hidden && ssid) {
3181 #if defined TIZEN_EXT
3182 if (network_security(wifi->hidden->security) ==
3183 network_security(security) &&
3185 if (!g_strcmp0(wifi->hidden->security, security) &&
3187 wifi->hidden->ssid_len == ssid_len &&
3188 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3189 connman_network_connect_hidden(network,
3190 wifi->hidden->identity,
3191 wifi->hidden->passphrase,
3192 wifi->hidden->user_data);
3193 wifi->hidden->user_data = NULL;
3194 hidden_free(wifi->hidden);
3195 wifi->hidden = NULL;
3200 static void network_removed(GSupplicantNetwork *network)
3202 GSupplicantInterface *interface;
3203 struct wifi_data *wifi;
3204 const char *name, *identifier;
3205 struct connman_network *connman_network;
3207 interface = g_supplicant_network_get_interface(network);
3208 wifi = g_supplicant_interface_get_data(interface);
3209 identifier = g_supplicant_network_get_identifier(network);
3210 name = g_supplicant_network_get_name(network);
3212 DBG("name %s", name);
3217 connman_network = connman_device_get_network(wifi->device, identifier);
3218 if (!connman_network)
3221 #if defined TIZEN_EXT
3222 if (connman_network == wifi->scan_pending_network)
3223 wifi->scan_pending_network = NULL;
3225 if (connman_network == wifi->pending_network)
3226 wifi->pending_network = NULL;
3228 if(connman_network_get_connecting(connman_network) == true){
3229 connman_network_set_connected(connman_network, false);
3233 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3235 connman_device_remove_network(wifi->device, connman_network);
3236 connman_network_unref(connman_network);
3239 static void network_changed(GSupplicantNetwork *network, const char *property)
3241 GSupplicantInterface *interface;
3242 struct wifi_data *wifi;
3243 const char *name, *identifier;
3244 struct connman_network *connman_network;
3246 #if defined TIZEN_EXT
3247 const unsigned char *bssid;
3248 unsigned int maxrate;
3253 interface = g_supplicant_network_get_interface(network);
3254 wifi = g_supplicant_interface_get_data(interface);
3255 identifier = g_supplicant_network_get_identifier(network);
3256 name = g_supplicant_network_get_name(network);
3258 DBG("name %s", name);
3263 connman_network = connman_device_get_network(wifi->device, identifier);
3264 if (!connman_network)
3267 if (g_str_equal(property, "Signal")) {
3268 connman_network_set_strength(connman_network,
3269 calculate_strength(network));
3270 connman_network_update(connman_network);
3273 #if defined TIZEN_EXT
3274 bssid = g_supplicant_network_get_bssid(network);
3275 maxrate = g_supplicant_network_get_maxrate(network);
3276 frequency = g_supplicant_network_get_frequency(network);
3277 wps = g_supplicant_network_get_wps(network);
3279 connman_network_set_bssid(connman_network, bssid);
3280 connman_network_set_maxrate(connman_network, maxrate);
3281 connman_network_set_frequency(connman_network, frequency);
3282 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3286 static void apply_peer_services(GSupplicantPeer *peer,
3287 struct connman_peer *connman_peer)
3289 const unsigned char *data;
3294 connman_peer_reset_services(connman_peer);
3296 data = g_supplicant_peer_get_widi_ies(peer, &length);
3298 connman_peer_add_service(connman_peer,
3299 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3303 static void add_station(const char *mac)
3305 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3309 static void remove_station(const char *mac)
3311 connman_technology_tethering_remove_station(mac);
3314 static void peer_found(GSupplicantPeer *peer)
3316 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3317 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3318 struct connman_peer *connman_peer;
3319 const char *identifier, *name;
3322 identifier = g_supplicant_peer_get_identifier(peer);
3323 name = g_supplicant_peer_get_name(peer);
3325 DBG("ident: %s", identifier);
3327 connman_peer = connman_peer_get(wifi->device, identifier);
3331 connman_peer = connman_peer_create(identifier);
3332 connman_peer_set_name(connman_peer, name);
3333 connman_peer_set_device(connman_peer, wifi->device);
3334 apply_peer_services(peer, connman_peer);
3336 ret = connman_peer_register(connman_peer);
3337 if (ret < 0 && ret != -EALREADY)
3338 connman_peer_unref(connman_peer);
3341 static void peer_lost(GSupplicantPeer *peer)
3343 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3344 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3345 struct connman_peer *connman_peer;
3346 const char *identifier;
3351 identifier = g_supplicant_peer_get_identifier(peer);
3353 DBG("ident: %s", identifier);
3355 connman_peer = connman_peer_get(wifi->device, identifier);
3357 if (wifi->p2p_connecting &&
3358 wifi->pending_peer == connman_peer) {
3359 peer_connect_timeout(wifi);
3361 connman_peer_unregister(connman_peer);
3362 connman_peer_unref(connman_peer);
3366 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3368 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3369 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3370 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3371 struct connman_peer *connman_peer;
3372 const char *identifier;
3374 identifier = g_supplicant_peer_get_identifier(peer);
3376 DBG("ident: %s", identifier);
3378 connman_peer = connman_peer_get(wifi->device, identifier);
3383 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3384 apply_peer_services(peer, connman_peer);
3385 connman_peer_services_changed(connman_peer);
3387 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3388 if (!g_supplicant_peer_is_in_a_group(peer))
3389 p_state = CONNMAN_PEER_STATE_IDLE;
3391 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3393 case G_SUPPLICANT_PEER_GROUP_STARTED:
3395 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3396 p_state = CONNMAN_PEER_STATE_IDLE;
3398 case G_SUPPLICANT_PEER_GROUP_JOINED:
3399 connman_peer_set_iface_address(connman_peer,
3400 g_supplicant_peer_get_iface_address(peer));
3402 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3403 p_state = CONNMAN_PEER_STATE_IDLE;
3405 case G_SUPPLICANT_PEER_GROUP_FAILED:
3406 if (g_supplicant_peer_has_requested_connection(peer))
3407 p_state = CONNMAN_PEER_STATE_IDLE;
3409 p_state = CONNMAN_PEER_STATE_FAILURE;
3413 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3414 p_state == CONNMAN_PEER_STATE_FAILURE) {
3415 if (wifi->p2p_connecting
3416 && connman_peer == wifi->pending_peer)
3417 peer_cancel_timeout(wifi);
3419 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3422 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3425 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3426 GSupplicantInterface *g_iface;
3427 struct wifi_data *g_wifi;
3429 g_iface = g_supplicant_peer_get_group_interface(peer);
3433 g_wifi = g_supplicant_interface_get_data(g_iface);
3437 connman_peer_set_as_master(connman_peer,
3438 !g_supplicant_peer_is_client(peer));
3439 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3442 connman_peer_set_state(connman_peer, p_state);
3445 static void peer_request(GSupplicantPeer *peer)
3447 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3448 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3449 struct connman_peer *connman_peer;
3450 const char *identifier;
3452 identifier = g_supplicant_peer_get_identifier(peer);
3454 DBG("ident: %s", identifier);
3456 connman_peer = connman_peer_get(wifi->device, identifier);
3460 connman_peer_request_connection(connman_peer);
3463 #if defined TIZEN_EXT
3464 static void system_power_off(void)
3467 struct wifi_data *wifi;
3468 struct connman_service *service;
3469 struct connman_ipconfig *ipconfig_ipv4;
3471 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3472 for (list = iface_list; list; list = list->next) {
3475 if (wifi->network != NULL) {
3476 service = connman_service_lookup_from_network(wifi->network);
3477 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3478 __connman_dhcp_stop(ipconfig_ipv4);
3484 static void network_merged(GSupplicantNetwork *network)
3486 GSupplicantInterface *interface;
3487 GSupplicantState state;
3488 struct wifi_data *wifi;
3489 const char *identifier;
3490 struct connman_network *connman_network;
3491 unsigned int ishs20AP = 0;
3494 interface = g_supplicant_network_get_interface(network);
3498 state = g_supplicant_interface_get_state(interface);
3499 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3502 wifi = g_supplicant_interface_get_data(interface);
3506 identifier = g_supplicant_network_get_identifier(network);
3508 connman_network = connman_device_get_network(wifi->device, identifier);
3509 if (!connman_network)
3512 DBG("merged identifier %s", identifier);
3514 if (wifi->connected == FALSE) {
3516 case G_SUPPLICANT_STATE_AUTHENTICATING:
3517 case G_SUPPLICANT_STATE_ASSOCIATING:
3518 case G_SUPPLICANT_STATE_ASSOCIATED:
3519 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3520 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3521 connman_network_set_associating(connman_network, TRUE);
3523 case G_SUPPLICANT_STATE_COMPLETED:
3524 connman_network_set_connected(connman_network, TRUE);
3527 DBG("Not handled the state : %d", state);
3532 ishs20AP = g_supplicant_network_is_hs20AP(network);
3533 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3536 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3537 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3538 connman_network_set_string(connman_network, "WiFi.EAP",
3540 connman_network_set_string(connman_network, "WiFi.Identity",
3541 g_supplicant_network_get_identity(network));
3542 connman_network_set_string(connman_network, "WiFi.Phase2",
3543 g_supplicant_network_get_phase2(network));
3548 wifi->network = connman_network;
3552 static void debug(const char *str)
3554 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3555 connman_debug("%s", str);
3558 static void disconnect_reasoncode(GSupplicantInterface *interface,
3561 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3564 wifi->disconnect_code = reasoncode;
3569 static const GSupplicantCallbacks callbacks = {
3570 .system_ready = system_ready,
3571 .system_killed = system_killed,
3572 .interface_added = interface_added,
3573 .interface_state = interface_state,
3574 .interface_removed = interface_removed,
3575 .p2p_support = p2p_support,
3576 .scan_started = scan_started,
3577 .scan_finished = scan_finished,
3578 .network_added = network_added,
3579 .network_removed = network_removed,
3580 .network_changed = network_changed,
3581 .add_station = add_station,
3582 .remove_station = remove_station,
3583 .peer_found = peer_found,
3584 .peer_lost = peer_lost,
3585 .peer_changed = peer_changed,
3586 .peer_request = peer_request,
3587 #if defined TIZEN_EXT
3588 .system_power_off = system_power_off,
3589 .network_merged = network_merged,
3591 .disconnect_reasoncode = disconnect_reasoncode,
3596 static int tech_probe(struct connman_technology *technology)
3598 wifi_technology = technology;
3603 static void tech_remove(struct connman_technology *technology)
3605 wifi_technology = NULL;
3608 struct wifi_tethering_info {
3609 struct wifi_data *wifi;
3610 struct connman_technology *technology;
3612 GSupplicantSSID *ssid;
3615 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3616 const char *passphrase, bool hidden)
3618 GSupplicantSSID *ap;
3620 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3624 ap->mode = G_SUPPLICANT_MODE_MASTER;
3626 ap->ssid_len = strlen(ssid);
3630 if (!passphrase || strlen(passphrase) == 0) {
3631 ap->security = G_SUPPLICANT_SECURITY_NONE;
3632 ap->passphrase = NULL;
3634 ap->security = G_SUPPLICANT_SECURITY_PSK;
3635 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3636 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3637 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3638 ap->passphrase = passphrase;
3642 ap->ignore_broadcast_ssid =
3643 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3645 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3650 static void ap_start_callback(int result, GSupplicantInterface *interface,
3653 struct wifi_tethering_info *info = user_data;
3655 DBG("result %d index %d bridge %s",
3656 result, info->wifi->index, info->wifi->bridge);
3659 connman_inet_remove_from_bridge(info->wifi->index,
3660 info->wifi->bridge);
3661 connman_technology_tethering_notify(info->technology, false);
3664 g_free(info->ifname);
3668 static void ap_create_callback(int result,
3669 GSupplicantInterface *interface,
3672 struct wifi_tethering_info *info = user_data;
3674 DBG("result %d ifname %s", result,
3675 g_supplicant_interface_get_ifname(interface));
3678 connman_inet_remove_from_bridge(info->wifi->index,
3679 info->wifi->bridge);
3680 connman_technology_tethering_notify(info->technology, false);
3682 g_free(info->ifname);
3688 info->wifi->interface = interface;
3689 g_supplicant_interface_set_data(interface, info->wifi);
3691 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3692 connman_error("Failed to set interface ap_scan property");
3694 g_supplicant_interface_connect(interface, info->ssid,
3695 ap_start_callback, info);
3698 static void sta_remove_callback(int result,
3699 GSupplicantInterface *interface,
3702 struct wifi_tethering_info *info = user_data;
3703 const char *driver = connman_option_get_string("wifi");
3705 DBG("ifname %s result %d ", info->ifname, result);
3708 info->wifi->tethering = true;
3710 g_free(info->ifname);
3716 info->wifi->interface = NULL;
3718 connman_technology_tethering_notify(info->technology, true);
3720 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3725 static int tech_set_tethering(struct connman_technology *technology,
3726 const char *identifier, const char *passphrase,
3727 const char *bridge, bool enabled, bool hidden)
3730 GSupplicantInterface *interface;
3731 struct wifi_data *wifi;
3732 struct wifi_tethering_info *info;
3740 for (list = iface_list; list; list = list->next) {
3743 if (wifi->tethering) {
3744 wifi->tethering = false;
3746 connman_inet_remove_from_bridge(wifi->index,
3748 wifi->bridged = false;
3752 connman_technology_tethering_notify(technology, false);
3757 for (list = iface_list; list; list = list->next) {
3760 interface = wifi->interface;
3765 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3767 mode = g_supplicant_interface_get_mode(interface);
3768 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3769 DBG("%s does not support AP mode", ifname);
3773 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3778 info->technology = technology;
3779 info->wifi->bridge = bridge;
3780 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3785 info->ifname = g_strdup(ifname);
3786 if (!info->ifname) {
3792 info->wifi->tethering = true;
3794 err = g_supplicant_interface_remove(interface,
3795 sta_remove_callback,
3804 static void regdom_callback(int result, const char *alpha2, void *user_data)
3808 if (!wifi_technology)
3814 connman_technology_regdom_notify(wifi_technology, alpha2);
3817 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3819 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3822 static struct connman_technology_driver tech_driver = {
3824 .type = CONNMAN_SERVICE_TYPE_WIFI,
3825 .probe = tech_probe,
3826 .remove = tech_remove,
3827 .set_tethering = tech_set_tethering,
3828 .set_regdom = tech_set_regdom,
3831 static int wifi_init(void)
3835 err = connman_network_driver_register(&network_driver);
3839 err = g_supplicant_register(&callbacks);
3841 connman_network_driver_unregister(&network_driver);
3845 err = connman_technology_driver_register(&tech_driver);
3847 g_supplicant_unregister(&callbacks);
3848 connman_network_driver_unregister(&network_driver);
3855 static void wifi_exit(void)
3859 connman_technology_driver_unregister(&tech_driver);
3861 g_supplicant_unregister(&callbacks);
3863 connman_network_driver_unregister(&network_driver);
3866 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3867 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)