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 scanning = connman_device_get_scanning(device);
1305 #if defined TIZEN_EXT
1306 if (scanning && wifi && !wifi->allow_full_scan)
1310 connman_device_set_scanning(device,
1311 CONNMAN_SERVICE_TYPE_WIFI, false);
1313 if (result != -ENOLINK)
1314 #if defined TIZEN_EXT
1317 start_autoscan(device);
1320 * If we are here then we were scanning; however, if we are
1321 * also mid-flight disabling the interface, then wifi_disable
1322 * has already cleared the device scanning state and
1323 * unreferenced the device, obviating the need to do it here.
1327 connman_device_unref(device);
1329 #if defined TIZEN_EXT
1330 if (wifi && wifi->allow_full_scan) {
1331 DBG("Trigger Full Channel Scan");
1332 throw_wifi_scan(device, scan_callback);
1333 wifi->allow_full_scan = FALSE;
1335 if (wifi && wifi->scan_pending_network && result != -EIO) {
1336 network_connect(wifi->scan_pending_network);
1337 wifi->scan_pending_network = NULL;
1338 connman_network_set_connecting(wifi->network);
1341 if (is_wifi_notifier_registered != true &&
1342 wifi_first_scan == true && found_with_first_scan == true) {
1343 wifi_first_scan = false;
1344 found_with_first_scan = false;
1346 connman_notifier_register(¬ifier);
1347 is_wifi_notifier_registered = true;
1352 static void scan_callback_hidden(int result,
1353 GSupplicantInterface *interface, void *user_data)
1355 struct connman_device *device = user_data;
1356 struct wifi_data *wifi = connman_device_get_data(device);
1357 GSupplicantScanParams *scan_params;
1360 DBG("result %d wifi %p", result, wifi);
1365 /* User is trying to connect to a hidden AP */
1366 if (wifi->hidden && wifi->postpone_hidden)
1369 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1373 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1374 ret = g_supplicant_interface_scan(wifi->interface,
1376 scan_callback_hidden,
1382 g_supplicant_free_scan_params(scan_params);
1385 scan_callback(result, interface, user_data);
1388 static gboolean autoscan_timeout(gpointer data)
1390 struct connman_device *device = data;
1391 struct wifi_data *wifi = connman_device_get_data(device);
1392 struct autoscan_params *autoscan;
1398 autoscan = wifi->autoscan;
1400 if (autoscan->interval <= 0) {
1401 interval = autoscan->base;
1404 interval = autoscan->interval * autoscan->base;
1406 #if defined TIZEN_EXT
1407 if (autoscan->interval >= autoscan->limit)
1409 if (interval > autoscan->limit)
1411 interval = autoscan->limit;
1413 throw_wifi_scan(wifi->device, scan_callback_hidden);
1416 DBG("interval %d", interval);
1418 autoscan->interval = interval;
1420 autoscan->timeout = g_timeout_add_seconds(interval,
1421 autoscan_timeout, device);
1426 static void start_autoscan(struct connman_device *device)
1428 struct wifi_data *wifi = connman_device_get_data(device);
1429 struct autoscan_params *autoscan;
1436 if (wifi->p2p_device)
1439 if (wifi->connected)
1442 autoscan = wifi->autoscan;
1446 if (autoscan->timeout > 0 || autoscan->interval > 0)
1449 connman_device_ref(device);
1451 autoscan_timeout(device);
1454 static struct autoscan_params *parse_autoscan_params(const char *params)
1456 struct autoscan_params *autoscan;
1461 DBG("Emulating autoscan");
1463 list_params = g_strsplit(params, ":", 0);
1464 if (list_params == 0)
1467 if (g_strv_length(list_params) < 3) {
1468 g_strfreev(list_params);
1472 base = atoi(list_params[1]);
1473 limit = atoi(list_params[2]);
1475 g_strfreev(list_params);
1477 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1479 DBG("Could not allocate memory for autoscan");
1483 DBG("base %d - limit %d", base, limit);
1484 autoscan->base = base;
1485 autoscan->limit = limit;
1490 static void setup_autoscan(struct wifi_data *wifi)
1492 if (!wifi->autoscan)
1493 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1495 start_autoscan(wifi->device);
1498 static void finalize_interface_creation(struct wifi_data *wifi)
1500 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1502 if (!wifi->device) {
1503 connman_error("WiFi device not set");
1507 connman_device_set_powered(wifi->device, true);
1509 if (!connman_setting_get_bool("BackgroundScanning"))
1512 if (wifi->p2p_device)
1515 setup_autoscan(wifi);
1518 static void interface_create_callback(int result,
1519 GSupplicantInterface *interface,
1522 struct wifi_data *wifi = user_data;
1524 DBG("result %d ifname %s, wifi %p", result,
1525 g_supplicant_interface_get_ifname(interface),
1528 if (result < 0 || !wifi)
1531 wifi->interface = interface;
1532 g_supplicant_interface_set_data(interface, wifi);
1534 if (g_supplicant_interface_get_ready(interface)) {
1535 wifi->interface_ready = true;
1536 finalize_interface_creation(wifi);
1540 static int wifi_enable(struct connman_device *device)
1542 struct wifi_data *wifi = connman_device_get_data(device);
1545 const char *driver = connman_option_get_string("wifi");
1548 DBG("device %p %p", device, wifi);
1550 index = connman_device_get_index(device);
1551 if (!wifi || index < 0)
1554 if (is_p2p_connecting())
1555 return -EINPROGRESS;
1557 interface = connman_inet_ifname(index);
1558 ret = g_supplicant_interface_create(interface, driver, NULL,
1559 interface_create_callback,
1566 return -EINPROGRESS;
1569 static int wifi_disable(struct connman_device *device)
1571 struct wifi_data *wifi = connman_device_get_data(device);
1574 DBG("device %p wifi %p", device, wifi);
1579 wifi->connected = false;
1580 wifi->disconnecting = false;
1582 if (wifi->pending_network)
1583 wifi->pending_network = NULL;
1585 stop_autoscan(device);
1587 if (wifi->p2p_find_timeout) {
1588 g_source_remove(wifi->p2p_find_timeout);
1589 wifi->p2p_find_timeout = 0;
1590 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1591 connman_device_unref(wifi->device);
1594 /* In case of a user scan, device is still referenced */
1595 if (connman_device_get_scanning(device)) {
1596 connman_device_set_scanning(device,
1597 CONNMAN_SERVICE_TYPE_WIFI, false);
1598 connman_device_unref(wifi->device);
1601 remove_networks(device, wifi);
1603 #if defined TIZEN_EXT
1604 wifi->scan_pending_network = NULL;
1606 if (is_wifi_notifier_registered == true) {
1607 connman_notifier_unregister(¬ifier);
1608 is_wifi_notifier_registered = false;
1612 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1616 return -EINPROGRESS;
1619 struct last_connected {
1625 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1627 GTimeVal *aval = (GTimeVal *)a;
1628 GTimeVal *bval = (GTimeVal *)b;
1630 /* Note that the sort order is descending */
1631 if (aval->tv_sec < bval->tv_sec)
1634 if (aval->tv_sec > bval->tv_sec)
1640 static void free_entry(gpointer data)
1642 struct last_connected *entry = data;
1644 g_free(entry->ssid);
1648 static int get_latest_connections(int max_ssids,
1649 GSupplicantScanParams *scan_data)
1651 GSequenceIter *iter;
1652 GSequence *latest_list;
1653 struct last_connected *entry;
1662 latest_list = g_sequence_new(free_entry);
1666 services = connman_storage_get_services();
1667 for (i = 0; services && services[i]; i++) {
1668 if (strncmp(services[i], "wifi_", 5) != 0)
1671 keyfile = connman_storage_load_service(services[i]);
1675 str = g_key_file_get_string(keyfile,
1676 services[i], "Favorite", NULL);
1677 if (!str || g_strcmp0(str, "true")) {
1679 g_key_file_free(keyfile);
1684 str = g_key_file_get_string(keyfile,
1685 services[i], "AutoConnect", NULL);
1686 if (!str || g_strcmp0(str, "true")) {
1688 g_key_file_free(keyfile);
1693 str = g_key_file_get_string(keyfile,
1694 services[i], "Modified", NULL);
1696 g_key_file_free(keyfile);
1699 g_time_val_from_iso8601(str, &modified);
1702 ssid = g_key_file_get_string(keyfile,
1703 services[i], "SSID", NULL);
1705 freq = g_key_file_get_integer(keyfile, services[i],
1708 entry = g_try_new(struct last_connected, 1);
1710 g_sequence_free(latest_list);
1711 g_key_file_free(keyfile);
1717 entry->modified = modified;
1720 g_sequence_insert_sorted(latest_list, entry,
1726 g_key_file_free(keyfile);
1729 g_strfreev(services);
1731 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1733 iter = g_sequence_get_begin_iter(latest_list);
1735 for (i = 0; i < num_ssids; i++) {
1736 entry = g_sequence_get(iter);
1738 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1739 entry->modified.tv_sec);
1741 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1742 max_ssids, entry->ssid);
1744 iter = g_sequence_iter_next(iter);
1747 g_sequence_free(latest_list);
1751 static int wifi_scan_simple(struct connman_device *device)
1753 reset_autoscan(device);
1755 return throw_wifi_scan(device, scan_callback_hidden);
1758 static gboolean p2p_find_stop(gpointer data)
1760 struct connman_device *device = data;
1761 struct wifi_data *wifi = connman_device_get_data(device);
1765 wifi->p2p_find_timeout = 0;
1767 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1769 g_supplicant_interface_p2p_stop_find(wifi->interface);
1771 connman_device_unref(device);
1772 reset_autoscan(device);
1777 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1780 struct connman_device *device = user_data;
1781 struct wifi_data *wifi = connman_device_get_data(device);
1783 DBG("result %d wifi %p", result, wifi);
1785 if (wifi->p2p_find_timeout) {
1786 g_source_remove(wifi->p2p_find_timeout);
1787 wifi->p2p_find_timeout = 0;
1793 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1794 p2p_find_stop, device);
1795 if (!wifi->p2p_find_timeout)
1800 p2p_find_stop(device);
1803 static int p2p_find(struct connman_device *device)
1805 struct wifi_data *wifi;
1810 if (!p2p_technology)
1813 wifi = connman_device_get_data(device);
1815 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1818 reset_autoscan(device);
1819 connman_device_ref(device);
1821 ret = g_supplicant_interface_p2p_find(wifi->interface,
1822 p2p_find_callback, device);
1824 connman_device_unref(device);
1825 start_autoscan(device);
1827 connman_device_set_scanning(device,
1828 CONNMAN_SERVICE_TYPE_P2P, true);
1834 #if defined TIZEN_EXT
1835 static void specific_scan_callback(int result, GSupplicantInterface *interface,
1838 struct connman_device *device = user_data;
1839 struct wifi_data *wifi = connman_device_get_data(device);
1842 DBG("result %d wifi %p", result, wifi);
1844 if (wifi && wifi->scan_params) {
1845 g_supplicant_free_scan_params(wifi->scan_params);
1846 wifi->scan_params = NULL;
1849 scanning = connman_device_get_scanning(device);
1851 connman_device_set_scanning(device,
1852 CONNMAN_SERVICE_TYPE_WIFI, false);
1853 connman_device_unref(device);
1857 static int wifi_specific_scan(enum connman_service_type type,
1858 struct connman_device *device, int scan_type,
1859 GSList *specific_scan_list, void *user_data)
1861 GSList *list = NULL;
1863 struct wifi_data *wifi = connman_device_get_data(device);
1864 GSupplicantScanParams *scan_params = NULL;
1865 struct scan_ssid *scan_ssid = NULL;
1874 if (wifi->p2p_device)
1877 if (type == CONNMAN_SERVICE_TYPE_P2P)
1878 return p2p_find(device);
1880 if (wifi->tethering)
1883 scanning = connman_device_get_scanning(device);
1887 DBG("scan_type: %d", scan_type);
1888 if (scan_type == 1) { /* ssid based scan */
1889 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1891 DBG("Failed to allocate memory.");
1895 for (list = specific_scan_list; list; list = list->next) {
1896 ssid = (char *)list->data;
1897 int ssid_len = strlen(ssid);
1899 scan_ssid = g_try_new0(struct scan_ssid, 1);
1901 DBG("Failed to allocate memory.");
1902 g_supplicant_free_scan_params(scan_params);
1906 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
1907 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
1908 scan_ssid->ssid_len = ssid_len;
1909 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
1912 scan_params->num_ssids = count;
1914 } else if (scan_type == 2) { /* frequency based scan */
1916 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1918 DBG("Failed to allocate memory.");
1922 guint num_freqs = g_slist_length(specific_scan_list);
1923 DBG("num_freqs: %d", num_freqs);
1925 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
1926 if (!scan_params->freqs) {
1927 DBG("Failed to allocate memory.");
1928 g_free(scan_params);
1933 for (list = specific_scan_list; list; list = list->next) {
1934 freq = (int)list->data;
1936 scan_params->freqs[count] = freq;
1937 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
1940 scan_params->num_freqs = count;
1943 DBG("Invalid scan");
1947 reset_autoscan(device);
1948 connman_device_ref(device);
1950 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1951 specific_scan_callback, device);
1954 connman_device_set_scanning(device,
1955 CONNMAN_SERVICE_TYPE_WIFI, true);
1957 g_supplicant_free_scan_params(scan_params);
1958 connman_device_unref(device);
1966 * Note that the hidden scan is only used when connecting to this specific
1967 * hidden AP first time. It is not used when system autoconnects to hidden AP.
1969 static int wifi_scan(enum connman_service_type type,
1970 struct connman_device *device,
1971 const char *ssid, unsigned int ssid_len,
1972 const char *identity, const char* passphrase,
1973 const char *security, void *user_data)
1975 struct wifi_data *wifi = connman_device_get_data(device);
1976 GSupplicantScanParams *scan_params = NULL;
1977 struct scan_ssid *scan_ssid;
1978 struct hidden_params *hidden;
1980 int driver_max_ssids = 0;
1987 if (wifi->p2p_device)
1990 if (type == CONNMAN_SERVICE_TYPE_P2P)
1991 return p2p_find(device);
1993 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
1995 if (wifi->tethering)
1998 scanning = connman_device_get_scanning(device);
2000 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2004 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2006 DBG("max ssids %d", driver_max_ssids);
2007 if (driver_max_ssids == 0)
2008 return wifi_scan_simple(device);
2012 if (scanning && wifi->hidden && wifi->postpone_hidden)
2018 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2023 scan_ssid = g_try_new(struct scan_ssid, 1);
2025 g_free(scan_params);
2029 memcpy(scan_ssid->ssid, ssid, ssid_len);
2030 scan_ssid->ssid_len = ssid_len;
2031 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2033 scan_params->num_ssids = 1;
2035 hidden = g_try_new0(struct hidden_params, 1);
2037 g_supplicant_free_scan_params(scan_params);
2042 hidden_free(wifi->hidden);
2043 wifi->hidden = NULL;
2046 memcpy(hidden->ssid, ssid, ssid_len);
2047 hidden->ssid_len = ssid_len;
2048 hidden->identity = g_strdup(identity);
2049 hidden->passphrase = g_strdup(passphrase);
2050 hidden->security = g_strdup(security);
2051 hidden->user_data = user_data;
2052 wifi->hidden = hidden;
2055 /* Let's keep this active scan for later,
2056 * when current scan will be over. */
2057 wifi->postpone_hidden = TRUE;
2058 hidden->scan_params = scan_params;
2062 } else if (wifi->connected) {
2063 g_supplicant_free_scan_params(scan_params);
2064 return wifi_scan_simple(device);
2066 ret = get_latest_connections(driver_max_ssids, scan_params);
2068 g_supplicant_free_scan_params(scan_params);
2069 return wifi_scan_simple(device);
2073 connman_device_ref(device);
2075 #if defined TIZEN_EXT
2076 /*To allow the Full Scan after ssid based scan, set the flag here
2077 It is required because Tizen does not use the ConnMan specific
2078 backgroung Scan feature.Tizen has added the BG Scan feature in net-config
2079 To sync with up ConnMan, we need to issue the Full Scan after SSID specific scan.*/
2080 wifi->allow_full_scan = TRUE;
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);
2091 g_supplicant_free_scan_params(scan_params);
2092 connman_device_unref(device);
2095 hidden_free(wifi->hidden);
2096 wifi->hidden = NULL;
2103 static void wifi_regdom_callback(int result,
2107 struct connman_device *device = user_data;
2109 connman_device_regdom_notify(device, result, alpha2);
2111 connman_device_unref(device);
2114 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2116 struct wifi_data *wifi = connman_device_get_data(device);
2122 connman_device_ref(device);
2124 ret = g_supplicant_interface_set_country(wifi->interface,
2125 wifi_regdom_callback,
2128 connman_device_unref(device);
2133 static struct connman_device_driver wifi_ng_driver = {
2135 .type = CONNMAN_DEVICE_TYPE_WIFI,
2136 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2137 .probe = wifi_probe,
2138 .remove = wifi_remove,
2139 .enable = wifi_enable,
2140 .disable = wifi_disable,
2142 .set_regdom = wifi_set_regdom,
2143 #if defined TIZEN_EXT
2144 .specific_scan = wifi_specific_scan,
2148 static void system_ready(void)
2152 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2153 connman_error("Failed to register WiFi driver");
2156 static void system_killed(void)
2160 connman_device_driver_unregister(&wifi_ng_driver);
2163 static int network_probe(struct connman_network *network)
2165 DBG("network %p", network);
2170 static void network_remove(struct connman_network *network)
2172 struct connman_device *device = connman_network_get_device(network);
2173 struct wifi_data *wifi;
2175 DBG("network %p", network);
2177 wifi = connman_device_get_data(device);
2181 if (wifi->network != network)
2184 wifi->network = NULL;
2186 #if defined TIZEN_EXT
2187 wifi->disconnecting = false;
2189 if (wifi->pending_network == network)
2190 wifi->pending_network = NULL;
2192 if (wifi->scan_pending_network == network)
2193 wifi->scan_pending_network = NULL;
2197 static void connect_callback(int result, GSupplicantInterface *interface,
2200 #if defined TIZEN_EXT
2202 struct wifi_data *wifi;
2204 struct connman_network *network = user_data;
2206 DBG("network %p result %d", network, result);
2208 #if defined TIZEN_EXT
2209 for (list = iface_list; list; list = list->next) {
2212 if (wifi && wifi->network == network)
2216 /* wifi_data may be invalid because wifi is already disabled */
2221 if (result == -ENOKEY) {
2222 connman_network_set_error(network,
2223 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2224 } else if (result < 0) {
2225 connman_network_set_error(network,
2226 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2229 connman_network_unref(network);
2232 static GSupplicantSecurity network_security(const char *security)
2234 if (g_str_equal(security, "none"))
2235 return G_SUPPLICANT_SECURITY_NONE;
2236 else if (g_str_equal(security, "wep"))
2237 return G_SUPPLICANT_SECURITY_WEP;
2238 else if (g_str_equal(security, "psk"))
2239 return G_SUPPLICANT_SECURITY_PSK;
2240 else if (g_str_equal(security, "wpa"))
2241 return G_SUPPLICANT_SECURITY_PSK;
2242 else if (g_str_equal(security, "rsn"))
2243 return G_SUPPLICANT_SECURITY_PSK;
2244 else if (g_str_equal(security, "ieee8021x"))
2245 return G_SUPPLICANT_SECURITY_IEEE8021X;
2246 #if defined TIZEN_EXT
2247 else if (g_str_equal(security, "ft_psk") == TRUE)
2248 return G_SUPPLICANT_SECURITY_FT_PSK;
2249 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2250 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2253 return G_SUPPLICANT_SECURITY_UNKNOWN;
2256 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2258 const char *security;
2260 memset(ssid, 0, sizeof(*ssid));
2261 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2262 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2264 ssid->scan_ssid = 1;
2265 security = connman_network_get_string(network, "WiFi.Security");
2266 ssid->security = network_security(security);
2267 ssid->passphrase = connman_network_get_string(network,
2270 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2273 * If our private key password is unset,
2274 * we use the supplied passphrase. That is needed
2275 * for PEAP where 2 passphrases (identity and client
2276 * cert may have to be provided.
2278 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2279 connman_network_set_string(network,
2280 "WiFi.PrivateKeyPassphrase",
2282 /* We must have an identity for both PEAP and TLS */
2283 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2285 /* Use agent provided identity as a fallback */
2286 if (!ssid->identity || strlen(ssid->identity) == 0)
2287 ssid->identity = connman_network_get_string(network,
2288 "WiFi.AgentIdentity");
2290 ssid->ca_cert_path = connman_network_get_string(network,
2292 ssid->client_cert_path = connman_network_get_string(network,
2293 "WiFi.ClientCertFile");
2294 ssid->private_key_path = connman_network_get_string(network,
2295 "WiFi.PrivateKeyFile");
2296 ssid->private_key_passphrase = connman_network_get_string(network,
2297 "WiFi.PrivateKeyPassphrase");
2298 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2300 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2301 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2303 #if defined TIZEN_EXT
2304 ssid->bssid = connman_network_get_bssid(network);
2306 #if defined TIZEN_EXT
2307 ssid->freq = connman_network_get_frequency(network);
2310 if (connman_setting_get_bool("BackgroundScanning"))
2311 ssid->bgscan = BGSCAN_DEFAULT;
2314 static int network_connect(struct connman_network *network)
2316 struct connman_device *device = connman_network_get_device(network);
2317 struct wifi_data *wifi;
2318 GSupplicantInterface *interface;
2319 GSupplicantSSID *ssid;
2321 DBG("network %p", network);
2326 wifi = connman_device_get_data(device);
2330 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2334 interface = wifi->interface;
2336 ssid_init(ssid, network);
2338 if (wifi->disconnecting) {
2339 wifi->pending_network = network;
2342 wifi->network = connman_network_ref(network);
2344 #if defined TIZEN_EXT
2345 wifi->scan_pending_network = NULL;
2348 return g_supplicant_interface_connect(interface, ssid,
2349 connect_callback, network);
2352 return -EINPROGRESS;
2355 static void disconnect_callback(int result, GSupplicantInterface *interface,
2358 #if defined TIZEN_EXT
2360 struct wifi_data *wifi;
2361 struct connman_network *network = user_data;
2363 DBG("network %p result %d", network, result);
2365 for (list = iface_list; list; list = list->next) {
2368 if (wifi->network == NULL && wifi->disconnecting == true)
2369 wifi->disconnecting = false;
2371 if (wifi->network == network)
2375 /* wifi_data may be invalid because wifi is already disabled */
2380 struct wifi_data *wifi = user_data;
2383 DBG("result %d supplicant interface %p wifi %p",
2384 result, interface, wifi);
2386 if (result == -ECONNABORTED) {
2387 DBG("wifi interface no longer available");
2391 if (wifi->network) {
2393 * if result < 0 supplican return an error because
2394 * the network is not current.
2395 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2396 * failed, call connman_network_set_connected to report
2397 * disconnect is completed.
2400 connman_network_set_connected(wifi->network, false);
2403 wifi->network = NULL;
2405 wifi->disconnecting = false;
2407 if (wifi->pending_network) {
2408 network_connect(wifi->pending_network);
2409 wifi->pending_network = NULL;
2412 start_autoscan(wifi->device);
2415 static int network_disconnect(struct connman_network *network)
2417 struct connman_device *device = connman_network_get_device(network);
2418 struct wifi_data *wifi;
2420 #if defined TIZEN_EXT
2421 struct connman_service *service;
2424 DBG("network %p", network);
2426 wifi = connman_device_get_data(device);
2427 if (!wifi || !wifi->interface)
2430 #if defined TIZEN_EXT
2431 if (connman_network_get_associating(network) == true) {
2432 connman_network_clear_associating(network);
2433 connman_network_set_bool(network, "WiFi.UseWPS", false);
2435 service = connman_service_lookup_from_network(network);
2437 if (service != NULL &&
2438 (__connman_service_is_connected_state(service,
2439 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2440 __connman_service_is_connected_state(service,
2441 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2442 (connman_service_get_favorite(service) == false))
2443 __connman_service_set_passphrase(service, NULL);
2446 if (wifi->pending_network == network)
2447 wifi->pending_network = NULL;
2449 if (wifi->scan_pending_network == network)
2450 wifi->scan_pending_network = NULL;
2453 connman_network_set_associating(network, false);
2455 if (wifi->disconnecting)
2458 wifi->disconnecting = true;
2460 #if defined TIZEN_EXT
2461 err = g_supplicant_interface_disconnect(wifi->interface,
2462 disconnect_callback, network);
2464 err = g_supplicant_interface_disconnect(wifi->interface,
2465 disconnect_callback, wifi);
2469 wifi->disconnecting = false;
2474 static struct connman_network_driver network_driver = {
2476 .type = CONNMAN_NETWORK_TYPE_WIFI,
2477 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2478 .probe = network_probe,
2479 .remove = network_remove,
2480 .connect = network_connect,
2481 .disconnect = network_disconnect,
2484 static void interface_added(GSupplicantInterface *interface)
2486 const char *ifname = g_supplicant_interface_get_ifname(interface);
2487 const char *driver = g_supplicant_interface_get_driver(interface);
2488 struct wifi_data *wifi;
2490 wifi = g_supplicant_interface_get_data(interface);
2492 wifi = get_pending_wifi_data(ifname);
2496 g_supplicant_interface_set_data(interface, wifi);
2497 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2498 wifi->p2p_device = true;
2501 DBG("ifname %s driver %s wifi %p tethering %d",
2502 ifname, driver, wifi, wifi->tethering);
2504 if (!wifi->device) {
2505 connman_error("WiFi device not set");
2509 connman_device_set_powered(wifi->device, true);
2512 static bool is_idle(struct wifi_data *wifi)
2514 DBG("state %d", wifi->state);
2516 switch (wifi->state) {
2517 case G_SUPPLICANT_STATE_UNKNOWN:
2518 case G_SUPPLICANT_STATE_DISABLED:
2519 case G_SUPPLICANT_STATE_DISCONNECTED:
2520 case G_SUPPLICANT_STATE_INACTIVE:
2521 case G_SUPPLICANT_STATE_SCANNING:
2524 case G_SUPPLICANT_STATE_AUTHENTICATING:
2525 case G_SUPPLICANT_STATE_ASSOCIATING:
2526 case G_SUPPLICANT_STATE_ASSOCIATED:
2527 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2528 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2529 case G_SUPPLICANT_STATE_COMPLETED:
2536 static bool is_idle_wps(GSupplicantInterface *interface,
2537 struct wifi_data *wifi)
2539 /* First, let's check if WPS processing did not went wrong */
2540 if (g_supplicant_interface_get_wps_state(interface) ==
2541 G_SUPPLICANT_WPS_STATE_FAIL)
2544 /* Unlike normal connection, being associated while processing wps
2545 * actually means that we are idling. */
2546 switch (wifi->state) {
2547 case G_SUPPLICANT_STATE_UNKNOWN:
2548 case G_SUPPLICANT_STATE_DISABLED:
2549 case G_SUPPLICANT_STATE_DISCONNECTED:
2550 case G_SUPPLICANT_STATE_INACTIVE:
2551 case G_SUPPLICANT_STATE_SCANNING:
2552 case G_SUPPLICANT_STATE_ASSOCIATED:
2554 case G_SUPPLICANT_STATE_AUTHENTICATING:
2555 case G_SUPPLICANT_STATE_ASSOCIATING:
2556 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2557 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2558 case G_SUPPLICANT_STATE_COMPLETED:
2565 static bool handle_wps_completion(GSupplicantInterface *interface,
2566 struct connman_network *network,
2567 struct connman_device *device,
2568 struct wifi_data *wifi)
2572 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2574 const unsigned char *ssid, *wps_ssid;
2575 unsigned int ssid_len, wps_ssid_len;
2576 const char *wps_key;
2578 /* Checking if we got associated with requested
2580 ssid = connman_network_get_blob(network, "WiFi.SSID",
2583 wps_ssid = g_supplicant_interface_get_wps_ssid(
2584 interface, &wps_ssid_len);
2586 if (!wps_ssid || wps_ssid_len != ssid_len ||
2587 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2588 connman_network_set_associating(network, false);
2589 #if defined TIZEN_EXT
2590 g_supplicant_interface_disconnect(wifi->interface,
2591 disconnect_callback, wifi->network);
2593 connman_network_set_bool(network, "WiFi.UseWPS", false);
2594 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2596 g_supplicant_interface_disconnect(wifi->interface,
2597 disconnect_callback, wifi);
2602 wps_key = g_supplicant_interface_get_wps_key(interface);
2603 connman_network_set_string(network, "WiFi.Passphrase",
2606 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2612 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2613 struct connman_network *network,
2614 struct wifi_data *wifi)
2616 #if defined TIZEN_EXT
2617 const char *security;
2618 struct connman_service *service;
2620 if (wifi->connected)
2623 security = connman_network_get_string(network, "WiFi.Security");
2625 if (g_str_equal(security, "ieee8021x") == true &&
2626 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2628 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2633 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2636 struct connman_service *service;
2638 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2641 if (wifi->connected)
2645 service = connman_service_lookup_from_network(network);
2651 if (connman_service_get_favorite(service)) {
2652 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2657 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2662 #if defined TIZEN_EXT
2663 static bool handle_wifi_assoc_retry(struct connman_network *network,
2664 struct wifi_data *wifi)
2666 const char *security;
2668 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2669 connman_network_get_connecting(network) != true) {
2670 wifi->assoc_retry_count = 0;
2674 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2675 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2676 wifi->assoc_retry_count = 0;
2680 security = connman_network_get_string(network, "WiFi.Security");
2681 if (g_str_equal(security, "ieee8021x") == true &&
2682 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2683 wifi->assoc_retry_count = 0;
2687 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2688 wifi->assoc_retry_count = 0;
2690 /* Honestly it's not an invalid-key error,
2691 * however QA team recommends that the invalid-key error
2692 * might be better to display for user experience.
2694 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2703 static void interface_state(GSupplicantInterface *interface)
2705 struct connman_network *network;
2706 struct connman_device *device;
2707 struct wifi_data *wifi;
2708 GSupplicantState state = g_supplicant_interface_get_state(interface);
2711 wifi = g_supplicant_interface_get_data(interface);
2713 DBG("wifi %p interface state %d", wifi, state);
2718 device = wifi->device;
2722 if (g_supplicant_interface_get_ready(interface) &&
2723 !wifi->interface_ready) {
2724 wifi->interface_ready = true;
2725 finalize_interface_creation(wifi);
2728 network = wifi->network;
2733 case G_SUPPLICANT_STATE_SCANNING:
2736 case G_SUPPLICANT_STATE_AUTHENTICATING:
2737 case G_SUPPLICANT_STATE_ASSOCIATING:
2738 #if defined TIZEN_EXT
2739 reset_autoscan(device);
2741 stop_autoscan(device);
2744 if (!wifi->connected)
2745 connman_network_set_associating(network, true);
2749 case G_SUPPLICANT_STATE_COMPLETED:
2750 #if defined TIZEN_EXT
2751 /* though it should be already reset: */
2752 reset_autoscan(device);
2754 wifi->assoc_retry_count = 0;
2756 wifi->scan_pending_network = NULL;
2758 /* should be cleared scanning flag */
2759 bool scanning = connman_device_get_scanning(device);
2761 connman_device_set_scanning(device,
2762 CONNMAN_SERVICE_TYPE_WIFI, false);
2763 connman_device_unref(device);
2766 /* though it should be already stopped: */
2767 stop_autoscan(device);
2770 if (!handle_wps_completion(interface, network, device, wifi))
2773 connman_network_set_connected(network, true);
2774 wifi->disconnect_code = 0;
2777 case G_SUPPLICANT_STATE_DISCONNECTED:
2779 * If we're in one of the idle modes, we have
2780 * not started association yet and thus setting
2781 * those ones to FALSE could cancel an association
2784 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2786 if (is_idle_wps(interface, wifi))
2792 /* If previous state was 4way-handshake, then
2793 * it's either: psk was incorrect and thus we retry
2794 * or if we reach the maximum retries we declare the
2796 if (handle_4way_handshake_failure(interface,
2800 /* See table 8-36 Reason codes in IEEE Std 802.11 */
2801 switch (wifi->disconnect_code) {
2802 case 1: /* Unspecified reason */
2803 /* Let's assume it's because we got blocked */
2805 case 6: /* Class 2 frame received from nonauthenticated STA */
2806 connman_network_set_error(network,
2807 CONNMAN_NETWORK_ERROR_BLOCKED);
2815 /* We disable the selected network, if not then
2816 * wpa_supplicant will loop retrying */
2817 if (g_supplicant_interface_enable_selected_network(interface,
2819 DBG("Could not disables selected network");
2821 #if defined TIZEN_EXT
2824 err = g_supplicant_interface_remove_network(wifi->interface);
2826 DBG("Failed to remove network(%d)", err);
2829 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2830 * Retry association until its retry count is expired */
2831 if (handle_wifi_assoc_retry(network, wifi) == true) {
2832 throw_wifi_scan(wifi->device, scan_callback);
2833 wifi->scan_pending_network = wifi->network;
2837 if(wifi->disconnect_code > 0){
2838 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
2839 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
2842 /* To avoid unnecessary repeated association in wpa_supplicant,
2843 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2844 if (wps != true && wifi->network && wifi->disconnecting == false) {
2845 wifi->disconnecting = true;
2846 err = g_supplicant_interface_disconnect(wifi->interface,
2847 disconnect_callback, wifi->network);
2849 wifi->disconnecting = false;
2851 connman_network_set_connected(network, false);
2852 connman_network_set_associating(network, false);
2854 start_autoscan(device);
2860 connman_network_set_connected(network, false);
2861 connman_network_set_associating(network, false);
2862 wifi->disconnecting = false;
2864 start_autoscan(device);
2868 case G_SUPPLICANT_STATE_INACTIVE:
2869 #if defined TIZEN_EXT
2870 if (handle_wps_completion(interface, network, device, wifi) == false)
2873 connman_network_set_associating(network, false);
2874 start_autoscan(device);
2878 case G_SUPPLICANT_STATE_UNKNOWN:
2879 case G_SUPPLICANT_STATE_DISABLED:
2880 case G_SUPPLICANT_STATE_ASSOCIATED:
2881 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2882 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2886 wifi->state = state;
2888 /* Saving wpa_s state policy:
2889 * If connected and if the state changes are roaming related:
2890 * --> We stay connected
2892 * --> We are connected
2894 * --> We are not connected
2897 #if defined TIZEN_EXT
2898 case G_SUPPLICANT_STATE_SCANNING:
2901 case G_SUPPLICANT_STATE_AUTHENTICATING:
2902 case G_SUPPLICANT_STATE_ASSOCIATING:
2903 case G_SUPPLICANT_STATE_ASSOCIATED:
2904 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2905 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2906 if (wifi->connected)
2907 connman_warn("Probably roaming right now!"
2908 " Staying connected...");
2910 wifi->connected = false;
2912 case G_SUPPLICANT_STATE_COMPLETED:
2913 wifi->connected = true;
2916 wifi->connected = false;
2923 static void interface_removed(GSupplicantInterface *interface)
2925 const char *ifname = g_supplicant_interface_get_ifname(interface);
2926 struct wifi_data *wifi;
2928 DBG("ifname %s", ifname);
2930 wifi = g_supplicant_interface_get_data(interface);
2933 wifi->interface = NULL;
2935 if (wifi && wifi->tethering)
2938 if (!wifi || !wifi->device) {
2939 DBG("wifi interface already removed");
2943 connman_device_set_powered(wifi->device, false);
2945 check_p2p_technology();
2948 static void set_device_type(const char *type, char dev_type[17])
2950 const char *oui = "0050F204";
2951 const char *category = "0100";
2952 const char *sub_category = "0000";
2954 if (!g_strcmp0(type, "handset")) {
2956 sub_category = "0500";
2957 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2958 sub_category = "0100";
2959 else if (!g_strcmp0(type, "server"))
2960 sub_category = "0200";
2961 else if (!g_strcmp0(type, "laptop"))
2962 sub_category = "0500";
2963 else if (!g_strcmp0(type, "desktop"))
2964 sub_category = "0600";
2965 else if (!g_strcmp0(type, "tablet"))
2966 sub_category = "0900";
2967 else if (!g_strcmp0(type, "watch"))
2970 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2973 static void p2p_support(GSupplicantInterface *interface)
2975 char dev_type[17] = {};
2976 const char *hostname;
2980 if (!g_supplicant_interface_has_p2p(interface))
2983 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2984 DBG("Could not register P2P technology driver");
2988 hostname = connman_utsname_get_hostname();
2990 hostname = "ConnMan";
2992 set_device_type(connman_machine_get_type(), dev_type);
2993 g_supplicant_interface_set_p2p_device_config(interface,
2994 hostname, dev_type);
2995 connman_peer_driver_register(&peer_driver);
2998 static void scan_started(GSupplicantInterface *interface)
3003 static void scan_finished(GSupplicantInterface *interface)
3005 #if defined TIZEN_EXT
3006 struct wifi_data *wifi;
3007 bool is_associating = false;
3008 static bool is_scanning = true;
3013 #if defined TIZEN_EXT
3014 wifi = g_supplicant_interface_get_data(interface);
3015 if (wifi && wifi->scan_pending_network) {
3016 network_connect(wifi->scan_pending_network);
3017 wifi->scan_pending_network = NULL;
3020 //service state - associating
3021 if(!wifi || !wifi->network)
3024 is_associating = connman_network_get_associating(wifi->network);
3025 if(is_associating && is_scanning){
3026 is_scanning = false;
3027 DBG("send scan for connecting");
3028 throw_wifi_scan(wifi->device, scan_callback);
3039 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3041 unsigned char strength;
3043 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3045 #if !defined TIZEN_EXT
3052 static void network_added(GSupplicantNetwork *supplicant_network)
3054 struct connman_network *network;
3055 GSupplicantInterface *interface;
3056 struct wifi_data *wifi;
3057 const char *name, *identifier, *security, *group, *mode;
3058 const unsigned char *ssid;
3059 unsigned int ssid_len;
3063 bool wps_advertizing;
3065 #if defined TIZEN_EXT
3066 const char *wifi_vsie;
3067 unsigned int wifi_vsie_len;
3070 mode = g_supplicant_network_get_mode(supplicant_network);
3071 identifier = g_supplicant_network_get_identifier(supplicant_network);
3073 DBG("%s", identifier);
3075 if (!g_strcmp0(mode, "adhoc"))
3078 interface = g_supplicant_network_get_interface(supplicant_network);
3079 wifi = g_supplicant_interface_get_data(interface);
3080 name = g_supplicant_network_get_name(supplicant_network);
3081 security = g_supplicant_network_get_security(supplicant_network);
3082 group = g_supplicant_network_get_identifier(supplicant_network);
3083 wps = g_supplicant_network_get_wps(supplicant_network);
3084 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3085 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3086 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3087 supplicant_network);
3092 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3094 #if defined TIZEN_EXT
3095 wifi_vsie = g_supplicant_network_get_wifi_vsie(supplicant_network, &wifi_vsie_len);
3097 network = connman_device_get_network(wifi->device, identifier);
3100 network = connman_network_create(identifier,
3101 CONNMAN_NETWORK_TYPE_WIFI);
3105 connman_network_set_index(network, wifi->index);
3107 if (connman_device_add_network(wifi->device, network) < 0) {
3108 connman_network_unref(network);
3112 wifi->networks = g_slist_prepend(wifi->networks, network);
3115 if (name && name[0] != '\0')
3116 connman_network_set_name(network, name);
3118 connman_network_set_blob(network, "WiFi.SSID",
3120 #if defined TIZEN_EXT
3121 if(wifi_vsie_len > 0 && wifi_vsie)
3122 connman_network_set_blob(network, "WiFi.Vsie",
3123 wifi_vsie, wifi_vsie_len);
3125 connman_network_set_string(network, "WiFi.Security", security);
3126 connman_network_set_strength(network,
3127 calculate_strength(supplicant_network));
3128 connman_network_set_bool(network, "WiFi.WPS", wps);
3131 /* Is AP advertizing for WPS association?
3132 * If so, we decide to use WPS by default */
3133 if (wps_ready && wps_pbc &&
3135 #if !defined TIZEN_EXT
3136 connman_network_set_bool(network, "WiFi.UseWPS", true);
3138 DBG("wps is activating by ap but ignore it.");
3143 connman_network_set_frequency(network,
3144 g_supplicant_network_get_frequency(supplicant_network));
3145 #if defined TIZEN_EXT
3146 connman_network_set_bssid(network,
3147 g_supplicant_network_get_bssid(supplicant_network));
3148 connman_network_set_maxrate(network,
3149 g_supplicant_network_get_maxrate(supplicant_network));
3150 connman_network_set_enc_mode(network,
3151 g_supplicant_network_get_enc_mode(supplicant_network));
3152 connman_network_set_rsn_mode(network,
3153 g_supplicant_network_get_rsn_mode(supplicant_network));
3154 connman_network_set_keymgmt(network,
3155 g_supplicant_network_get_keymgmt(supplicant_network));
3157 connman_network_set_available(network, true);
3158 connman_network_set_string(network, "WiFi.Mode", mode);
3160 #if defined TIZEN_EXT
3165 connman_network_set_group(network, group);
3167 #if defined TIZEN_EXT
3168 if (wifi_first_scan == true)
3169 found_with_first_scan = true;
3172 if (wifi->hidden && ssid) {
3173 #if defined TIZEN_EXT
3174 if (network_security(wifi->hidden->security) ==
3175 network_security(security) &&
3177 if (!g_strcmp0(wifi->hidden->security, security) &&
3179 wifi->hidden->ssid_len == ssid_len &&
3180 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3181 connman_network_connect_hidden(network,
3182 wifi->hidden->identity,
3183 wifi->hidden->passphrase,
3184 wifi->hidden->user_data);
3185 wifi->hidden->user_data = NULL;
3186 hidden_free(wifi->hidden);
3187 wifi->hidden = NULL;
3192 static void network_removed(GSupplicantNetwork *network)
3194 GSupplicantInterface *interface;
3195 struct wifi_data *wifi;
3196 const char *name, *identifier;
3197 struct connman_network *connman_network;
3199 interface = g_supplicant_network_get_interface(network);
3200 wifi = g_supplicant_interface_get_data(interface);
3201 identifier = g_supplicant_network_get_identifier(network);
3202 name = g_supplicant_network_get_name(network);
3204 DBG("name %s", name);
3209 connman_network = connman_device_get_network(wifi->device, identifier);
3210 if (!connman_network)
3213 #if defined TIZEN_EXT
3214 if (connman_network == wifi->scan_pending_network)
3215 wifi->scan_pending_network = NULL;
3217 if (connman_network == wifi->pending_network)
3218 wifi->pending_network = NULL;
3220 if(connman_network_get_connecting(connman_network) == true){
3221 connman_network_set_connected(connman_network, false);
3225 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3227 connman_device_remove_network(wifi->device, connman_network);
3228 connman_network_unref(connman_network);
3231 static void network_changed(GSupplicantNetwork *network, const char *property)
3233 GSupplicantInterface *interface;
3234 struct wifi_data *wifi;
3235 const char *name, *identifier;
3236 struct connman_network *connman_network;
3238 #if defined TIZEN_EXT
3239 const unsigned char *bssid;
3240 unsigned int maxrate;
3245 interface = g_supplicant_network_get_interface(network);
3246 wifi = g_supplicant_interface_get_data(interface);
3247 identifier = g_supplicant_network_get_identifier(network);
3248 name = g_supplicant_network_get_name(network);
3250 DBG("name %s", name);
3255 connman_network = connman_device_get_network(wifi->device, identifier);
3256 if (!connman_network)
3259 if (g_str_equal(property, "Signal")) {
3260 connman_network_set_strength(connman_network,
3261 calculate_strength(network));
3262 connman_network_update(connman_network);
3265 #if defined TIZEN_EXT
3266 bssid = g_supplicant_network_get_bssid(network);
3267 maxrate = g_supplicant_network_get_maxrate(network);
3268 frequency = g_supplicant_network_get_frequency(network);
3269 wps = g_supplicant_network_get_wps(network);
3271 connman_network_set_bssid(connman_network, bssid);
3272 connman_network_set_maxrate(connman_network, maxrate);
3273 connman_network_set_frequency(connman_network, frequency);
3274 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3278 static void apply_peer_services(GSupplicantPeer *peer,
3279 struct connman_peer *connman_peer)
3281 const unsigned char *data;
3286 connman_peer_reset_services(connman_peer);
3288 data = g_supplicant_peer_get_widi_ies(peer, &length);
3290 connman_peer_add_service(connman_peer,
3291 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3295 static void add_station(const char *mac)
3297 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3301 static void remove_station(const char *mac)
3303 connman_technology_tethering_remove_station(mac);
3306 static void peer_found(GSupplicantPeer *peer)
3308 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3309 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3310 struct connman_peer *connman_peer;
3311 const char *identifier, *name;
3314 identifier = g_supplicant_peer_get_identifier(peer);
3315 name = g_supplicant_peer_get_name(peer);
3317 DBG("ident: %s", identifier);
3319 connman_peer = connman_peer_get(wifi->device, identifier);
3323 connman_peer = connman_peer_create(identifier);
3324 connman_peer_set_name(connman_peer, name);
3325 connman_peer_set_device(connman_peer, wifi->device);
3326 apply_peer_services(peer, connman_peer);
3328 ret = connman_peer_register(connman_peer);
3329 if (ret < 0 && ret != -EALREADY)
3330 connman_peer_unref(connman_peer);
3333 static void peer_lost(GSupplicantPeer *peer)
3335 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3336 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3337 struct connman_peer *connman_peer;
3338 const char *identifier;
3343 identifier = g_supplicant_peer_get_identifier(peer);
3345 DBG("ident: %s", identifier);
3347 connman_peer = connman_peer_get(wifi->device, identifier);
3349 if (wifi->p2p_connecting &&
3350 wifi->pending_peer == connman_peer) {
3351 peer_connect_timeout(wifi);
3353 connman_peer_unregister(connman_peer);
3354 connman_peer_unref(connman_peer);
3358 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3360 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3361 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3362 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3363 struct connman_peer *connman_peer;
3364 const char *identifier;
3366 identifier = g_supplicant_peer_get_identifier(peer);
3368 DBG("ident: %s", identifier);
3370 connman_peer = connman_peer_get(wifi->device, identifier);
3375 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3376 apply_peer_services(peer, connman_peer);
3377 connman_peer_services_changed(connman_peer);
3379 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3380 if (!g_supplicant_peer_is_in_a_group(peer))
3381 p_state = CONNMAN_PEER_STATE_IDLE;
3383 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3385 case G_SUPPLICANT_PEER_GROUP_STARTED:
3387 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3388 p_state = CONNMAN_PEER_STATE_IDLE;
3390 case G_SUPPLICANT_PEER_GROUP_JOINED:
3391 connman_peer_set_iface_address(connman_peer,
3392 g_supplicant_peer_get_iface_address(peer));
3394 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3395 p_state = CONNMAN_PEER_STATE_IDLE;
3397 case G_SUPPLICANT_PEER_GROUP_FAILED:
3398 if (g_supplicant_peer_has_requested_connection(peer))
3399 p_state = CONNMAN_PEER_STATE_IDLE;
3401 p_state = CONNMAN_PEER_STATE_FAILURE;
3405 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3406 p_state == CONNMAN_PEER_STATE_FAILURE) {
3407 if (wifi->p2p_connecting
3408 && connman_peer == wifi->pending_peer)
3409 peer_cancel_timeout(wifi);
3411 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3414 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3417 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3418 GSupplicantInterface *g_iface;
3419 struct wifi_data *g_wifi;
3421 g_iface = g_supplicant_peer_get_group_interface(peer);
3425 g_wifi = g_supplicant_interface_get_data(g_iface);
3429 connman_peer_set_as_master(connman_peer,
3430 !g_supplicant_peer_is_client(peer));
3431 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3434 connman_peer_set_state(connman_peer, p_state);
3437 static void peer_request(GSupplicantPeer *peer)
3439 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3440 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3441 struct connman_peer *connman_peer;
3442 const char *identifier;
3444 identifier = g_supplicant_peer_get_identifier(peer);
3446 DBG("ident: %s", identifier);
3448 connman_peer = connman_peer_get(wifi->device, identifier);
3452 connman_peer_request_connection(connman_peer);
3455 #if defined TIZEN_EXT
3456 static void system_power_off(void)
3459 struct wifi_data *wifi;
3460 struct connman_service *service;
3461 struct connman_ipconfig *ipconfig_ipv4;
3463 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3464 for (list = iface_list; list; list = list->next) {
3467 if (wifi->network != NULL) {
3468 service = connman_service_lookup_from_network(wifi->network);
3469 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3470 __connman_dhcp_stop(ipconfig_ipv4);
3476 static void network_merged(GSupplicantNetwork *network)
3478 GSupplicantInterface *interface;
3479 GSupplicantState state;
3480 struct wifi_data *wifi;
3481 const char *identifier;
3482 struct connman_network *connman_network;
3483 unsigned int ishs20AP = 0;
3486 interface = g_supplicant_network_get_interface(network);
3490 state = g_supplicant_interface_get_state(interface);
3491 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3494 wifi = g_supplicant_interface_get_data(interface);
3498 identifier = g_supplicant_network_get_identifier(network);
3500 connman_network = connman_device_get_network(wifi->device, identifier);
3501 if (!connman_network)
3504 DBG("merged identifier %s", identifier);
3506 if (wifi->connected == FALSE) {
3508 case G_SUPPLICANT_STATE_AUTHENTICATING:
3509 case G_SUPPLICANT_STATE_ASSOCIATING:
3510 case G_SUPPLICANT_STATE_ASSOCIATED:
3511 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3512 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3513 connman_network_set_associating(connman_network, TRUE);
3515 case G_SUPPLICANT_STATE_COMPLETED:
3516 connman_network_set_connected(connman_network, TRUE);
3519 DBG("Not handled the state : %d", state);
3524 ishs20AP = g_supplicant_network_is_hs20AP(network);
3525 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3528 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3529 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3530 connman_network_set_string(connman_network, "WiFi.EAP",
3532 connman_network_set_string(connman_network, "WiFi.Identity",
3533 g_supplicant_network_get_identity(network));
3534 connman_network_set_string(connman_network, "WiFi.Phase2",
3535 g_supplicant_network_get_phase2(network));
3540 wifi->network = connman_network;
3544 static void debug(const char *str)
3546 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3547 connman_debug("%s", str);
3550 static void disconnect_reasoncode(GSupplicantInterface *interface,
3553 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3556 wifi->disconnect_code = reasoncode;
3561 static const GSupplicantCallbacks callbacks = {
3562 .system_ready = system_ready,
3563 .system_killed = system_killed,
3564 .interface_added = interface_added,
3565 .interface_state = interface_state,
3566 .interface_removed = interface_removed,
3567 .p2p_support = p2p_support,
3568 .scan_started = scan_started,
3569 .scan_finished = scan_finished,
3570 .network_added = network_added,
3571 .network_removed = network_removed,
3572 .network_changed = network_changed,
3573 .add_station = add_station,
3574 .remove_station = remove_station,
3575 .peer_found = peer_found,
3576 .peer_lost = peer_lost,
3577 .peer_changed = peer_changed,
3578 .peer_request = peer_request,
3579 #if defined TIZEN_EXT
3580 .system_power_off = system_power_off,
3581 .network_merged = network_merged,
3583 .disconnect_reasoncode = disconnect_reasoncode,
3588 static int tech_probe(struct connman_technology *technology)
3590 wifi_technology = technology;
3595 static void tech_remove(struct connman_technology *technology)
3597 wifi_technology = NULL;
3600 struct wifi_tethering_info {
3601 struct wifi_data *wifi;
3602 struct connman_technology *technology;
3604 GSupplicantSSID *ssid;
3607 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3608 const char *passphrase, bool hidden)
3610 GSupplicantSSID *ap;
3612 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3616 ap->mode = G_SUPPLICANT_MODE_MASTER;
3618 ap->ssid_len = strlen(ssid);
3622 if (!passphrase || strlen(passphrase) == 0) {
3623 ap->security = G_SUPPLICANT_SECURITY_NONE;
3624 ap->passphrase = NULL;
3626 ap->security = G_SUPPLICANT_SECURITY_PSK;
3627 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3628 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3629 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3630 ap->passphrase = passphrase;
3634 ap->ignore_broadcast_ssid =
3635 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3637 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3642 static void ap_start_callback(int result, GSupplicantInterface *interface,
3645 struct wifi_tethering_info *info = user_data;
3647 DBG("result %d index %d bridge %s",
3648 result, info->wifi->index, info->wifi->bridge);
3651 connman_inet_remove_from_bridge(info->wifi->index,
3652 info->wifi->bridge);
3653 connman_technology_tethering_notify(info->technology, false);
3656 g_free(info->ifname);
3660 static void ap_create_callback(int result,
3661 GSupplicantInterface *interface,
3664 struct wifi_tethering_info *info = user_data;
3666 DBG("result %d ifname %s", result,
3667 g_supplicant_interface_get_ifname(interface));
3670 connman_inet_remove_from_bridge(info->wifi->index,
3671 info->wifi->bridge);
3672 connman_technology_tethering_notify(info->technology, false);
3674 g_free(info->ifname);
3680 info->wifi->interface = interface;
3681 g_supplicant_interface_set_data(interface, info->wifi);
3683 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3684 connman_error("Failed to set interface ap_scan property");
3686 g_supplicant_interface_connect(interface, info->ssid,
3687 ap_start_callback, info);
3690 static void sta_remove_callback(int result,
3691 GSupplicantInterface *interface,
3694 struct wifi_tethering_info *info = user_data;
3695 const char *driver = connman_option_get_string("wifi");
3697 DBG("ifname %s result %d ", info->ifname, result);
3700 info->wifi->tethering = true;
3702 g_free(info->ifname);
3708 info->wifi->interface = NULL;
3710 connman_technology_tethering_notify(info->technology, true);
3712 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3717 static int tech_set_tethering(struct connman_technology *technology,
3718 const char *identifier, const char *passphrase,
3719 const char *bridge, bool enabled, bool hidden)
3722 GSupplicantInterface *interface;
3723 struct wifi_data *wifi;
3724 struct wifi_tethering_info *info;
3732 for (list = iface_list; list; list = list->next) {
3735 if (wifi->tethering) {
3736 wifi->tethering = false;
3738 connman_inet_remove_from_bridge(wifi->index,
3740 wifi->bridged = false;
3744 connman_technology_tethering_notify(technology, false);
3749 for (list = iface_list; list; list = list->next) {
3752 interface = wifi->interface;
3757 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3759 mode = g_supplicant_interface_get_mode(interface);
3760 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3761 DBG("%s does not support AP mode", ifname);
3765 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3770 info->technology = technology;
3771 info->wifi->bridge = bridge;
3772 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3777 info->ifname = g_strdup(ifname);
3778 if (!info->ifname) {
3784 info->wifi->tethering = true;
3786 err = g_supplicant_interface_remove(interface,
3787 sta_remove_callback,
3796 static void regdom_callback(int result, const char *alpha2, void *user_data)
3800 if (!wifi_technology)
3806 connman_technology_regdom_notify(wifi_technology, alpha2);
3809 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3811 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3814 static struct connman_technology_driver tech_driver = {
3816 .type = CONNMAN_SERVICE_TYPE_WIFI,
3817 .probe = tech_probe,
3818 .remove = tech_remove,
3819 .set_tethering = tech_set_tethering,
3820 .set_regdom = tech_set_regdom,
3823 static int wifi_init(void)
3827 err = connman_network_driver_register(&network_driver);
3831 err = g_supplicant_register(&callbacks);
3833 connman_network_driver_unregister(&network_driver);
3837 err = connman_technology_driver_register(&tech_driver);
3839 g_supplicant_unregister(&callbacks);
3840 connman_network_driver_unregister(&network_driver);
3847 static void wifi_exit(void)
3851 connman_technology_driver_unregister(&tech_driver);
3853 g_supplicant_unregister(&callbacks);
3855 connman_network_driver_unregister(&network_driver);
3858 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3859 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)