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
75 static struct connman_technology *wifi_technology = NULL;
76 static struct connman_technology *p2p_technology = NULL;
78 struct hidden_params {
80 unsigned int ssid_len;
84 GSupplicantScanParams *scan_params;
89 * Used for autoscan "emulation".
90 * Should be removed when wpa_s autoscan support will be by default.
92 struct autoscan_params {
101 struct connman_device *device;
102 struct connman_network *network;
103 struct connman_network *pending_network;
105 GSupplicantInterface *interface;
106 GSupplicantState state;
111 bool interface_ready;
117 struct hidden_params *hidden;
118 bool postpone_hidden;
120 * autoscan "emulation".
122 struct autoscan_params *autoscan;
124 GSupplicantScanParams *scan_params;
125 unsigned int p2p_find_timeout;
126 unsigned int p2p_connection_timeout;
127 struct connman_peer *pending_peer;
128 GSupplicantPeer *peer;
132 #if defined TIZEN_EXT
133 int assoc_retry_count;
134 struct connman_network *scan_pending_network;
135 bool allow_full_scan;
141 #if defined TIZEN_EXT
144 #define TIZEN_ASSOC_RETRY_COUNT 4
146 static gboolean wifi_first_scan = false;
147 static gboolean found_with_first_scan = false;
148 static gboolean is_wifi_notifier_registered = false;
152 static GList *iface_list = NULL;
154 static GList *pending_wifi_device = NULL;
155 static GList *p2p_iface_list = NULL;
156 bool wfd_service_registered = false;
158 static void start_autoscan(struct connman_device *device);
160 static int p2p_tech_probe(struct connman_technology *technology)
162 p2p_technology = technology;
167 static void p2p_tech_remove(struct connman_technology *technology)
169 p2p_technology = NULL;
172 static struct connman_technology_driver p2p_tech_driver = {
174 .type = CONNMAN_SERVICE_TYPE_P2P,
175 .probe = p2p_tech_probe,
176 .remove = p2p_tech_remove,
179 static bool is_p2p_connecting(void)
183 for (list = iface_list; list; list = list->next) {
184 struct wifi_data *wifi = list->data;
186 if (wifi->p2p_connecting)
193 static void add_pending_wifi_device(struct wifi_data *wifi)
195 if (g_list_find(pending_wifi_device, wifi))
198 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
201 static struct wifi_data *get_pending_wifi_data(const char *ifname)
205 for (list = pending_wifi_device; list; list = list->next) {
206 struct wifi_data *wifi;
207 const char *dev_name;
210 if (!wifi || !wifi->device)
213 dev_name = connman_device_get_string(wifi->device, "Interface");
214 if (!g_strcmp0(ifname, dev_name)) {
215 pending_wifi_device = g_list_delete_link(
216 pending_wifi_device, list);
224 static void remove_pending_wifi_device(struct wifi_data *wifi)
228 link = g_list_find(pending_wifi_device, wifi);
233 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
236 static void peer_cancel_timeout(struct wifi_data *wifi)
238 if (wifi->p2p_connection_timeout > 0)
239 g_source_remove(wifi->p2p_connection_timeout);
241 wifi->p2p_connection_timeout = 0;
242 wifi->p2p_connecting = false;
244 if (wifi->pending_peer) {
245 connman_peer_unref(wifi->pending_peer);
246 wifi->pending_peer = NULL;
252 static gboolean peer_connect_timeout(gpointer data)
254 struct wifi_data *wifi = data;
258 if (wifi->p2p_connecting) {
259 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
261 if (g_supplicant_peer_has_requested_connection(wifi->peer))
262 state = CONNMAN_PEER_STATE_IDLE;
264 connman_peer_set_state(wifi->pending_peer, state);
267 peer_cancel_timeout(wifi);
272 static void peer_connect_callback(int result, GSupplicantInterface *interface,
275 struct wifi_data *wifi = user_data;
276 struct connman_peer *peer = wifi->pending_peer;
278 DBG("peer %p - %d", peer, result);
284 peer_connect_timeout(wifi);
288 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
290 wifi->p2p_connection_timeout = g_timeout_add_seconds(
291 P2P_CONNECTION_TIMEOUT,
292 peer_connect_timeout, wifi);
295 static int peer_connect(struct connman_peer *peer,
296 enum connman_peer_wps_method wps_method,
299 struct connman_device *device = connman_peer_get_device(peer);
300 GSupplicantPeerParams *peer_params;
301 GSupplicantPeer *gs_peer;
302 struct wifi_data *wifi;
306 DBG("peer %p", peer);
311 wifi = connman_device_get_data(device);
315 if (wifi->p2p_connecting)
320 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
321 connman_peer_get_identifier(peer));
325 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
326 pin = g_supplicant_peer_is_wps_pin(gs_peer);
328 switch (wps_method) {
329 case CONNMAN_PEER_WPS_UNKNOWN:
330 if ((pbc && pin) || pin)
333 case CONNMAN_PEER_WPS_PBC:
338 case CONNMAN_PEER_WPS_PIN:
339 if (!pin || !wps_pin)
344 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
348 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
350 peer_params->wps_pin = g_strdup(wps_pin);
352 peer_params->master = connman_peer_service_is_master();
354 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
355 peer_connect_callback, wifi);
356 if (ret == -EINPROGRESS) {
357 wifi->pending_peer = connman_peer_ref(peer);
358 wifi->peer = gs_peer;
359 wifi->p2p_connecting = true;
366 static int peer_disconnect(struct connman_peer *peer)
368 struct connman_device *device = connman_peer_get_device(peer);
369 GSupplicantPeerParams peer_params = {};
370 GSupplicantPeer *gs_peer;
371 struct wifi_data *wifi;
374 DBG("peer %p", peer);
379 wifi = connman_device_get_data(device);
383 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
384 connman_peer_get_identifier(peer));
388 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
390 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
392 g_free(peer_params.path);
394 if (ret == -EINPROGRESS)
395 peer_cancel_timeout(wifi);
400 struct peer_service_registration {
401 peer_service_registration_cb_t callback;
405 static bool is_service_wfd(const unsigned char *specs, int length)
407 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
413 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
415 struct wifi_data *wifi = data;
417 if (!wifi->interface ||
418 !g_supplicant_interface_has_p2p(wifi->interface))
421 if (!wifi->servicing) {
422 g_supplicant_interface_p2p_listen(wifi->interface,
423 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
429 static void register_wfd_service_cb(int result,
430 GSupplicantInterface *iface, void *user_data)
432 struct peer_service_registration *reg_data = user_data;
437 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
439 if (reg_data && reg_data->callback) {
440 reg_data->callback(result, reg_data->user_data);
445 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
446 const unsigned char *spec,
447 int spec_length, const unsigned char *query,
448 int query_length, int version)
450 GSupplicantP2PServiceParams *params;
452 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
457 params->version = version;
458 params->service = g_memdup(spec, spec_length);
459 } else if (query_length > 0 && spec_length > 0) {
460 params->query = g_memdup(query, query_length);
461 params->query_length = query_length;
463 params->response = g_memdup(spec, spec_length);
464 params->response_length = spec_length;
466 params->wfd_ies = g_memdup(spec, spec_length);
467 params->wfd_ies_length = spec_length;
473 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
478 g_free(params->service);
479 g_free(params->query);
480 g_free(params->response);
481 g_free(params->wfd_ies);
486 static int peer_register_wfd_service(const unsigned char *specification,
487 int specification_length,
488 peer_service_registration_cb_t callback,
491 struct peer_service_registration *reg_data = NULL;
492 static GSupplicantP2PServiceParams *params;
497 if (wfd_service_registered)
500 params = fill_in_peer_service_params(specification,
501 specification_length, NULL, 0, 0);
505 reg_data = g_try_malloc0(sizeof(*reg_data));
511 reg_data->callback = callback;
512 reg_data->user_data = user_data;
514 ret = g_supplicant_set_widi_ies(params,
515 register_wfd_service_cb, reg_data);
516 if (ret < 0 && ret != -EINPROGRESS)
519 wfd_service_registered = true;
523 free_peer_service_params(params);
529 static void register_peer_service_cb(int result,
530 GSupplicantInterface *iface, void *user_data)
532 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
533 struct peer_service_registration *reg_data = user_data;
535 #if defined TIZEN_EXT
543 apply_p2p_listen_on_iface(wifi, NULL);
545 if (reg_data->callback)
546 reg_data->callback(result, reg_data->user_data);
551 static int peer_register_service(const unsigned char *specification,
552 int specification_length,
553 const unsigned char *query,
554 int query_length, int version,
555 peer_service_registration_cb_t callback,
558 struct peer_service_registration *reg_data;
559 GSupplicantP2PServiceParams *params;
566 if (specification && !version && !query &&
567 is_service_wfd(specification, specification_length)) {
568 return peer_register_wfd_service(specification,
569 specification_length, callback, user_data);
572 reg_data = g_try_malloc0(sizeof(*reg_data));
576 reg_data->callback = callback;
577 reg_data->user_data = user_data;
581 for (list = iface_list; list; list = list->next) {
582 struct wifi_data *wifi = list->data;
583 GSupplicantInterface *iface = wifi->interface;
585 if (!g_supplicant_interface_has_p2p(iface))
588 params = fill_in_peer_service_params(specification,
589 specification_length, query,
590 query_length, version);
597 ret_f = g_supplicant_interface_p2p_add_service(iface,
598 register_peer_service_cb, params, reg_data);
599 if (ret_f == 0 || ret_f == -EINPROGRESS)
603 ret = g_supplicant_interface_p2p_add_service(iface,
604 register_peer_service_cb, params, NULL);
605 if (ret != 0 && ret != -EINPROGRESS)
606 free_peer_service_params(params);
609 if (ret_f != 0 && ret_f != -EINPROGRESS)
615 static int peer_unregister_wfd_service(void)
617 GSupplicantP2PServiceParams *params;
620 if (!wfd_service_registered)
623 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
627 wfd_service_registered = false;
629 g_supplicant_set_widi_ies(params, NULL, NULL);
631 for (list = iface_list; list; list = list->next) {
632 struct wifi_data *wifi = list->data;
634 if (!g_supplicant_interface_has_p2p(wifi->interface))
638 if (!wifi->servicing || wifi->servicing < 0) {
639 g_supplicant_interface_p2p_listen(wifi->interface,
648 static int peer_unregister_service(const unsigned char *specification,
649 int specification_length,
650 const unsigned char *query,
651 int query_length, int version)
653 GSupplicantP2PServiceParams *params;
658 if (specification && !version && !query &&
659 is_service_wfd(specification, specification_length)) {
660 ret = peer_unregister_wfd_service();
661 if (ret != 0 && ret != -EINPROGRESS)
666 for (list = iface_list; list; list = list->next) {
667 struct wifi_data *wifi = list->data;
668 GSupplicantInterface *iface = wifi->interface;
673 if (!g_supplicant_interface_has_p2p(iface))
676 params = fill_in_peer_service_params(specification,
677 specification_length, query,
678 query_length, version);
684 ret = g_supplicant_interface_p2p_del_service(iface, params);
685 if (ret != 0 && ret != -EINPROGRESS)
686 free_peer_service_params(params);
689 if (!wifi->servicing || wifi->servicing < 0) {
690 g_supplicant_interface_p2p_listen(iface, 0, 0);
698 static struct connman_peer_driver peer_driver = {
699 .connect = peer_connect,
700 .disconnect = peer_disconnect,
701 .register_service = peer_register_service,
702 .unregister_service = peer_unregister_service,
705 static void handle_tethering(struct wifi_data *wifi)
707 if (!wifi->tethering)
716 DBG("index %d bridge %s", wifi->index, wifi->bridge);
718 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
721 wifi->bridged = true;
724 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
726 struct connman_device *device = user_data;
727 struct wifi_data *wifi = connman_device_get_data(device);
732 DBG("index %d flags %d change %d", wifi->index, flags, change);
734 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
738 DBG("interface down");
741 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
742 if (flags & IFF_LOWER_UP) {
745 handle_tethering(wifi);
753 static int wifi_probe(struct connman_device *device)
755 struct wifi_data *wifi;
757 DBG("device %p", device);
759 wifi = g_try_new0(struct wifi_data, 1);
763 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
765 connman_device_set_data(device, wifi);
766 wifi->device = connman_device_ref(device);
768 wifi->index = connman_device_get_index(device);
771 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
772 wifi_newlink, device);
773 if (is_p2p_connecting())
774 add_pending_wifi_device(wifi);
776 iface_list = g_list_append(iface_list, wifi);
781 static void remove_networks(struct connman_device *device,
782 struct wifi_data *wifi)
786 for (list = wifi->networks; list; list = list->next) {
787 struct connman_network *network = list->data;
789 connman_device_remove_network(device, network);
790 connman_network_unref(network);
793 g_slist_free(wifi->networks);
794 wifi->networks = NULL;
797 static void reset_autoscan(struct connman_device *device)
799 struct wifi_data *wifi = connman_device_get_data(device);
800 struct autoscan_params *autoscan;
804 if (!wifi || !wifi->autoscan)
807 autoscan = wifi->autoscan;
809 if (autoscan->timeout == 0 && autoscan->interval == 0)
812 g_source_remove(autoscan->timeout);
814 autoscan->timeout = 0;
815 autoscan->interval = 0;
817 connman_device_unref(device);
820 static void stop_autoscan(struct connman_device *device)
822 const struct wifi_data *wifi = connman_device_get_data(device);
824 if (!wifi || !wifi->autoscan)
827 reset_autoscan(device);
829 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
832 static void check_p2p_technology(void)
834 bool p2p_exists = false;
837 for (list = iface_list; list; list = list->next) {
838 struct wifi_data *w = list->data;
841 g_supplicant_interface_has_p2p(w->interface))
846 connman_technology_driver_unregister(&p2p_tech_driver);
847 connman_peer_driver_unregister(&peer_driver);
851 static void wifi_remove(struct connman_device *device)
853 struct wifi_data *wifi = connman_device_get_data(device);
855 DBG("device %p wifi %p", device, wifi);
860 stop_autoscan(device);
862 if (wifi->p2p_device)
863 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
865 iface_list = g_list_remove(iface_list, wifi);
867 check_p2p_technology();
869 remove_pending_wifi_device(wifi);
871 if (wifi->p2p_find_timeout) {
872 g_source_remove(wifi->p2p_find_timeout);
873 connman_device_unref(wifi->device);
876 if (wifi->p2p_connection_timeout)
877 g_source_remove(wifi->p2p_connection_timeout);
879 remove_networks(device, wifi);
881 connman_device_set_powered(device, false);
882 connman_device_set_data(device, NULL);
883 connman_device_unref(wifi->device);
884 connman_rtnl_remove_watch(wifi->watch);
886 g_supplicant_interface_set_data(wifi->interface, NULL);
888 g_supplicant_interface_cancel(wifi->interface);
890 if (wifi->scan_params)
891 g_supplicant_free_scan_params(wifi->scan_params);
893 g_free(wifi->autoscan);
894 g_free(wifi->identifier);
898 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
902 for (iter = list; iter; iter = g_slist_next(iter)) {
903 struct scan_ssid *scan_ssid = iter->data;
905 if (ssid_len == scan_ssid->ssid_len &&
906 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
913 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
914 int freq, GSupplicantScanParams *scan_data,
915 int driver_max_scan_ssids, char *ssid_name)
918 struct scan_ssid *scan_ssid;
920 if ((driver_max_scan_ssids == 0 ||
921 driver_max_scan_ssids > scan_data->num_ssids) &&
922 (hex_ssid || raw_ssid)) {
924 unsigned int j = 0, hex;
927 size_t hex_ssid_len = strlen(hex_ssid);
929 ssid = g_try_malloc0(hex_ssid_len / 2);
933 for (i = 0; i < hex_ssid_len; i += 2) {
934 sscanf(hex_ssid + i, "%02x", &hex);
943 * If we have already added hidden AP to the list,
944 * then do not do it again. This might happen if you have
945 * used or are using multiple wifi cards, so in that case
946 * you might have multiple service files for same AP.
948 if (is_duplicate(scan_data->ssids, ssid, j)) {
954 scan_ssid = g_try_new(struct scan_ssid, 1);
961 memcpy(scan_ssid->ssid, ssid, j);
962 scan_ssid->ssid_len = j;
963 scan_data->ssids = g_slist_prepend(scan_data->ssids,
966 scan_data->num_ssids++;
968 DBG("SSID %s added to scanned list of %d entries", ssid_name,
969 scan_data->num_ssids);
976 scan_data->ssids = g_slist_reverse(scan_data->ssids);
978 if (!scan_data->freqs) {
979 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
980 if (!scan_data->freqs) {
981 g_slist_free_full(scan_data->ssids, g_free);
985 scan_data->num_freqs = 1;
986 scan_data->freqs[0] = freq;
988 bool duplicate = false;
990 /* Don't add duplicate entries */
991 for (i = 0; i < scan_data->num_freqs; i++) {
992 if (scan_data->freqs[i] == freq) {
999 scan_data->num_freqs++;
1000 scan_data->freqs = g_try_realloc(scan_data->freqs,
1001 sizeof(uint16_t) * scan_data->num_freqs);
1002 if (!scan_data->freqs) {
1003 g_slist_free_full(scan_data->ssids, g_free);
1006 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1013 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1015 struct connman_config_entry **entries;
1021 int num_ssids = 0, add_param_failed = 0;
1023 services = connman_storage_get_services();
1024 for (i = 0; services && services[i]; i++) {
1025 if (strncmp(services[i], "wifi_", 5) != 0)
1028 keyfile = connman_storage_load_service(services[i]);
1032 value = g_key_file_get_boolean(keyfile,
1033 services[i], "Hidden", NULL);
1035 g_key_file_free(keyfile);
1039 value = g_key_file_get_boolean(keyfile,
1040 services[i], "Favorite", NULL);
1042 g_key_file_free(keyfile);
1046 #if defined TIZEN_EXT
1047 value = g_key_file_get_boolean(keyfile,
1048 services[i], "AutoConnect", NULL);
1050 g_key_file_free(keyfile);
1055 ssid = g_key_file_get_string(keyfile,
1056 services[i], "SSID", NULL);
1058 name = g_key_file_get_string(keyfile, services[i], "Name",
1061 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1069 g_key_file_free(keyfile);
1073 * Check if there are any hidden AP that needs to be provisioned.
1075 entries = connman_config_get_entries("wifi");
1076 for (i = 0; entries && entries[i]; i++) {
1079 if (!entries[i]->hidden)
1082 if (!entries[i]->ssid) {
1083 ssid = entries[i]->name;
1086 ssid = entries[i]->ssid;
1087 len = entries[i]->ssid_len;
1093 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1100 connman_config_free_entries(entries);
1102 if (add_param_failed > 0)
1103 DBG("Unable to scan %d out of %d SSIDs",
1104 add_param_failed, num_ssids);
1106 g_strfreev(services);
1111 static int get_hidden_connections_params(struct wifi_data *wifi,
1112 GSupplicantScanParams *scan_params)
1114 int driver_max_ssids, i;
1115 GSupplicantScanParams *orig_params;
1118 * Scan hidden networks so that we can autoconnect to them.
1119 * We will assume 1 as a default number of ssid to scan.
1121 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1123 if (driver_max_ssids == 0)
1124 driver_max_ssids = 1;
1126 DBG("max ssids %d", driver_max_ssids);
1128 if (!wifi->scan_params) {
1129 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1130 if (!wifi->scan_params)
1133 if (get_hidden_connections(wifi->scan_params) == 0) {
1134 g_supplicant_free_scan_params(wifi->scan_params);
1135 wifi->scan_params = NULL;
1141 orig_params = wifi->scan_params;
1143 /* Let's transfer driver_max_ssids params */
1144 for (i = 0; i < driver_max_ssids; i++) {
1145 struct scan_ssid *ssid;
1147 if (!wifi->scan_params->ssids)
1150 ssid = orig_params->ssids->data;
1151 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1152 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1156 scan_params->num_ssids = i;
1157 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1159 scan_params->freqs = g_memdup(orig_params->freqs,
1160 sizeof(uint16_t) * orig_params->num_freqs);
1161 if (!scan_params->freqs)
1164 scan_params->num_freqs = orig_params->num_freqs;
1169 orig_params->num_ssids -= scan_params->num_ssids;
1171 return scan_params->num_ssids;
1174 g_slist_free_full(scan_params->ssids, g_free);
1175 g_supplicant_free_scan_params(wifi->scan_params);
1176 wifi->scan_params = NULL;
1181 static int throw_wifi_scan(struct connman_device *device,
1182 GSupplicantInterfaceCallback callback)
1184 struct wifi_data *wifi = connman_device_get_data(device);
1190 DBG("device %p %p", device, wifi->interface);
1192 if (wifi->tethering)
1194 #if defined TIZEN_EXT
1195 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1197 if (connman_device_get_scanning(device))
1201 connman_device_ref(device);
1203 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1206 connman_device_set_scanning(device,
1207 CONNMAN_SERVICE_TYPE_WIFI, true);
1209 connman_device_unref(device);
1214 static void hidden_free(struct hidden_params *hidden)
1219 if (hidden->scan_params)
1220 g_supplicant_free_scan_params(hidden->scan_params);
1221 g_free(hidden->identity);
1222 g_free(hidden->passphrase);
1223 g_free(hidden->security);
1227 #if defined TIZEN_EXT
1228 static void service_state_changed(struct connman_service *service,
1229 enum connman_service_state state);
1231 static int network_connect(struct connman_network *network);
1233 static struct connman_notifier notifier = {
1235 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1236 .service_state_changed = service_state_changed,
1239 static void service_state_changed(struct connman_service *service,
1240 enum connman_service_state state)
1242 enum connman_service_type type;
1244 type = connman_service_get_type(service);
1245 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1248 DBG("service %p state %d", service, state);
1251 case CONNMAN_SERVICE_STATE_READY:
1252 case CONNMAN_SERVICE_STATE_ONLINE:
1253 case CONNMAN_SERVICE_STATE_FAILURE:
1254 connman_notifier_unregister(¬ifier);
1255 is_wifi_notifier_registered = FALSE;
1257 __connman_device_request_scan(type);
1266 static void scan_callback(int result, GSupplicantInterface *interface,
1269 struct connman_device *device = user_data;
1270 struct wifi_data *wifi = connman_device_get_data(device);
1273 DBG("result %d wifi %p", result, wifi);
1276 if (wifi->hidden && !wifi->postpone_hidden) {
1277 connman_network_clear_hidden(wifi->hidden->user_data);
1278 hidden_free(wifi->hidden);
1279 wifi->hidden = NULL;
1282 if (wifi->scan_params) {
1283 g_supplicant_free_scan_params(wifi->scan_params);
1284 wifi->scan_params = NULL;
1289 connman_device_reset_scanning(device);
1291 /* User is connecting to a hidden AP, let's wait for finished event */
1292 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1293 GSupplicantScanParams *scan_params;
1296 wifi->postpone_hidden = false;
1297 scan_params = wifi->hidden->scan_params;
1298 wifi->hidden->scan_params = NULL;
1300 reset_autoscan(device);
1302 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1303 scan_callback, device);
1307 /* On error, let's recall scan_callback, which will cleanup */
1308 return scan_callback(ret, interface, user_data);
1311 #if defined TIZEN_EXT
1312 if (wifi && wifi->allow_full_scan) {
1314 DBG("Trigger Full Channel Scan");
1315 wifi->allow_full_scan = FALSE;
1317 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1318 scan_callback, device);
1322 /* On error, let's recall scan_callback, which will cleanup */
1323 return scan_callback(ret, interface, user_data);
1327 scanning = connman_device_get_scanning(device);
1329 connman_device_set_scanning(device,
1330 CONNMAN_SERVICE_TYPE_WIFI, false);
1332 if (result != -ENOLINK)
1333 #if defined TIZEN_EXT
1336 start_autoscan(device);
1339 * If we are here then we were scanning; however, if we are
1340 * also mid-flight disabling the interface, then wifi_disable
1341 * has already cleared the device scanning state and
1342 * unreferenced the device, obviating the need to do it here.
1346 connman_device_unref(device);
1348 #if defined TIZEN_EXT
1349 if (wifi && wifi->scan_pending_network && result != -EIO) {
1350 network_connect(wifi->scan_pending_network);
1351 wifi->scan_pending_network = NULL;
1352 connman_network_set_connecting(wifi->network);
1355 if (is_wifi_notifier_registered != true &&
1356 wifi_first_scan == true && found_with_first_scan == true) {
1357 wifi_first_scan = false;
1358 found_with_first_scan = false;
1360 connman_notifier_register(¬ifier);
1361 is_wifi_notifier_registered = true;
1366 static void scan_callback_hidden(int result,
1367 GSupplicantInterface *interface, void *user_data)
1369 struct connman_device *device = user_data;
1370 struct wifi_data *wifi = connman_device_get_data(device);
1371 GSupplicantScanParams *scan_params;
1374 DBG("result %d wifi %p", result, wifi);
1379 /* User is trying to connect to a hidden AP */
1380 if (wifi->hidden && wifi->postpone_hidden)
1383 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1387 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1388 ret = g_supplicant_interface_scan(wifi->interface,
1390 scan_callback_hidden,
1396 g_supplicant_free_scan_params(scan_params);
1399 scan_callback(result, interface, user_data);
1402 static gboolean autoscan_timeout(gpointer data)
1404 struct connman_device *device = data;
1405 struct wifi_data *wifi = connman_device_get_data(device);
1406 struct autoscan_params *autoscan;
1412 autoscan = wifi->autoscan;
1414 if (autoscan->interval <= 0) {
1415 interval = autoscan->base;
1418 interval = autoscan->interval * autoscan->base;
1420 #if defined TIZEN_EXT
1421 if (autoscan->interval >= autoscan->limit)
1423 if (interval > autoscan->limit)
1425 interval = autoscan->limit;
1427 throw_wifi_scan(wifi->device, scan_callback_hidden);
1430 DBG("interval %d", interval);
1432 autoscan->interval = interval;
1434 autoscan->timeout = g_timeout_add_seconds(interval,
1435 autoscan_timeout, device);
1440 static void start_autoscan(struct connman_device *device)
1442 struct wifi_data *wifi = connman_device_get_data(device);
1443 struct autoscan_params *autoscan;
1450 if (wifi->p2p_device)
1453 if (wifi->connected)
1456 autoscan = wifi->autoscan;
1460 if (autoscan->timeout > 0 || autoscan->interval > 0)
1463 connman_device_ref(device);
1465 autoscan_timeout(device);
1468 static struct autoscan_params *parse_autoscan_params(const char *params)
1470 struct autoscan_params *autoscan;
1475 DBG("Emulating autoscan");
1477 list_params = g_strsplit(params, ":", 0);
1478 if (list_params == 0)
1481 if (g_strv_length(list_params) < 3) {
1482 g_strfreev(list_params);
1486 base = atoi(list_params[1]);
1487 limit = atoi(list_params[2]);
1489 g_strfreev(list_params);
1491 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1493 DBG("Could not allocate memory for autoscan");
1497 DBG("base %d - limit %d", base, limit);
1498 autoscan->base = base;
1499 autoscan->limit = limit;
1504 static void setup_autoscan(struct wifi_data *wifi)
1506 if (!wifi->autoscan)
1507 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1509 start_autoscan(wifi->device);
1512 static void finalize_interface_creation(struct wifi_data *wifi)
1514 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1516 if (!wifi->device) {
1517 connman_error("WiFi device not set");
1521 connman_device_set_powered(wifi->device, true);
1523 if (!connman_setting_get_bool("BackgroundScanning"))
1526 if (wifi->p2p_device)
1529 setup_autoscan(wifi);
1532 static void interface_create_callback(int result,
1533 GSupplicantInterface *interface,
1536 struct wifi_data *wifi = user_data;
1538 DBG("result %d ifname %s, wifi %p", result,
1539 g_supplicant_interface_get_ifname(interface),
1542 if (result < 0 || !wifi)
1545 wifi->interface = interface;
1546 g_supplicant_interface_set_data(interface, wifi);
1548 if (g_supplicant_interface_get_ready(interface)) {
1549 wifi->interface_ready = true;
1550 finalize_interface_creation(wifi);
1554 static int wifi_enable(struct connman_device *device)
1556 struct wifi_data *wifi = connman_device_get_data(device);
1559 const char *driver = connman_option_get_string("wifi");
1562 DBG("device %p %p", device, wifi);
1564 index = connman_device_get_index(device);
1565 if (!wifi || index < 0)
1568 if (is_p2p_connecting())
1569 return -EINPROGRESS;
1571 interface = connman_inet_ifname(index);
1572 ret = g_supplicant_interface_create(interface, driver, NULL,
1573 interface_create_callback,
1580 return -EINPROGRESS;
1583 static int wifi_disable(struct connman_device *device)
1585 struct wifi_data *wifi = connman_device_get_data(device);
1588 DBG("device %p wifi %p", device, wifi);
1593 wifi->connected = false;
1594 wifi->disconnecting = false;
1596 if (wifi->pending_network)
1597 wifi->pending_network = NULL;
1599 stop_autoscan(device);
1601 if (wifi->p2p_find_timeout) {
1602 g_source_remove(wifi->p2p_find_timeout);
1603 wifi->p2p_find_timeout = 0;
1604 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1605 connman_device_unref(wifi->device);
1608 /* In case of a user scan, device is still referenced */
1609 if (connman_device_get_scanning(device)) {
1610 connman_device_set_scanning(device,
1611 CONNMAN_SERVICE_TYPE_WIFI, false);
1612 connman_device_unref(wifi->device);
1615 remove_networks(device, wifi);
1617 #if defined TIZEN_EXT
1618 wifi->scan_pending_network = NULL;
1620 if (is_wifi_notifier_registered == true) {
1621 connman_notifier_unregister(¬ifier);
1622 is_wifi_notifier_registered = false;
1626 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1630 return -EINPROGRESS;
1633 struct last_connected {
1639 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1641 GTimeVal *aval = (GTimeVal *)a;
1642 GTimeVal *bval = (GTimeVal *)b;
1644 /* Note that the sort order is descending */
1645 if (aval->tv_sec < bval->tv_sec)
1648 if (aval->tv_sec > bval->tv_sec)
1654 static void free_entry(gpointer data)
1656 struct last_connected *entry = data;
1658 g_free(entry->ssid);
1662 static int get_latest_connections(int max_ssids,
1663 GSupplicantScanParams *scan_data)
1665 GSequenceIter *iter;
1666 GSequence *latest_list;
1667 struct last_connected *entry;
1676 latest_list = g_sequence_new(free_entry);
1680 services = connman_storage_get_services();
1681 for (i = 0; services && services[i]; i++) {
1682 if (strncmp(services[i], "wifi_", 5) != 0)
1685 keyfile = connman_storage_load_service(services[i]);
1689 str = g_key_file_get_string(keyfile,
1690 services[i], "Favorite", NULL);
1691 if (!str || g_strcmp0(str, "true")) {
1693 g_key_file_free(keyfile);
1698 str = g_key_file_get_string(keyfile,
1699 services[i], "AutoConnect", NULL);
1700 if (!str || g_strcmp0(str, "true")) {
1702 g_key_file_free(keyfile);
1707 str = g_key_file_get_string(keyfile,
1708 services[i], "Modified", NULL);
1710 g_key_file_free(keyfile);
1713 g_time_val_from_iso8601(str, &modified);
1716 ssid = g_key_file_get_string(keyfile,
1717 services[i], "SSID", NULL);
1719 freq = g_key_file_get_integer(keyfile, services[i],
1722 entry = g_try_new(struct last_connected, 1);
1724 g_sequence_free(latest_list);
1725 g_key_file_free(keyfile);
1731 entry->modified = modified;
1734 g_sequence_insert_sorted(latest_list, entry,
1740 g_key_file_free(keyfile);
1743 g_strfreev(services);
1745 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1747 iter = g_sequence_get_begin_iter(latest_list);
1749 for (i = 0; i < num_ssids; i++) {
1750 entry = g_sequence_get(iter);
1752 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1753 entry->modified.tv_sec);
1755 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1756 max_ssids, entry->ssid);
1758 iter = g_sequence_iter_next(iter);
1761 g_sequence_free(latest_list);
1765 static int wifi_scan_simple(struct connman_device *device)
1767 reset_autoscan(device);
1769 return throw_wifi_scan(device, scan_callback_hidden);
1772 static gboolean p2p_find_stop(gpointer data)
1774 struct connman_device *device = data;
1775 struct wifi_data *wifi = connman_device_get_data(device);
1779 wifi->p2p_find_timeout = 0;
1781 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1783 g_supplicant_interface_p2p_stop_find(wifi->interface);
1785 connman_device_unref(device);
1786 reset_autoscan(device);
1791 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1794 struct connman_device *device = user_data;
1795 struct wifi_data *wifi = connman_device_get_data(device);
1797 DBG("result %d wifi %p", result, wifi);
1799 if (wifi->p2p_find_timeout) {
1800 g_source_remove(wifi->p2p_find_timeout);
1801 wifi->p2p_find_timeout = 0;
1807 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1808 p2p_find_stop, device);
1809 if (!wifi->p2p_find_timeout)
1814 p2p_find_stop(device);
1817 static int p2p_find(struct connman_device *device)
1819 struct wifi_data *wifi;
1824 if (!p2p_technology)
1827 wifi = connman_device_get_data(device);
1829 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1832 reset_autoscan(device);
1833 connman_device_ref(device);
1835 ret = g_supplicant_interface_p2p_find(wifi->interface,
1836 p2p_find_callback, device);
1838 connman_device_unref(device);
1839 start_autoscan(device);
1841 connman_device_set_scanning(device,
1842 CONNMAN_SERVICE_TYPE_P2P, true);
1848 #if defined TIZEN_EXT
1849 static void specific_scan_callback(int result, GSupplicantInterface *interface,
1852 struct connman_device *device = user_data;
1853 struct wifi_data *wifi = connman_device_get_data(device);
1856 DBG("result %d wifi %p", result, wifi);
1858 if (wifi && wifi->scan_params) {
1859 g_supplicant_free_scan_params(wifi->scan_params);
1860 wifi->scan_params = NULL;
1863 scanning = connman_device_get_scanning(device);
1865 connman_device_set_scanning(device,
1866 CONNMAN_SERVICE_TYPE_WIFI, false);
1867 connman_device_unref(device);
1871 static int wifi_specific_scan(enum connman_service_type type,
1872 struct connman_device *device, int scan_type,
1873 GSList *specific_scan_list, void *user_data)
1875 GSList *list = NULL;
1877 struct wifi_data *wifi = connman_device_get_data(device);
1878 GSupplicantScanParams *scan_params = NULL;
1879 struct scan_ssid *scan_ssid = NULL;
1888 if (wifi->p2p_device)
1891 if (type == CONNMAN_SERVICE_TYPE_P2P)
1892 return p2p_find(device);
1894 if (wifi->tethering)
1897 scanning = connman_device_get_scanning(device);
1901 DBG("scan_type: %d", scan_type);
1902 if (scan_type == 1) { /* ssid based scan */
1903 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1905 DBG("Failed to allocate memory.");
1909 for (list = specific_scan_list; list; list = list->next) {
1910 ssid = (char *)list->data;
1911 int ssid_len = strlen(ssid);
1913 scan_ssid = g_try_new0(struct scan_ssid, 1);
1915 DBG("Failed to allocate memory.");
1916 g_supplicant_free_scan_params(scan_params);
1920 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
1921 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
1922 scan_ssid->ssid_len = ssid_len;
1923 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
1926 scan_params->num_ssids = count;
1928 } else if (scan_type == 2) { /* frequency based scan */
1930 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1932 DBG("Failed to allocate memory.");
1936 guint num_freqs = g_slist_length(specific_scan_list);
1937 DBG("num_freqs: %d", num_freqs);
1939 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
1940 if (!scan_params->freqs) {
1941 DBG("Failed to allocate memory.");
1942 g_free(scan_params);
1947 for (list = specific_scan_list; list; list = list->next) {
1948 freq = (int)list->data;
1950 scan_params->freqs[count] = freq;
1951 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
1954 scan_params->num_freqs = count;
1957 DBG("Invalid scan");
1961 reset_autoscan(device);
1962 connman_device_ref(device);
1964 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1965 specific_scan_callback, device);
1968 connman_device_set_scanning(device,
1969 CONNMAN_SERVICE_TYPE_WIFI, true);
1971 g_supplicant_free_scan_params(scan_params);
1972 connman_device_unref(device);
1980 * Note that the hidden scan is only used when connecting to this specific
1981 * hidden AP first time. It is not used when system autoconnects to hidden AP.
1983 static int wifi_scan(enum connman_service_type type,
1984 struct connman_device *device,
1985 const char *ssid, unsigned int ssid_len,
1986 const char *identity, const char* passphrase,
1987 const char *security, void *user_data)
1989 struct wifi_data *wifi = connman_device_get_data(device);
1990 GSupplicantScanParams *scan_params = NULL;
1991 struct scan_ssid *scan_ssid;
1992 struct hidden_params *hidden;
1994 int driver_max_ssids = 0;
2001 if (wifi->p2p_device)
2004 if (type == CONNMAN_SERVICE_TYPE_P2P)
2005 return p2p_find(device);
2007 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2009 if (wifi->tethering)
2012 scanning = connman_device_get_scanning(device);
2014 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2018 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2020 DBG("max ssids %d", driver_max_ssids);
2021 if (driver_max_ssids == 0)
2022 return wifi_scan_simple(device);
2026 if (scanning && wifi->hidden && wifi->postpone_hidden)
2032 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2037 scan_ssid = g_try_new(struct scan_ssid, 1);
2039 g_free(scan_params);
2043 memcpy(scan_ssid->ssid, ssid, ssid_len);
2044 scan_ssid->ssid_len = ssid_len;
2045 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2047 scan_params->num_ssids = 1;
2049 hidden = g_try_new0(struct hidden_params, 1);
2051 g_supplicant_free_scan_params(scan_params);
2056 hidden_free(wifi->hidden);
2057 wifi->hidden = NULL;
2060 memcpy(hidden->ssid, ssid, ssid_len);
2061 hidden->ssid_len = ssid_len;
2062 hidden->identity = g_strdup(identity);
2063 hidden->passphrase = g_strdup(passphrase);
2064 hidden->security = g_strdup(security);
2065 hidden->user_data = user_data;
2066 wifi->hidden = hidden;
2069 /* Let's keep this active scan for later,
2070 * when current scan will be over. */
2071 wifi->postpone_hidden = TRUE;
2072 hidden->scan_params = scan_params;
2076 } else if (wifi->connected) {
2077 g_supplicant_free_scan_params(scan_params);
2078 return wifi_scan_simple(device);
2080 ret = get_latest_connections(driver_max_ssids, scan_params);
2082 g_supplicant_free_scan_params(scan_params);
2083 return wifi_scan_simple(device);
2087 connman_device_ref(device);
2089 reset_autoscan(device);
2091 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2092 scan_callback, device);
2095 connman_device_set_scanning(device,
2096 CONNMAN_SERVICE_TYPE_WIFI, true);
2097 #if defined TIZEN_EXT
2098 /*To allow the Full Scan after ssid based scan, set the flag here
2099 It is required because Tizen does not use the ConnMan specific
2100 backgroung Scan feature.Tizen has added the BG Scan feature in
2101 net-config. To sync with up ConnMan, we need to issue the Full Scan
2102 after SSID specific scan.*/
2103 wifi->allow_full_scan = TRUE;
2106 g_supplicant_free_scan_params(scan_params);
2107 connman_device_unref(device);
2110 hidden_free(wifi->hidden);
2111 wifi->hidden = NULL;
2118 static void wifi_regdom_callback(int result,
2122 struct connman_device *device = user_data;
2124 connman_device_regdom_notify(device, result, alpha2);
2126 connman_device_unref(device);
2129 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2131 struct wifi_data *wifi = connman_device_get_data(device);
2137 connman_device_ref(device);
2139 ret = g_supplicant_interface_set_country(wifi->interface,
2140 wifi_regdom_callback,
2143 connman_device_unref(device);
2148 static struct connman_device_driver wifi_ng_driver = {
2150 .type = CONNMAN_DEVICE_TYPE_WIFI,
2151 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2152 .probe = wifi_probe,
2153 .remove = wifi_remove,
2154 .enable = wifi_enable,
2155 .disable = wifi_disable,
2157 .set_regdom = wifi_set_regdom,
2158 #if defined TIZEN_EXT
2159 .specific_scan = wifi_specific_scan,
2163 static void system_ready(void)
2167 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2168 connman_error("Failed to register WiFi driver");
2171 static void system_killed(void)
2175 connman_device_driver_unregister(&wifi_ng_driver);
2178 static int network_probe(struct connman_network *network)
2180 DBG("network %p", network);
2185 static void network_remove(struct connman_network *network)
2187 struct connman_device *device = connman_network_get_device(network);
2188 struct wifi_data *wifi;
2190 DBG("network %p", network);
2192 wifi = connman_device_get_data(device);
2196 if (wifi->network != network)
2199 wifi->network = NULL;
2201 #if defined TIZEN_EXT
2202 wifi->disconnecting = false;
2204 if (wifi->pending_network == network)
2205 wifi->pending_network = NULL;
2207 if (wifi->scan_pending_network == network)
2208 wifi->scan_pending_network = NULL;
2212 static void connect_callback(int result, GSupplicantInterface *interface,
2215 #if defined TIZEN_EXT
2217 struct wifi_data *wifi;
2219 struct connman_network *network = user_data;
2221 DBG("network %p result %d", network, result);
2223 #if defined TIZEN_EXT
2224 for (list = iface_list; list; list = list->next) {
2227 if (wifi && wifi->network == network)
2231 /* wifi_data may be invalid because wifi is already disabled */
2236 if (result == -ENOKEY) {
2237 connman_network_set_error(network,
2238 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2239 } else if (result < 0) {
2240 connman_network_set_error(network,
2241 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2244 connman_network_unref(network);
2247 static GSupplicantSecurity network_security(const char *security)
2249 if (g_str_equal(security, "none"))
2250 return G_SUPPLICANT_SECURITY_NONE;
2251 else if (g_str_equal(security, "wep"))
2252 return G_SUPPLICANT_SECURITY_WEP;
2253 else if (g_str_equal(security, "psk"))
2254 return G_SUPPLICANT_SECURITY_PSK;
2255 else if (g_str_equal(security, "wpa"))
2256 return G_SUPPLICANT_SECURITY_PSK;
2257 else if (g_str_equal(security, "rsn"))
2258 return G_SUPPLICANT_SECURITY_PSK;
2259 else if (g_str_equal(security, "ieee8021x"))
2260 return G_SUPPLICANT_SECURITY_IEEE8021X;
2261 #if defined TIZEN_EXT
2262 else if (g_str_equal(security, "ft_psk") == TRUE)
2263 return G_SUPPLICANT_SECURITY_FT_PSK;
2264 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2265 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2268 return G_SUPPLICANT_SECURITY_UNKNOWN;
2271 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2273 const char *security;
2275 memset(ssid, 0, sizeof(*ssid));
2276 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2277 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2279 ssid->scan_ssid = 1;
2280 security = connman_network_get_string(network, "WiFi.Security");
2281 ssid->security = network_security(security);
2282 ssid->passphrase = connman_network_get_string(network,
2285 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2288 * If our private key password is unset,
2289 * we use the supplied passphrase. That is needed
2290 * for PEAP where 2 passphrases (identity and client
2291 * cert may have to be provided.
2293 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2294 connman_network_set_string(network,
2295 "WiFi.PrivateKeyPassphrase",
2297 /* We must have an identity for both PEAP and TLS */
2298 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2300 /* Use agent provided identity as a fallback */
2301 if (!ssid->identity || strlen(ssid->identity) == 0)
2302 ssid->identity = connman_network_get_string(network,
2303 "WiFi.AgentIdentity");
2305 ssid->ca_cert_path = connman_network_get_string(network,
2307 ssid->client_cert_path = connman_network_get_string(network,
2308 "WiFi.ClientCertFile");
2309 ssid->private_key_path = connman_network_get_string(network,
2310 "WiFi.PrivateKeyFile");
2311 ssid->private_key_passphrase = connman_network_get_string(network,
2312 "WiFi.PrivateKeyPassphrase");
2313 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2315 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2316 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2318 #if defined TIZEN_EXT
2319 ssid->bssid = connman_network_get_bssid(network);
2321 #if defined TIZEN_EXT
2322 ssid->freq = connman_network_get_frequency(network);
2325 if (connman_setting_get_bool("BackgroundScanning"))
2326 ssid->bgscan = BGSCAN_DEFAULT;
2329 static int network_connect(struct connman_network *network)
2331 struct connman_device *device = connman_network_get_device(network);
2332 struct wifi_data *wifi;
2333 GSupplicantInterface *interface;
2334 GSupplicantSSID *ssid;
2336 DBG("network %p", network);
2341 wifi = connman_device_get_data(device);
2345 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2349 interface = wifi->interface;
2351 ssid_init(ssid, network);
2353 if (wifi->disconnecting) {
2354 wifi->pending_network = network;
2357 wifi->network = connman_network_ref(network);
2359 #if defined TIZEN_EXT
2360 wifi->scan_pending_network = NULL;
2363 return g_supplicant_interface_connect(interface, ssid,
2364 connect_callback, network);
2367 return -EINPROGRESS;
2370 static void disconnect_callback(int result, GSupplicantInterface *interface,
2373 #if defined TIZEN_EXT
2375 struct wifi_data *wifi;
2376 struct connman_network *network = user_data;
2378 DBG("network %p result %d", network, result);
2380 for (list = iface_list; list; list = list->next) {
2383 if (wifi->network == NULL && wifi->disconnecting == true)
2384 wifi->disconnecting = false;
2386 if (wifi->network == network)
2390 /* wifi_data may be invalid because wifi is already disabled */
2395 struct wifi_data *wifi = user_data;
2398 DBG("result %d supplicant interface %p wifi %p",
2399 result, interface, wifi);
2401 if (result == -ECONNABORTED) {
2402 DBG("wifi interface no longer available");
2406 if (wifi->network) {
2408 * if result < 0 supplican return an error because
2409 * the network is not current.
2410 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2411 * failed, call connman_network_set_connected to report
2412 * disconnect is completed.
2415 connman_network_set_connected(wifi->network, false);
2418 wifi->network = NULL;
2420 wifi->disconnecting = false;
2422 if (wifi->pending_network) {
2423 network_connect(wifi->pending_network);
2424 wifi->pending_network = NULL;
2427 start_autoscan(wifi->device);
2430 static int network_disconnect(struct connman_network *network)
2432 struct connman_device *device = connman_network_get_device(network);
2433 struct wifi_data *wifi;
2435 #if defined TIZEN_EXT
2436 struct connman_service *service;
2439 DBG("network %p", network);
2441 wifi = connman_device_get_data(device);
2442 if (!wifi || !wifi->interface)
2445 #if defined TIZEN_EXT
2446 if (connman_network_get_associating(network) == true) {
2447 connman_network_clear_associating(network);
2448 connman_network_set_bool(network, "WiFi.UseWPS", false);
2450 service = connman_service_lookup_from_network(network);
2452 if (service != NULL &&
2453 (__connman_service_is_connected_state(service,
2454 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2455 __connman_service_is_connected_state(service,
2456 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2457 (connman_service_get_favorite(service) == false))
2458 __connman_service_set_passphrase(service, NULL);
2461 if (wifi->pending_network == network)
2462 wifi->pending_network = NULL;
2464 if (wifi->scan_pending_network == network)
2465 wifi->scan_pending_network = NULL;
2468 connman_network_set_associating(network, false);
2470 if (wifi->disconnecting)
2473 wifi->disconnecting = true;
2475 #if defined TIZEN_EXT
2476 err = g_supplicant_interface_disconnect(wifi->interface,
2477 disconnect_callback, network);
2479 err = g_supplicant_interface_disconnect(wifi->interface,
2480 disconnect_callback, wifi);
2484 wifi->disconnecting = false;
2489 static struct connman_network_driver network_driver = {
2491 .type = CONNMAN_NETWORK_TYPE_WIFI,
2492 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2493 .probe = network_probe,
2494 .remove = network_remove,
2495 .connect = network_connect,
2496 .disconnect = network_disconnect,
2499 static void interface_added(GSupplicantInterface *interface)
2501 const char *ifname = g_supplicant_interface_get_ifname(interface);
2502 const char *driver = g_supplicant_interface_get_driver(interface);
2503 struct wifi_data *wifi;
2505 wifi = g_supplicant_interface_get_data(interface);
2507 wifi = get_pending_wifi_data(ifname);
2511 g_supplicant_interface_set_data(interface, wifi);
2512 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2513 wifi->p2p_device = true;
2516 DBG("ifname %s driver %s wifi %p tethering %d",
2517 ifname, driver, wifi, wifi->tethering);
2519 if (!wifi->device) {
2520 connman_error("WiFi device not set");
2524 connman_device_set_powered(wifi->device, true);
2527 static bool is_idle(struct wifi_data *wifi)
2529 DBG("state %d", wifi->state);
2531 switch (wifi->state) {
2532 case G_SUPPLICANT_STATE_UNKNOWN:
2533 case G_SUPPLICANT_STATE_DISABLED:
2534 case G_SUPPLICANT_STATE_DISCONNECTED:
2535 case G_SUPPLICANT_STATE_INACTIVE:
2536 case G_SUPPLICANT_STATE_SCANNING:
2539 case G_SUPPLICANT_STATE_AUTHENTICATING:
2540 case G_SUPPLICANT_STATE_ASSOCIATING:
2541 case G_SUPPLICANT_STATE_ASSOCIATED:
2542 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2543 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2544 case G_SUPPLICANT_STATE_COMPLETED:
2551 static bool is_idle_wps(GSupplicantInterface *interface,
2552 struct wifi_data *wifi)
2554 /* First, let's check if WPS processing did not went wrong */
2555 if (g_supplicant_interface_get_wps_state(interface) ==
2556 G_SUPPLICANT_WPS_STATE_FAIL)
2559 /* Unlike normal connection, being associated while processing wps
2560 * actually means that we are idling. */
2561 switch (wifi->state) {
2562 case G_SUPPLICANT_STATE_UNKNOWN:
2563 case G_SUPPLICANT_STATE_DISABLED:
2564 case G_SUPPLICANT_STATE_DISCONNECTED:
2565 case G_SUPPLICANT_STATE_INACTIVE:
2566 case G_SUPPLICANT_STATE_SCANNING:
2567 case G_SUPPLICANT_STATE_ASSOCIATED:
2569 case G_SUPPLICANT_STATE_AUTHENTICATING:
2570 case G_SUPPLICANT_STATE_ASSOCIATING:
2571 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2572 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2573 case G_SUPPLICANT_STATE_COMPLETED:
2580 static bool handle_wps_completion(GSupplicantInterface *interface,
2581 struct connman_network *network,
2582 struct connman_device *device,
2583 struct wifi_data *wifi)
2587 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2589 const unsigned char *ssid, *wps_ssid;
2590 unsigned int ssid_len, wps_ssid_len;
2591 const char *wps_key;
2593 /* Checking if we got associated with requested
2595 ssid = connman_network_get_blob(network, "WiFi.SSID",
2598 wps_ssid = g_supplicant_interface_get_wps_ssid(
2599 interface, &wps_ssid_len);
2601 if (!wps_ssid || wps_ssid_len != ssid_len ||
2602 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2603 connman_network_set_associating(network, false);
2604 #if defined TIZEN_EXT
2605 g_supplicant_interface_disconnect(wifi->interface,
2606 disconnect_callback, wifi->network);
2608 connman_network_set_bool(network, "WiFi.UseWPS", false);
2609 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2611 g_supplicant_interface_disconnect(wifi->interface,
2612 disconnect_callback, wifi);
2617 wps_key = g_supplicant_interface_get_wps_key(interface);
2618 connman_network_set_string(network, "WiFi.Passphrase",
2621 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2627 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2628 struct connman_network *network,
2629 struct wifi_data *wifi)
2631 #if defined TIZEN_EXT
2632 const char *security;
2633 struct connman_service *service;
2635 if (wifi->connected)
2638 security = connman_network_get_string(network, "WiFi.Security");
2640 if (security && g_str_equal(security, "ieee8021x") == true &&
2641 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2643 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2648 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2651 struct connman_service *service;
2653 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2656 if (wifi->connected)
2660 service = connman_service_lookup_from_network(network);
2666 if (connman_service_get_favorite(service)) {
2667 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2672 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2677 #if defined TIZEN_EXT
2678 static bool handle_wifi_assoc_retry(struct connman_network *network,
2679 struct wifi_data *wifi)
2681 const char *security;
2683 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2684 connman_network_get_connecting(network) != true) {
2685 wifi->assoc_retry_count = 0;
2689 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2690 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2691 wifi->assoc_retry_count = 0;
2695 security = connman_network_get_string(network, "WiFi.Security");
2696 if (security && g_str_equal(security, "ieee8021x") == true &&
2697 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2698 wifi->assoc_retry_count = 0;
2702 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2703 wifi->assoc_retry_count = 0;
2705 /* Honestly it's not an invalid-key error,
2706 * however QA team recommends that the invalid-key error
2707 * might be better to display for user experience.
2709 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2718 static void interface_state(GSupplicantInterface *interface)
2720 struct connman_network *network;
2721 struct connman_device *device;
2722 struct wifi_data *wifi;
2723 GSupplicantState state = g_supplicant_interface_get_state(interface);
2726 wifi = g_supplicant_interface_get_data(interface);
2728 DBG("wifi %p interface state %d", wifi, state);
2733 device = wifi->device;
2737 if (g_supplicant_interface_get_ready(interface) &&
2738 !wifi->interface_ready) {
2739 wifi->interface_ready = true;
2740 finalize_interface_creation(wifi);
2743 network = wifi->network;
2748 case G_SUPPLICANT_STATE_SCANNING:
2751 case G_SUPPLICANT_STATE_AUTHENTICATING:
2752 case G_SUPPLICANT_STATE_ASSOCIATING:
2753 #if defined TIZEN_EXT
2754 reset_autoscan(device);
2756 stop_autoscan(device);
2759 if (!wifi->connected)
2760 connman_network_set_associating(network, true);
2764 case G_SUPPLICANT_STATE_COMPLETED:
2765 #if defined TIZEN_EXT
2766 /* though it should be already reset: */
2767 reset_autoscan(device);
2769 wifi->assoc_retry_count = 0;
2771 wifi->scan_pending_network = NULL;
2773 /* should be cleared scanning flag */
2774 bool scanning = connman_device_get_scanning(device);
2776 connman_device_set_scanning(device,
2777 CONNMAN_SERVICE_TYPE_WIFI, false);
2778 connman_device_unref(device);
2781 /* though it should be already stopped: */
2782 stop_autoscan(device);
2785 if (!handle_wps_completion(interface, network, device, wifi))
2788 connman_network_set_connected(network, true);
2789 wifi->disconnect_code = 0;
2790 wifi->assoc_code = 0;
2793 case G_SUPPLICANT_STATE_DISCONNECTED:
2795 * If we're in one of the idle modes, we have
2796 * not started association yet and thus setting
2797 * those ones to FALSE could cancel an association
2800 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2802 if (is_idle_wps(interface, wifi))
2808 /* If previous state was 4way-handshake, then
2809 * it's either: psk was incorrect and thus we retry
2810 * or if we reach the maximum retries we declare the
2812 if (handle_4way_handshake_failure(interface,
2816 /* See table 8-36 Reason codes in IEEE Std 802.11 */
2817 switch (wifi->disconnect_code) {
2818 case 1: /* Unspecified reason */
2819 /* Let's assume it's because we got blocked */
2821 case 6: /* Class 2 frame received from nonauthenticated STA */
2822 connman_network_set_error(network,
2823 CONNMAN_NETWORK_ERROR_BLOCKED);
2831 /* We disable the selected network, if not then
2832 * wpa_supplicant will loop retrying */
2833 if (g_supplicant_interface_enable_selected_network(interface,
2835 DBG("Could not disables selected network");
2837 #if defined TIZEN_EXT
2840 err = g_supplicant_interface_remove_network(wifi->interface);
2842 DBG("Failed to remove network(%d)", err);
2845 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2846 * Retry association until its retry count is expired */
2847 if (handle_wifi_assoc_retry(network, wifi) == true) {
2848 throw_wifi_scan(wifi->device, scan_callback);
2849 wifi->scan_pending_network = wifi->network;
2853 if(wifi->disconnect_code > 0){
2854 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
2855 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
2858 /* To avoid unnecessary repeated association in wpa_supplicant,
2859 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2860 if (wps != true && wifi->network && wifi->disconnecting == false) {
2861 wifi->disconnecting = true;
2862 err = g_supplicant_interface_disconnect(wifi->interface,
2863 disconnect_callback, wifi->network);
2865 wifi->disconnecting = false;
2867 connman_network_set_connected(network, false);
2868 connman_network_set_associating(network, false);
2870 start_autoscan(device);
2876 connman_network_set_connected(network, false);
2877 connman_network_set_associating(network, false);
2878 wifi->disconnecting = false;
2880 start_autoscan(device);
2884 case G_SUPPLICANT_STATE_INACTIVE:
2885 #if defined TIZEN_EXT
2886 if (handle_wps_completion(interface, network, device, wifi) == false)
2889 connman_network_set_associating(network, false);
2890 start_autoscan(device);
2894 case G_SUPPLICANT_STATE_UNKNOWN:
2895 case G_SUPPLICANT_STATE_DISABLED:
2896 case G_SUPPLICANT_STATE_ASSOCIATED:
2897 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2898 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2902 wifi->state = state;
2904 /* Saving wpa_s state policy:
2905 * If connected and if the state changes are roaming related:
2906 * --> We stay connected
2908 * --> We are connected
2910 * --> We are not connected
2913 #if defined TIZEN_EXT
2914 case G_SUPPLICANT_STATE_SCANNING:
2917 case G_SUPPLICANT_STATE_AUTHENTICATING:
2918 case G_SUPPLICANT_STATE_ASSOCIATING:
2919 case G_SUPPLICANT_STATE_ASSOCIATED:
2920 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2921 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2922 if (wifi->connected)
2923 connman_warn("Probably roaming right now!"
2924 " Staying connected...");
2926 wifi->connected = false;
2928 case G_SUPPLICANT_STATE_COMPLETED:
2929 wifi->connected = true;
2932 wifi->connected = false;
2939 static void interface_removed(GSupplicantInterface *interface)
2941 const char *ifname = g_supplicant_interface_get_ifname(interface);
2942 struct wifi_data *wifi;
2944 DBG("ifname %s", ifname);
2946 wifi = g_supplicant_interface_get_data(interface);
2949 wifi->interface = NULL;
2951 if (wifi && wifi->tethering)
2954 if (!wifi || !wifi->device) {
2955 DBG("wifi interface already removed");
2959 connman_device_set_powered(wifi->device, false);
2961 check_p2p_technology();
2964 static void set_device_type(const char *type, char dev_type[17])
2966 const char *oui = "0050F204";
2967 const char *category = "0100";
2968 const char *sub_category = "0000";
2970 if (!g_strcmp0(type, "handset")) {
2972 sub_category = "0500";
2973 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2974 sub_category = "0100";
2975 else if (!g_strcmp0(type, "server"))
2976 sub_category = "0200";
2977 else if (!g_strcmp0(type, "laptop"))
2978 sub_category = "0500";
2979 else if (!g_strcmp0(type, "desktop"))
2980 sub_category = "0600";
2981 else if (!g_strcmp0(type, "tablet"))
2982 sub_category = "0900";
2983 else if (!g_strcmp0(type, "watch"))
2986 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2989 static void p2p_support(GSupplicantInterface *interface)
2991 char dev_type[17] = {};
2992 const char *hostname;
2996 if (!g_supplicant_interface_has_p2p(interface))
2999 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3000 DBG("Could not register P2P technology driver");
3004 hostname = connman_utsname_get_hostname();
3006 hostname = "ConnMan";
3008 set_device_type(connman_machine_get_type(), dev_type);
3009 g_supplicant_interface_set_p2p_device_config(interface,
3010 hostname, dev_type);
3011 connman_peer_driver_register(&peer_driver);
3014 static void scan_started(GSupplicantInterface *interface)
3019 static void scan_finished(GSupplicantInterface *interface)
3021 #if defined TIZEN_EXT
3022 struct wifi_data *wifi;
3023 bool is_associating = false;
3024 static bool is_scanning = true;
3029 #if defined TIZEN_EXT
3030 wifi = g_supplicant_interface_get_data(interface);
3031 if (wifi && wifi->scan_pending_network) {
3032 network_connect(wifi->scan_pending_network);
3033 wifi->scan_pending_network = NULL;
3036 //service state - associating
3037 if(!wifi || !wifi->network)
3040 is_associating = connman_network_get_associating(wifi->network);
3041 if(is_associating && is_scanning){
3042 is_scanning = false;
3043 DBG("send scan for connecting");
3044 throw_wifi_scan(wifi->device, scan_callback);
3055 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3057 unsigned char strength;
3059 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3061 #if !defined TIZEN_EXT
3068 static void network_added(GSupplicantNetwork *supplicant_network)
3070 struct connman_network *network;
3071 GSupplicantInterface *interface;
3072 struct wifi_data *wifi;
3073 const char *name, *identifier, *security, *group, *mode;
3074 const unsigned char *ssid;
3075 unsigned int ssid_len;
3079 bool wps_advertizing;
3081 #if defined TIZEN_EXT
3082 const char *wifi_vsie;
3083 unsigned int wifi_vsie_len;
3086 mode = g_supplicant_network_get_mode(supplicant_network);
3087 identifier = g_supplicant_network_get_identifier(supplicant_network);
3089 DBG("%s", identifier);
3091 if (!g_strcmp0(mode, "adhoc"))
3094 interface = g_supplicant_network_get_interface(supplicant_network);
3095 wifi = g_supplicant_interface_get_data(interface);
3096 name = g_supplicant_network_get_name(supplicant_network);
3097 security = g_supplicant_network_get_security(supplicant_network);
3098 group = g_supplicant_network_get_identifier(supplicant_network);
3099 wps = g_supplicant_network_get_wps(supplicant_network);
3100 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3101 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3102 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3103 supplicant_network);
3108 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3110 #if defined TIZEN_EXT
3111 wifi_vsie = g_supplicant_network_get_wifi_vsie(supplicant_network, &wifi_vsie_len);
3113 network = connman_device_get_network(wifi->device, identifier);
3116 network = connman_network_create(identifier,
3117 CONNMAN_NETWORK_TYPE_WIFI);
3121 connman_network_set_index(network, wifi->index);
3123 if (connman_device_add_network(wifi->device, network) < 0) {
3124 connman_network_unref(network);
3128 wifi->networks = g_slist_prepend(wifi->networks, network);
3131 if (name && name[0] != '\0')
3132 connman_network_set_name(network, name);
3134 connman_network_set_blob(network, "WiFi.SSID",
3136 #if defined TIZEN_EXT
3137 if(wifi_vsie_len > 0 && wifi_vsie)
3138 connman_network_set_blob(network, "WiFi.Vsie",
3139 wifi_vsie, wifi_vsie_len);
3141 connman_network_set_string(network, "WiFi.Security", security);
3142 connman_network_set_strength(network,
3143 calculate_strength(supplicant_network));
3144 connman_network_set_bool(network, "WiFi.WPS", wps);
3147 /* Is AP advertizing for WPS association?
3148 * If so, we decide to use WPS by default */
3149 if (wps_ready && wps_pbc &&
3151 #if !defined TIZEN_EXT
3152 connman_network_set_bool(network, "WiFi.UseWPS", true);
3154 DBG("wps is activating by ap but ignore it.");
3159 connman_network_set_frequency(network,
3160 g_supplicant_network_get_frequency(supplicant_network));
3161 #if defined TIZEN_EXT
3162 connman_network_set_bssid(network,
3163 g_supplicant_network_get_bssid(supplicant_network));
3164 connman_network_set_maxrate(network,
3165 g_supplicant_network_get_maxrate(supplicant_network));
3166 connman_network_set_enc_mode(network,
3167 g_supplicant_network_get_enc_mode(supplicant_network));
3168 connman_network_set_rsn_mode(network,
3169 g_supplicant_network_get_rsn_mode(supplicant_network));
3170 connman_network_set_keymgmt(network,
3171 g_supplicant_network_get_keymgmt(supplicant_network));
3173 connman_network_set_available(network, true);
3174 connman_network_set_string(network, "WiFi.Mode", mode);
3176 #if defined TIZEN_EXT
3181 connman_network_set_group(network, group);
3183 #if defined TIZEN_EXT
3184 if (wifi_first_scan == true)
3185 found_with_first_scan = true;
3188 if (wifi->hidden && ssid) {
3189 #if defined TIZEN_EXT
3190 if (network_security(wifi->hidden->security) ==
3191 network_security(security) &&
3193 if (!g_strcmp0(wifi->hidden->security, security) &&
3195 wifi->hidden->ssid_len == ssid_len &&
3196 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3197 connman_network_connect_hidden(network,
3198 wifi->hidden->identity,
3199 wifi->hidden->passphrase,
3200 wifi->hidden->user_data);
3201 wifi->hidden->user_data = NULL;
3202 hidden_free(wifi->hidden);
3203 wifi->hidden = NULL;
3208 static void network_removed(GSupplicantNetwork *network)
3210 GSupplicantInterface *interface;
3211 struct wifi_data *wifi;
3212 const char *name, *identifier;
3213 struct connman_network *connman_network;
3215 interface = g_supplicant_network_get_interface(network);
3216 wifi = g_supplicant_interface_get_data(interface);
3217 identifier = g_supplicant_network_get_identifier(network);
3218 name = g_supplicant_network_get_name(network);
3220 DBG("name %s", name);
3225 connman_network = connman_device_get_network(wifi->device, identifier);
3226 if (!connman_network)
3229 #if defined TIZEN_EXT
3230 if (connman_network == wifi->scan_pending_network)
3231 wifi->scan_pending_network = NULL;
3233 if (connman_network == wifi->pending_network)
3234 wifi->pending_network = NULL;
3236 if(connman_network_get_connecting(connman_network) == true){
3237 connman_network_set_connected(connman_network, false);
3241 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3243 connman_device_remove_network(wifi->device, connman_network);
3244 connman_network_unref(connman_network);
3247 static void network_changed(GSupplicantNetwork *network, const char *property)
3249 GSupplicantInterface *interface;
3250 struct wifi_data *wifi;
3251 const char *name, *identifier;
3252 struct connman_network *connman_network;
3254 #if defined TIZEN_EXT
3255 const unsigned char *bssid;
3256 unsigned int maxrate;
3261 interface = g_supplicant_network_get_interface(network);
3262 wifi = g_supplicant_interface_get_data(interface);
3263 identifier = g_supplicant_network_get_identifier(network);
3264 name = g_supplicant_network_get_name(network);
3266 DBG("name %s", name);
3271 connman_network = connman_device_get_network(wifi->device, identifier);
3272 if (!connman_network)
3275 if (g_str_equal(property, "Signal")) {
3276 connman_network_set_strength(connman_network,
3277 calculate_strength(network));
3278 connman_network_update(connman_network);
3281 #if defined TIZEN_EXT
3282 bssid = g_supplicant_network_get_bssid(network);
3283 maxrate = g_supplicant_network_get_maxrate(network);
3284 frequency = g_supplicant_network_get_frequency(network);
3285 wps = g_supplicant_network_get_wps(network);
3287 connman_network_set_bssid(connman_network, bssid);
3288 connman_network_set_maxrate(connman_network, maxrate);
3289 connman_network_set_frequency(connman_network, frequency);
3290 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3294 static void apply_peer_services(GSupplicantPeer *peer,
3295 struct connman_peer *connman_peer)
3297 const unsigned char *data;
3302 connman_peer_reset_services(connman_peer);
3304 data = g_supplicant_peer_get_widi_ies(peer, &length);
3306 connman_peer_add_service(connman_peer,
3307 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3311 static void add_station(const char *mac)
3313 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3317 static void remove_station(const char *mac)
3319 connman_technology_tethering_remove_station(mac);
3322 static void peer_found(GSupplicantPeer *peer)
3324 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3325 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3326 struct connman_peer *connman_peer;
3327 const char *identifier, *name;
3329 #if defined TIZEN_EXT
3333 identifier = g_supplicant_peer_get_identifier(peer);
3334 name = g_supplicant_peer_get_name(peer);
3336 DBG("ident: %s", identifier);
3338 connman_peer = connman_peer_get(wifi->device, identifier);
3342 connman_peer = connman_peer_create(identifier);
3343 connman_peer_set_name(connman_peer, name);
3344 connman_peer_set_device(connman_peer, wifi->device);
3345 apply_peer_services(peer, connman_peer);
3347 ret = connman_peer_register(connman_peer);
3348 if (ret < 0 && ret != -EALREADY)
3349 connman_peer_unref(connman_peer);
3352 static void peer_lost(GSupplicantPeer *peer)
3354 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3355 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3356 struct connman_peer *connman_peer;
3357 const char *identifier;
3362 identifier = g_supplicant_peer_get_identifier(peer);
3364 DBG("ident: %s", identifier);
3366 connman_peer = connman_peer_get(wifi->device, identifier);
3368 if (wifi->p2p_connecting &&
3369 wifi->pending_peer == connman_peer) {
3370 peer_connect_timeout(wifi);
3372 connman_peer_unregister(connman_peer);
3373 connman_peer_unref(connman_peer);
3377 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3379 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3380 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3381 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3382 struct connman_peer *connman_peer;
3383 const char *identifier;
3385 #if defined TIZEN_EXT
3390 identifier = g_supplicant_peer_get_identifier(peer);
3392 DBG("ident: %s", identifier);
3394 connman_peer = connman_peer_get(wifi->device, identifier);
3399 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3400 apply_peer_services(peer, connman_peer);
3401 connman_peer_services_changed(connman_peer);
3403 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3404 if (!g_supplicant_peer_is_in_a_group(peer))
3405 p_state = CONNMAN_PEER_STATE_IDLE;
3407 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3409 case G_SUPPLICANT_PEER_GROUP_STARTED:
3411 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3412 p_state = CONNMAN_PEER_STATE_IDLE;
3414 case G_SUPPLICANT_PEER_GROUP_JOINED:
3415 connman_peer_set_iface_address(connman_peer,
3416 g_supplicant_peer_get_iface_address(peer));
3418 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3419 p_state = CONNMAN_PEER_STATE_IDLE;
3421 case G_SUPPLICANT_PEER_GROUP_FAILED:
3422 if (g_supplicant_peer_has_requested_connection(peer))
3423 p_state = CONNMAN_PEER_STATE_IDLE;
3425 p_state = CONNMAN_PEER_STATE_FAILURE;
3429 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3430 p_state == CONNMAN_PEER_STATE_FAILURE) {
3431 if (wifi->p2p_connecting
3432 && connman_peer == wifi->pending_peer)
3433 peer_cancel_timeout(wifi);
3435 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3438 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3441 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3442 GSupplicantInterface *g_iface;
3443 struct wifi_data *g_wifi;
3445 g_iface = g_supplicant_peer_get_group_interface(peer);
3449 g_wifi = g_supplicant_interface_get_data(g_iface);
3453 connman_peer_set_as_master(connman_peer,
3454 !g_supplicant_peer_is_client(peer));
3455 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3458 connman_peer_set_state(connman_peer, p_state);
3461 static void peer_request(GSupplicantPeer *peer)
3463 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3464 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3465 struct connman_peer *connman_peer;
3466 const char *identifier;
3468 #if defined TIZEN_EXT
3473 identifier = g_supplicant_peer_get_identifier(peer);
3475 DBG("ident: %s", identifier);
3477 connman_peer = connman_peer_get(wifi->device, identifier);
3481 connman_peer_request_connection(connman_peer);
3484 #if defined TIZEN_EXT
3485 static void system_power_off(void)
3488 struct wifi_data *wifi;
3489 struct connman_service *service;
3490 struct connman_ipconfig *ipconfig_ipv4;
3492 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3493 for (list = iface_list; list; list = list->next) {
3496 if (wifi->network != NULL) {
3497 service = connman_service_lookup_from_network(wifi->network);
3498 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3499 __connman_dhcp_stop(ipconfig_ipv4);
3505 static void network_merged(GSupplicantNetwork *network)
3507 GSupplicantInterface *interface;
3508 GSupplicantState state;
3509 struct wifi_data *wifi;
3510 const char *identifier;
3511 struct connman_network *connman_network;
3512 unsigned int ishs20AP = 0;
3515 interface = g_supplicant_network_get_interface(network);
3519 state = g_supplicant_interface_get_state(interface);
3520 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3523 wifi = g_supplicant_interface_get_data(interface);
3527 identifier = g_supplicant_network_get_identifier(network);
3529 connman_network = connman_device_get_network(wifi->device, identifier);
3530 if (!connman_network)
3533 DBG("merged identifier %s", identifier);
3535 if (wifi->connected == FALSE) {
3537 case G_SUPPLICANT_STATE_AUTHENTICATING:
3538 case G_SUPPLICANT_STATE_ASSOCIATING:
3539 case G_SUPPLICANT_STATE_ASSOCIATED:
3540 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3541 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3542 connman_network_set_associating(connman_network, TRUE);
3544 case G_SUPPLICANT_STATE_COMPLETED:
3545 connman_network_set_connected(connman_network, TRUE);
3548 DBG("Not handled the state : %d", state);
3553 ishs20AP = g_supplicant_network_is_hs20AP(network);
3554 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3557 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3558 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3559 connman_network_set_string(connman_network, "WiFi.EAP",
3561 connman_network_set_string(connman_network, "WiFi.Identity",
3562 g_supplicant_network_get_identity(network));
3563 connman_network_set_string(connman_network, "WiFi.Phase2",
3564 g_supplicant_network_get_phase2(network));
3569 wifi->network = connman_network;
3573 static void debug(const char *str)
3575 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3576 connman_debug("%s", str);
3579 static void disconnect_reasoncode(GSupplicantInterface *interface,
3582 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3584 wifi->disconnect_code = reasoncode;
3588 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
3590 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3592 #if defined TIZEN_EXT
3593 struct connman_network *network;
3597 wifi->assoc_code = status_code;
3599 #if defined TIZEN_EXT
3600 network = wifi->network;
3601 connman_network_set_assoc_status_code(network,status_code);
3607 static const GSupplicantCallbacks callbacks = {
3608 .system_ready = system_ready,
3609 .system_killed = system_killed,
3610 .interface_added = interface_added,
3611 .interface_state = interface_state,
3612 .interface_removed = interface_removed,
3613 .p2p_support = p2p_support,
3614 .scan_started = scan_started,
3615 .scan_finished = scan_finished,
3616 .network_added = network_added,
3617 .network_removed = network_removed,
3618 .network_changed = network_changed,
3619 .add_station = add_station,
3620 .remove_station = remove_station,
3621 .peer_found = peer_found,
3622 .peer_lost = peer_lost,
3623 .peer_changed = peer_changed,
3624 .peer_request = peer_request,
3625 #if defined TIZEN_EXT
3626 .system_power_off = system_power_off,
3627 .network_merged = network_merged,
3629 .disconnect_reasoncode = disconnect_reasoncode,
3630 .assoc_status_code = assoc_status_code,
3635 static int tech_probe(struct connman_technology *technology)
3637 wifi_technology = technology;
3642 static void tech_remove(struct connman_technology *technology)
3644 wifi_technology = NULL;
3647 struct wifi_tethering_info {
3648 struct wifi_data *wifi;
3649 struct connman_technology *technology;
3651 GSupplicantSSID *ssid;
3654 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3655 const char *passphrase, bool hidden)
3657 GSupplicantSSID *ap;
3659 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3663 ap->mode = G_SUPPLICANT_MODE_MASTER;
3665 ap->ssid_len = strlen(ssid);
3669 if (!passphrase || strlen(passphrase) == 0) {
3670 ap->security = G_SUPPLICANT_SECURITY_NONE;
3671 ap->passphrase = NULL;
3673 ap->security = G_SUPPLICANT_SECURITY_PSK;
3674 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3675 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3676 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3677 ap->passphrase = passphrase;
3681 ap->ignore_broadcast_ssid =
3682 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3684 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3689 static void ap_start_callback(int result, GSupplicantInterface *interface,
3692 struct wifi_tethering_info *info = user_data;
3694 DBG("result %d index %d bridge %s",
3695 result, info->wifi->index, info->wifi->bridge);
3698 connman_inet_remove_from_bridge(info->wifi->index,
3699 info->wifi->bridge);
3700 connman_technology_tethering_notify(info->technology, false);
3703 g_free(info->ifname);
3707 static void ap_create_callback(int result,
3708 GSupplicantInterface *interface,
3711 struct wifi_tethering_info *info = user_data;
3713 DBG("result %d ifname %s", result,
3714 g_supplicant_interface_get_ifname(interface));
3717 connman_inet_remove_from_bridge(info->wifi->index,
3718 info->wifi->bridge);
3719 connman_technology_tethering_notify(info->technology, false);
3721 g_free(info->ifname);
3727 info->wifi->interface = interface;
3728 g_supplicant_interface_set_data(interface, info->wifi);
3730 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3731 connman_error("Failed to set interface ap_scan property");
3733 g_supplicant_interface_connect(interface, info->ssid,
3734 ap_start_callback, info);
3737 static void sta_remove_callback(int result,
3738 GSupplicantInterface *interface,
3741 struct wifi_tethering_info *info = user_data;
3742 const char *driver = connman_option_get_string("wifi");
3744 DBG("ifname %s result %d ", info->ifname, result);
3747 info->wifi->tethering = true;
3749 g_free(info->ifname);
3755 info->wifi->interface = NULL;
3757 connman_technology_tethering_notify(info->technology, true);
3759 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3764 static int tech_set_tethering(struct connman_technology *technology,
3765 const char *identifier, const char *passphrase,
3766 const char *bridge, bool enabled, bool hidden)
3769 GSupplicantInterface *interface;
3770 struct wifi_data *wifi;
3771 struct wifi_tethering_info *info;
3779 for (list = iface_list; list; list = list->next) {
3782 if (wifi->tethering) {
3783 wifi->tethering = false;
3785 connman_inet_remove_from_bridge(wifi->index,
3787 wifi->bridged = false;
3791 connman_technology_tethering_notify(technology, false);
3796 for (list = iface_list; list; list = list->next) {
3799 interface = wifi->interface;
3804 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3806 mode = g_supplicant_interface_get_mode(interface);
3807 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3808 DBG("%s does not support AP mode", ifname);
3812 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3817 info->technology = technology;
3818 info->wifi->bridge = bridge;
3819 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3824 info->ifname = g_strdup(ifname);
3825 if (!info->ifname) {
3831 info->wifi->tethering = true;
3833 err = g_supplicant_interface_remove(interface,
3834 sta_remove_callback,
3843 static void regdom_callback(int result, const char *alpha2, void *user_data)
3847 if (!wifi_technology)
3853 connman_technology_regdom_notify(wifi_technology, alpha2);
3856 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3858 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3861 static struct connman_technology_driver tech_driver = {
3863 .type = CONNMAN_SERVICE_TYPE_WIFI,
3864 .probe = tech_probe,
3865 .remove = tech_remove,
3866 .set_tethering = tech_set_tethering,
3867 .set_regdom = tech_set_regdom,
3870 static int wifi_init(void)
3874 err = connman_network_driver_register(&network_driver);
3878 err = g_supplicant_register(&callbacks);
3880 connman_network_driver_unregister(&network_driver);
3884 err = connman_technology_driver_register(&tech_driver);
3886 g_supplicant_unregister(&callbacks);
3887 connman_network_driver_unregister(&network_driver);
3894 static void wifi_exit(void)
3898 connman_technology_driver_unregister(&tech_driver);
3900 g_supplicant_unregister(&callbacks);
3902 connman_network_driver_unregister(&network_driver);
3905 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3906 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)