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.
1326 #if defined TIZEN_EXT
1327 if (scanning && wifi && !wifi->allow_full_scan)
1331 connman_device_unref(device);
1333 #if defined TIZEN_EXT
1334 if (wifi && wifi->allow_full_scan) {
1335 DBG("Trigger Full Channel Scan");
1336 throw_wifi_scan(device, scan_callback);
1337 wifi->allow_full_scan = FALSE;
1339 if (wifi && wifi->scan_pending_network && result != -EIO) {
1340 network_connect(wifi->scan_pending_network);
1341 wifi->scan_pending_network = NULL;
1342 connman_network_set_connecting(wifi->network);
1345 if (is_wifi_notifier_registered != true &&
1346 wifi_first_scan == true && found_with_first_scan == true) {
1347 wifi_first_scan = false;
1348 found_with_first_scan = false;
1350 connman_notifier_register(¬ifier);
1351 is_wifi_notifier_registered = true;
1356 static void scan_callback_hidden(int result,
1357 GSupplicantInterface *interface, void *user_data)
1359 struct connman_device *device = user_data;
1360 struct wifi_data *wifi = connman_device_get_data(device);
1361 GSupplicantScanParams *scan_params;
1364 DBG("result %d wifi %p", result, wifi);
1369 /* User is trying to connect to a hidden AP */
1370 if (wifi->hidden && wifi->postpone_hidden)
1373 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1377 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1378 ret = g_supplicant_interface_scan(wifi->interface,
1380 scan_callback_hidden,
1386 g_supplicant_free_scan_params(scan_params);
1389 scan_callback(result, interface, user_data);
1392 static gboolean autoscan_timeout(gpointer data)
1394 struct connman_device *device = data;
1395 struct wifi_data *wifi = connman_device_get_data(device);
1396 struct autoscan_params *autoscan;
1402 autoscan = wifi->autoscan;
1404 if (autoscan->interval <= 0) {
1405 interval = autoscan->base;
1408 interval = autoscan->interval * autoscan->base;
1410 #if defined TIZEN_EXT
1411 if (autoscan->interval >= autoscan->limit)
1413 if (interval > autoscan->limit)
1415 interval = autoscan->limit;
1417 throw_wifi_scan(wifi->device, scan_callback_hidden);
1420 DBG("interval %d", interval);
1422 autoscan->interval = interval;
1424 autoscan->timeout = g_timeout_add_seconds(interval,
1425 autoscan_timeout, device);
1430 static void start_autoscan(struct connman_device *device)
1432 struct wifi_data *wifi = connman_device_get_data(device);
1433 struct autoscan_params *autoscan;
1440 if (wifi->p2p_device)
1443 if (wifi->connected)
1446 autoscan = wifi->autoscan;
1450 if (autoscan->timeout > 0 || autoscan->interval > 0)
1453 connman_device_ref(device);
1455 autoscan_timeout(device);
1458 static struct autoscan_params *parse_autoscan_params(const char *params)
1460 struct autoscan_params *autoscan;
1465 DBG("Emulating autoscan");
1467 list_params = g_strsplit(params, ":", 0);
1468 if (list_params == 0)
1471 if (g_strv_length(list_params) < 3) {
1472 g_strfreev(list_params);
1476 base = atoi(list_params[1]);
1477 limit = atoi(list_params[2]);
1479 g_strfreev(list_params);
1481 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1483 DBG("Could not allocate memory for autoscan");
1487 DBG("base %d - limit %d", base, limit);
1488 autoscan->base = base;
1489 autoscan->limit = limit;
1494 static void setup_autoscan(struct wifi_data *wifi)
1496 if (!wifi->autoscan)
1497 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1499 start_autoscan(wifi->device);
1502 static void finalize_interface_creation(struct wifi_data *wifi)
1504 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1506 if (!wifi->device) {
1507 connman_error("WiFi device not set");
1511 connman_device_set_powered(wifi->device, true);
1513 if (!connman_setting_get_bool("BackgroundScanning"))
1516 if (wifi->p2p_device)
1519 setup_autoscan(wifi);
1522 static void interface_create_callback(int result,
1523 GSupplicantInterface *interface,
1526 struct wifi_data *wifi = user_data;
1528 DBG("result %d ifname %s, wifi %p", result,
1529 g_supplicant_interface_get_ifname(interface),
1532 if (result < 0 || !wifi)
1535 wifi->interface = interface;
1536 g_supplicant_interface_set_data(interface, wifi);
1538 if (g_supplicant_interface_get_ready(interface)) {
1539 wifi->interface_ready = true;
1540 finalize_interface_creation(wifi);
1544 static int wifi_enable(struct connman_device *device)
1546 struct wifi_data *wifi = connman_device_get_data(device);
1549 const char *driver = connman_option_get_string("wifi");
1552 DBG("device %p %p", device, wifi);
1554 index = connman_device_get_index(device);
1555 if (!wifi || index < 0)
1558 if (is_p2p_connecting())
1559 return -EINPROGRESS;
1561 interface = connman_inet_ifname(index);
1562 ret = g_supplicant_interface_create(interface, driver, NULL,
1563 interface_create_callback,
1570 return -EINPROGRESS;
1573 static int wifi_disable(struct connman_device *device)
1575 struct wifi_data *wifi = connman_device_get_data(device);
1578 DBG("device %p wifi %p", device, wifi);
1583 wifi->connected = false;
1584 wifi->disconnecting = false;
1586 if (wifi->pending_network)
1587 wifi->pending_network = NULL;
1589 stop_autoscan(device);
1591 if (wifi->p2p_find_timeout) {
1592 g_source_remove(wifi->p2p_find_timeout);
1593 wifi->p2p_find_timeout = 0;
1594 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1595 connman_device_unref(wifi->device);
1598 /* In case of a user scan, device is still referenced */
1599 if (connman_device_get_scanning(device)) {
1600 connman_device_set_scanning(device,
1601 CONNMAN_SERVICE_TYPE_WIFI, false);
1602 connman_device_unref(wifi->device);
1605 remove_networks(device, wifi);
1607 #if defined TIZEN_EXT
1608 wifi->scan_pending_network = NULL;
1610 if (is_wifi_notifier_registered == true) {
1611 connman_notifier_unregister(¬ifier);
1612 is_wifi_notifier_registered = false;
1616 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1620 return -EINPROGRESS;
1623 struct last_connected {
1629 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1631 GTimeVal *aval = (GTimeVal *)a;
1632 GTimeVal *bval = (GTimeVal *)b;
1634 /* Note that the sort order is descending */
1635 if (aval->tv_sec < bval->tv_sec)
1638 if (aval->tv_sec > bval->tv_sec)
1644 static void free_entry(gpointer data)
1646 struct last_connected *entry = data;
1648 g_free(entry->ssid);
1652 static int get_latest_connections(int max_ssids,
1653 GSupplicantScanParams *scan_data)
1655 GSequenceIter *iter;
1656 GSequence *latest_list;
1657 struct last_connected *entry;
1666 latest_list = g_sequence_new(free_entry);
1670 services = connman_storage_get_services();
1671 for (i = 0; services && services[i]; i++) {
1672 if (strncmp(services[i], "wifi_", 5) != 0)
1675 keyfile = connman_storage_load_service(services[i]);
1679 str = g_key_file_get_string(keyfile,
1680 services[i], "Favorite", NULL);
1681 if (!str || g_strcmp0(str, "true")) {
1683 g_key_file_free(keyfile);
1688 str = g_key_file_get_string(keyfile,
1689 services[i], "AutoConnect", NULL);
1690 if (!str || g_strcmp0(str, "true")) {
1692 g_key_file_free(keyfile);
1697 str = g_key_file_get_string(keyfile,
1698 services[i], "Modified", NULL);
1700 g_key_file_free(keyfile);
1703 g_time_val_from_iso8601(str, &modified);
1706 ssid = g_key_file_get_string(keyfile,
1707 services[i], "SSID", NULL);
1709 freq = g_key_file_get_integer(keyfile, services[i],
1712 entry = g_try_new(struct last_connected, 1);
1714 g_sequence_free(latest_list);
1715 g_key_file_free(keyfile);
1721 entry->modified = modified;
1724 g_sequence_insert_sorted(latest_list, entry,
1730 g_key_file_free(keyfile);
1733 g_strfreev(services);
1735 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1737 iter = g_sequence_get_begin_iter(latest_list);
1739 for (i = 0; i < num_ssids; i++) {
1740 entry = g_sequence_get(iter);
1742 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1743 entry->modified.tv_sec);
1745 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1746 max_ssids, entry->ssid);
1748 iter = g_sequence_iter_next(iter);
1751 g_sequence_free(latest_list);
1755 static int wifi_scan_simple(struct connman_device *device)
1757 reset_autoscan(device);
1759 return throw_wifi_scan(device, scan_callback_hidden);
1762 static gboolean p2p_find_stop(gpointer data)
1764 struct connman_device *device = data;
1765 struct wifi_data *wifi = connman_device_get_data(device);
1769 wifi->p2p_find_timeout = 0;
1771 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1773 g_supplicant_interface_p2p_stop_find(wifi->interface);
1775 connman_device_unref(device);
1776 reset_autoscan(device);
1781 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1784 struct connman_device *device = user_data;
1785 struct wifi_data *wifi = connman_device_get_data(device);
1787 DBG("result %d wifi %p", result, wifi);
1789 if (wifi->p2p_find_timeout) {
1790 g_source_remove(wifi->p2p_find_timeout);
1791 wifi->p2p_find_timeout = 0;
1797 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1798 p2p_find_stop, device);
1799 if (!wifi->p2p_find_timeout)
1804 p2p_find_stop(device);
1807 static int p2p_find(struct connman_device *device)
1809 struct wifi_data *wifi;
1814 if (!p2p_technology)
1817 wifi = connman_device_get_data(device);
1819 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1822 reset_autoscan(device);
1823 connman_device_ref(device);
1825 ret = g_supplicant_interface_p2p_find(wifi->interface,
1826 p2p_find_callback, device);
1828 connman_device_unref(device);
1829 start_autoscan(device);
1831 connman_device_set_scanning(device,
1832 CONNMAN_SERVICE_TYPE_P2P, true);
1838 #if defined TIZEN_EXT
1839 static void specific_scan_callback(int result, GSupplicantInterface *interface,
1842 struct connman_device *device = user_data;
1843 struct wifi_data *wifi = connman_device_get_data(device);
1846 DBG("result %d wifi %p", result, wifi);
1848 if (wifi && wifi->scan_params) {
1849 g_supplicant_free_scan_params(wifi->scan_params);
1850 wifi->scan_params = NULL;
1853 scanning = connman_device_get_scanning(device);
1855 connman_device_set_scanning(device,
1856 CONNMAN_SERVICE_TYPE_WIFI, false);
1857 connman_device_unref(device);
1861 static int wifi_specific_scan(enum connman_service_type type,
1862 struct connman_device *device, int scan_type,
1863 GSList *specific_scan_list, void *user_data)
1865 GSList *list = NULL;
1867 struct wifi_data *wifi = connman_device_get_data(device);
1868 GSupplicantScanParams *scan_params = NULL;
1869 struct scan_ssid *scan_ssid = NULL;
1878 if (wifi->p2p_device)
1881 if (type == CONNMAN_SERVICE_TYPE_P2P)
1882 return p2p_find(device);
1884 if (wifi->tethering)
1887 scanning = connman_device_get_scanning(device);
1891 DBG("scan_type: %d", scan_type);
1892 if (scan_type == 1) { /* ssid based scan */
1893 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1895 DBG("Failed to allocate memory.");
1899 for (list = specific_scan_list; list; list = list->next) {
1900 ssid = (char *)list->data;
1901 int ssid_len = strlen(ssid);
1903 scan_ssid = g_try_new0(struct scan_ssid, 1);
1905 DBG("Failed to allocate memory.");
1906 g_supplicant_free_scan_params(scan_params);
1910 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
1911 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
1912 scan_ssid->ssid_len = ssid_len;
1913 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
1916 scan_params->num_ssids = count;
1918 } else if (scan_type == 2) { /* frequency based scan */
1920 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1922 DBG("Failed to allocate memory.");
1926 guint num_freqs = g_slist_length(specific_scan_list);
1927 DBG("num_freqs: %d", num_freqs);
1929 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
1930 if (!scan_params->freqs) {
1931 DBG("Failed to allocate memory.");
1932 g_free(scan_params);
1937 for (list = specific_scan_list; list; list = list->next) {
1938 freq = (int)list->data;
1940 scan_params->freqs[count] = freq;
1941 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
1944 scan_params->num_freqs = count;
1947 DBG("Invalid scan");
1951 reset_autoscan(device);
1952 connman_device_ref(device);
1954 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1955 specific_scan_callback, device);
1958 connman_device_set_scanning(device,
1959 CONNMAN_SERVICE_TYPE_WIFI, true);
1961 g_supplicant_free_scan_params(scan_params);
1962 connman_device_unref(device);
1970 * Note that the hidden scan is only used when connecting to this specific
1971 * hidden AP first time. It is not used when system autoconnects to hidden AP.
1973 static int wifi_scan(enum connman_service_type type,
1974 struct connman_device *device,
1975 const char *ssid, unsigned int ssid_len,
1976 const char *identity, const char* passphrase,
1977 const char *security, void *user_data)
1979 struct wifi_data *wifi = connman_device_get_data(device);
1980 GSupplicantScanParams *scan_params = NULL;
1981 struct scan_ssid *scan_ssid;
1982 struct hidden_params *hidden;
1984 int driver_max_ssids = 0;
1991 if (wifi->p2p_device)
1994 if (type == CONNMAN_SERVICE_TYPE_P2P)
1995 return p2p_find(device);
1997 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
1999 if (wifi->tethering)
2002 scanning = connman_device_get_scanning(device);
2004 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2008 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2010 DBG("max ssids %d", driver_max_ssids);
2011 if (driver_max_ssids == 0)
2012 return wifi_scan_simple(device);
2016 if (scanning && wifi->hidden && wifi->postpone_hidden)
2022 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2027 scan_ssid = g_try_new(struct scan_ssid, 1);
2029 g_free(scan_params);
2033 memcpy(scan_ssid->ssid, ssid, ssid_len);
2034 scan_ssid->ssid_len = ssid_len;
2035 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2037 scan_params->num_ssids = 1;
2039 hidden = g_try_new0(struct hidden_params, 1);
2041 g_supplicant_free_scan_params(scan_params);
2046 hidden_free(wifi->hidden);
2047 wifi->hidden = NULL;
2050 memcpy(hidden->ssid, ssid, ssid_len);
2051 hidden->ssid_len = ssid_len;
2052 hidden->identity = g_strdup(identity);
2053 hidden->passphrase = g_strdup(passphrase);
2054 hidden->security = g_strdup(security);
2055 hidden->user_data = user_data;
2056 wifi->hidden = hidden;
2059 /* Let's keep this active scan for later,
2060 * when current scan will be over. */
2061 wifi->postpone_hidden = TRUE;
2062 hidden->scan_params = scan_params;
2066 } else if (wifi->connected) {
2067 g_supplicant_free_scan_params(scan_params);
2068 return wifi_scan_simple(device);
2070 ret = get_latest_connections(driver_max_ssids, scan_params);
2072 g_supplicant_free_scan_params(scan_params);
2073 return wifi_scan_simple(device);
2077 connman_device_ref(device);
2079 #if defined TIZEN_EXT
2080 /*To allow the Full Scan after ssid based scan, set the flag here
2081 It is required because Tizen does not use the ConnMan specific
2082 backgroung Scan feature.Tizen has added the BG Scan feature in net-config
2083 To sync with up ConnMan, we need to issue the Full Scan after SSID specific scan.*/
2084 wifi->allow_full_scan = TRUE;
2086 reset_autoscan(device);
2088 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2089 scan_callback, device);
2092 connman_device_set_scanning(device,
2093 CONNMAN_SERVICE_TYPE_WIFI, true);
2095 g_supplicant_free_scan_params(scan_params);
2096 connman_device_unref(device);
2099 hidden_free(wifi->hidden);
2100 wifi->hidden = NULL;
2107 static void wifi_regdom_callback(int result,
2111 struct connman_device *device = user_data;
2113 connman_device_regdom_notify(device, result, alpha2);
2115 connman_device_unref(device);
2118 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2120 struct wifi_data *wifi = connman_device_get_data(device);
2126 connman_device_ref(device);
2128 ret = g_supplicant_interface_set_country(wifi->interface,
2129 wifi_regdom_callback,
2132 connman_device_unref(device);
2137 static struct connman_device_driver wifi_ng_driver = {
2139 .type = CONNMAN_DEVICE_TYPE_WIFI,
2140 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2141 .probe = wifi_probe,
2142 .remove = wifi_remove,
2143 .enable = wifi_enable,
2144 .disable = wifi_disable,
2146 .set_regdom = wifi_set_regdom,
2147 #if defined TIZEN_EXT
2148 .specific_scan = wifi_specific_scan,
2152 static void system_ready(void)
2156 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2157 connman_error("Failed to register WiFi driver");
2160 static void system_killed(void)
2164 connman_device_driver_unregister(&wifi_ng_driver);
2167 static int network_probe(struct connman_network *network)
2169 DBG("network %p", network);
2174 static void network_remove(struct connman_network *network)
2176 struct connman_device *device = connman_network_get_device(network);
2177 struct wifi_data *wifi;
2179 DBG("network %p", network);
2181 wifi = connman_device_get_data(device);
2185 if (wifi->network != network)
2188 wifi->network = NULL;
2190 #if defined TIZEN_EXT
2191 wifi->disconnecting = false;
2193 if (wifi->pending_network == network)
2194 wifi->pending_network = NULL;
2196 if (wifi->scan_pending_network == network)
2197 wifi->scan_pending_network = NULL;
2201 static void connect_callback(int result, GSupplicantInterface *interface,
2204 #if defined TIZEN_EXT
2206 struct wifi_data *wifi;
2208 struct connman_network *network = user_data;
2210 DBG("network %p result %d", network, result);
2212 #if defined TIZEN_EXT
2213 for (list = iface_list; list; list = list->next) {
2216 if (wifi && wifi->network == network)
2220 /* wifi_data may be invalid because wifi is already disabled */
2225 if (result == -ENOKEY) {
2226 connman_network_set_error(network,
2227 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2228 } else if (result < 0) {
2229 connman_network_set_error(network,
2230 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2233 connman_network_unref(network);
2236 static GSupplicantSecurity network_security(const char *security)
2238 if (g_str_equal(security, "none"))
2239 return G_SUPPLICANT_SECURITY_NONE;
2240 else if (g_str_equal(security, "wep"))
2241 return G_SUPPLICANT_SECURITY_WEP;
2242 else if (g_str_equal(security, "psk"))
2243 return G_SUPPLICANT_SECURITY_PSK;
2244 else if (g_str_equal(security, "wpa"))
2245 return G_SUPPLICANT_SECURITY_PSK;
2246 else if (g_str_equal(security, "rsn"))
2247 return G_SUPPLICANT_SECURITY_PSK;
2248 else if (g_str_equal(security, "ieee8021x"))
2249 return G_SUPPLICANT_SECURITY_IEEE8021X;
2250 #if defined TIZEN_EXT
2251 else if (g_str_equal(security, "ft_psk") == TRUE)
2252 return G_SUPPLICANT_SECURITY_FT_PSK;
2253 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2254 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2257 return G_SUPPLICANT_SECURITY_UNKNOWN;
2260 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2262 const char *security;
2264 memset(ssid, 0, sizeof(*ssid));
2265 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2266 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2268 ssid->scan_ssid = 1;
2269 security = connman_network_get_string(network, "WiFi.Security");
2270 ssid->security = network_security(security);
2271 ssid->passphrase = connman_network_get_string(network,
2274 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2277 * If our private key password is unset,
2278 * we use the supplied passphrase. That is needed
2279 * for PEAP where 2 passphrases (identity and client
2280 * cert may have to be provided.
2282 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2283 connman_network_set_string(network,
2284 "WiFi.PrivateKeyPassphrase",
2286 /* We must have an identity for both PEAP and TLS */
2287 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2289 /* Use agent provided identity as a fallback */
2290 if (!ssid->identity || strlen(ssid->identity) == 0)
2291 ssid->identity = connman_network_get_string(network,
2292 "WiFi.AgentIdentity");
2294 ssid->ca_cert_path = connman_network_get_string(network,
2296 ssid->client_cert_path = connman_network_get_string(network,
2297 "WiFi.ClientCertFile");
2298 ssid->private_key_path = connman_network_get_string(network,
2299 "WiFi.PrivateKeyFile");
2300 ssid->private_key_passphrase = connman_network_get_string(network,
2301 "WiFi.PrivateKeyPassphrase");
2302 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2304 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2305 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2307 #if defined TIZEN_EXT
2308 ssid->bssid = connman_network_get_bssid(network);
2310 #if defined TIZEN_EXT
2311 ssid->freq = connman_network_get_frequency(network);
2314 if (connman_setting_get_bool("BackgroundScanning"))
2315 ssid->bgscan = BGSCAN_DEFAULT;
2318 static int network_connect(struct connman_network *network)
2320 struct connman_device *device = connman_network_get_device(network);
2321 struct wifi_data *wifi;
2322 GSupplicantInterface *interface;
2323 GSupplicantSSID *ssid;
2325 DBG("network %p", network);
2330 wifi = connman_device_get_data(device);
2334 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2338 interface = wifi->interface;
2340 ssid_init(ssid, network);
2342 if (wifi->disconnecting) {
2343 wifi->pending_network = network;
2346 wifi->network = connman_network_ref(network);
2348 #if defined TIZEN_EXT
2349 wifi->scan_pending_network = NULL;
2352 return g_supplicant_interface_connect(interface, ssid,
2353 connect_callback, network);
2356 return -EINPROGRESS;
2359 static void disconnect_callback(int result, GSupplicantInterface *interface,
2362 #if defined TIZEN_EXT
2364 struct wifi_data *wifi;
2365 struct connman_network *network = user_data;
2367 DBG("network %p result %d", network, result);
2369 for (list = iface_list; list; list = list->next) {
2372 if (wifi->network == NULL && wifi->disconnecting == true)
2373 wifi->disconnecting = false;
2375 if (wifi->network == network)
2379 /* wifi_data may be invalid because wifi is already disabled */
2384 struct wifi_data *wifi = user_data;
2387 DBG("result %d supplicant interface %p wifi %p",
2388 result, interface, wifi);
2390 if (result == -ECONNABORTED) {
2391 DBG("wifi interface no longer available");
2395 if (wifi->network) {
2397 * if result < 0 supplican return an error because
2398 * the network is not current.
2399 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2400 * failed, call connman_network_set_connected to report
2401 * disconnect is completed.
2404 connman_network_set_connected(wifi->network, false);
2407 wifi->network = NULL;
2409 wifi->disconnecting = false;
2411 if (wifi->pending_network) {
2412 network_connect(wifi->pending_network);
2413 wifi->pending_network = NULL;
2416 start_autoscan(wifi->device);
2419 static int network_disconnect(struct connman_network *network)
2421 struct connman_device *device = connman_network_get_device(network);
2422 struct wifi_data *wifi;
2424 #if defined TIZEN_EXT
2425 struct connman_service *service;
2428 DBG("network %p", network);
2430 wifi = connman_device_get_data(device);
2431 if (!wifi || !wifi->interface)
2434 #if defined TIZEN_EXT
2435 if (connman_network_get_associating(network) == true) {
2436 connman_network_clear_associating(network);
2437 connman_network_set_bool(network, "WiFi.UseWPS", false);
2439 service = connman_service_lookup_from_network(network);
2441 if (service != NULL &&
2442 (__connman_service_is_connected_state(service,
2443 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2444 __connman_service_is_connected_state(service,
2445 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2446 (connman_service_get_favorite(service) == false))
2447 __connman_service_set_passphrase(service, NULL);
2450 if (wifi->pending_network == network)
2451 wifi->pending_network = NULL;
2453 if (wifi->scan_pending_network == network)
2454 wifi->scan_pending_network = NULL;
2457 connman_network_set_associating(network, false);
2459 if (wifi->disconnecting)
2462 wifi->disconnecting = true;
2464 #if defined TIZEN_EXT
2465 err = g_supplicant_interface_disconnect(wifi->interface,
2466 disconnect_callback, network);
2468 err = g_supplicant_interface_disconnect(wifi->interface,
2469 disconnect_callback, wifi);
2473 wifi->disconnecting = false;
2478 static struct connman_network_driver network_driver = {
2480 .type = CONNMAN_NETWORK_TYPE_WIFI,
2481 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2482 .probe = network_probe,
2483 .remove = network_remove,
2484 .connect = network_connect,
2485 .disconnect = network_disconnect,
2488 static void interface_added(GSupplicantInterface *interface)
2490 const char *ifname = g_supplicant_interface_get_ifname(interface);
2491 const char *driver = g_supplicant_interface_get_driver(interface);
2492 struct wifi_data *wifi;
2494 wifi = g_supplicant_interface_get_data(interface);
2496 wifi = get_pending_wifi_data(ifname);
2500 g_supplicant_interface_set_data(interface, wifi);
2501 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2502 wifi->p2p_device = true;
2505 DBG("ifname %s driver %s wifi %p tethering %d",
2506 ifname, driver, wifi, wifi->tethering);
2508 if (!wifi->device) {
2509 connman_error("WiFi device not set");
2513 connman_device_set_powered(wifi->device, true);
2516 static bool is_idle(struct wifi_data *wifi)
2518 DBG("state %d", wifi->state);
2520 switch (wifi->state) {
2521 case G_SUPPLICANT_STATE_UNKNOWN:
2522 case G_SUPPLICANT_STATE_DISABLED:
2523 case G_SUPPLICANT_STATE_DISCONNECTED:
2524 case G_SUPPLICANT_STATE_INACTIVE:
2525 case G_SUPPLICANT_STATE_SCANNING:
2528 case G_SUPPLICANT_STATE_AUTHENTICATING:
2529 case G_SUPPLICANT_STATE_ASSOCIATING:
2530 case G_SUPPLICANT_STATE_ASSOCIATED:
2531 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2532 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2533 case G_SUPPLICANT_STATE_COMPLETED:
2540 static bool is_idle_wps(GSupplicantInterface *interface,
2541 struct wifi_data *wifi)
2543 /* First, let's check if WPS processing did not went wrong */
2544 if (g_supplicant_interface_get_wps_state(interface) ==
2545 G_SUPPLICANT_WPS_STATE_FAIL)
2548 /* Unlike normal connection, being associated while processing wps
2549 * actually means that we are idling. */
2550 switch (wifi->state) {
2551 case G_SUPPLICANT_STATE_UNKNOWN:
2552 case G_SUPPLICANT_STATE_DISABLED:
2553 case G_SUPPLICANT_STATE_DISCONNECTED:
2554 case G_SUPPLICANT_STATE_INACTIVE:
2555 case G_SUPPLICANT_STATE_SCANNING:
2556 case G_SUPPLICANT_STATE_ASSOCIATED:
2558 case G_SUPPLICANT_STATE_AUTHENTICATING:
2559 case G_SUPPLICANT_STATE_ASSOCIATING:
2560 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2561 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2562 case G_SUPPLICANT_STATE_COMPLETED:
2569 static bool handle_wps_completion(GSupplicantInterface *interface,
2570 struct connman_network *network,
2571 struct connman_device *device,
2572 struct wifi_data *wifi)
2576 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2578 const unsigned char *ssid, *wps_ssid;
2579 unsigned int ssid_len, wps_ssid_len;
2580 const char *wps_key;
2582 /* Checking if we got associated with requested
2584 ssid = connman_network_get_blob(network, "WiFi.SSID",
2587 wps_ssid = g_supplicant_interface_get_wps_ssid(
2588 interface, &wps_ssid_len);
2590 if (!wps_ssid || wps_ssid_len != ssid_len ||
2591 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2592 connman_network_set_associating(network, false);
2593 #if defined TIZEN_EXT
2594 g_supplicant_interface_disconnect(wifi->interface,
2595 disconnect_callback, wifi->network);
2597 connman_network_set_bool(network, "WiFi.UseWPS", false);
2598 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2600 g_supplicant_interface_disconnect(wifi->interface,
2601 disconnect_callback, wifi);
2606 wps_key = g_supplicant_interface_get_wps_key(interface);
2607 connman_network_set_string(network, "WiFi.Passphrase",
2610 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2616 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2617 struct connman_network *network,
2618 struct wifi_data *wifi)
2620 #if defined TIZEN_EXT
2621 const char *security;
2622 struct connman_service *service;
2624 if (wifi->connected)
2627 security = connman_network_get_string(network, "WiFi.Security");
2629 if (g_str_equal(security, "ieee8021x") == true &&
2630 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2632 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2637 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2640 struct connman_service *service;
2642 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2645 if (wifi->connected)
2649 service = connman_service_lookup_from_network(network);
2655 if (connman_service_get_favorite(service)) {
2656 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2661 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2666 #if defined TIZEN_EXT
2667 static bool handle_wifi_assoc_retry(struct connman_network *network,
2668 struct wifi_data *wifi)
2670 const char *security;
2672 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2673 connman_network_get_connecting(network) != true) {
2674 wifi->assoc_retry_count = 0;
2678 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2679 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2680 wifi->assoc_retry_count = 0;
2684 security = connman_network_get_string(network, "WiFi.Security");
2685 if (g_str_equal(security, "ieee8021x") == true &&
2686 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2687 wifi->assoc_retry_count = 0;
2691 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2692 wifi->assoc_retry_count = 0;
2694 /* Honestly it's not an invalid-key error,
2695 * however QA team recommends that the invalid-key error
2696 * might be better to display for user experience.
2698 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2707 static void interface_state(GSupplicantInterface *interface)
2709 struct connman_network *network;
2710 struct connman_device *device;
2711 struct wifi_data *wifi;
2712 GSupplicantState state = g_supplicant_interface_get_state(interface);
2715 wifi = g_supplicant_interface_get_data(interface);
2717 DBG("wifi %p interface state %d", wifi, state);
2722 device = wifi->device;
2726 if (g_supplicant_interface_get_ready(interface) &&
2727 !wifi->interface_ready) {
2728 wifi->interface_ready = true;
2729 finalize_interface_creation(wifi);
2732 network = wifi->network;
2737 case G_SUPPLICANT_STATE_SCANNING:
2740 case G_SUPPLICANT_STATE_AUTHENTICATING:
2741 case G_SUPPLICANT_STATE_ASSOCIATING:
2742 #if defined TIZEN_EXT
2743 reset_autoscan(device);
2745 stop_autoscan(device);
2748 if (!wifi->connected)
2749 connman_network_set_associating(network, true);
2753 case G_SUPPLICANT_STATE_COMPLETED:
2754 #if defined TIZEN_EXT
2755 /* though it should be already reset: */
2756 reset_autoscan(device);
2758 wifi->assoc_retry_count = 0;
2760 wifi->scan_pending_network = NULL;
2762 /* should be cleared scanning flag */
2763 bool scanning = connman_device_get_scanning(device);
2765 connman_device_set_scanning(device,
2766 CONNMAN_SERVICE_TYPE_WIFI, false);
2767 connman_device_unref(device);
2770 /* though it should be already stopped: */
2771 stop_autoscan(device);
2774 if (!handle_wps_completion(interface, network, device, wifi))
2777 connman_network_set_connected(network, true);
2778 wifi->disconnect_code = 0;
2781 case G_SUPPLICANT_STATE_DISCONNECTED:
2783 * If we're in one of the idle modes, we have
2784 * not started association yet and thus setting
2785 * those ones to FALSE could cancel an association
2788 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2790 if (is_idle_wps(interface, wifi))
2796 /* If previous state was 4way-handshake, then
2797 * it's either: psk was incorrect and thus we retry
2798 * or if we reach the maximum retries we declare the
2800 if (handle_4way_handshake_failure(interface,
2804 /* See table 8-36 Reason codes in IEEE Std 802.11 */
2805 switch (wifi->disconnect_code) {
2806 case 1: /* Unspecified reason */
2807 /* Let's assume it's because we got blocked */
2809 case 6: /* Class 2 frame received from nonauthenticated STA */
2810 connman_network_set_error(network,
2811 CONNMAN_NETWORK_ERROR_BLOCKED);
2819 /* We disable the selected network, if not then
2820 * wpa_supplicant will loop retrying */
2821 if (g_supplicant_interface_enable_selected_network(interface,
2823 DBG("Could not disables selected network");
2825 #if defined TIZEN_EXT
2828 err = g_supplicant_interface_remove_network(wifi->interface);
2830 DBG("Failed to remove network(%d)", err);
2833 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2834 * Retry association until its retry count is expired */
2835 if (handle_wifi_assoc_retry(network, wifi) == true) {
2836 throw_wifi_scan(wifi->device, scan_callback);
2837 wifi->scan_pending_network = wifi->network;
2841 if(wifi->disconnect_code > 0){
2842 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
2843 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
2846 /* To avoid unnecessary repeated association in wpa_supplicant,
2847 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2848 if (wps != true && wifi->network && wifi->disconnecting == false) {
2849 wifi->disconnecting = true;
2850 err = g_supplicant_interface_disconnect(wifi->interface,
2851 disconnect_callback, wifi->network);
2853 wifi->disconnecting = false;
2855 connman_network_set_connected(network, false);
2856 connman_network_set_associating(network, false);
2858 start_autoscan(device);
2864 connman_network_set_connected(network, false);
2865 connman_network_set_associating(network, false);
2866 wifi->disconnecting = false;
2868 start_autoscan(device);
2872 case G_SUPPLICANT_STATE_INACTIVE:
2873 #if defined TIZEN_EXT
2874 if (handle_wps_completion(interface, network, device, wifi) == false)
2877 connman_network_set_associating(network, false);
2878 start_autoscan(device);
2882 case G_SUPPLICANT_STATE_UNKNOWN:
2883 case G_SUPPLICANT_STATE_DISABLED:
2884 case G_SUPPLICANT_STATE_ASSOCIATED:
2885 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2886 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2890 wifi->state = state;
2892 /* Saving wpa_s state policy:
2893 * If connected and if the state changes are roaming related:
2894 * --> We stay connected
2896 * --> We are connected
2898 * --> We are not connected
2901 #if defined TIZEN_EXT
2902 case G_SUPPLICANT_STATE_SCANNING:
2905 case G_SUPPLICANT_STATE_AUTHENTICATING:
2906 case G_SUPPLICANT_STATE_ASSOCIATING:
2907 case G_SUPPLICANT_STATE_ASSOCIATED:
2908 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2909 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2910 if (wifi->connected)
2911 connman_warn("Probably roaming right now!"
2912 " Staying connected...");
2914 wifi->connected = false;
2916 case G_SUPPLICANT_STATE_COMPLETED:
2917 wifi->connected = true;
2920 wifi->connected = false;
2927 static void interface_removed(GSupplicantInterface *interface)
2929 const char *ifname = g_supplicant_interface_get_ifname(interface);
2930 struct wifi_data *wifi;
2932 DBG("ifname %s", ifname);
2934 wifi = g_supplicant_interface_get_data(interface);
2937 wifi->interface = NULL;
2939 if (wifi && wifi->tethering)
2942 if (!wifi || !wifi->device) {
2943 DBG("wifi interface already removed");
2947 connman_device_set_powered(wifi->device, false);
2949 check_p2p_technology();
2952 static void set_device_type(const char *type, char dev_type[17])
2954 const char *oui = "0050F204";
2955 const char *category = "0100";
2956 const char *sub_category = "0000";
2958 if (!g_strcmp0(type, "handset")) {
2960 sub_category = "0500";
2961 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2962 sub_category = "0100";
2963 else if (!g_strcmp0(type, "server"))
2964 sub_category = "0200";
2965 else if (!g_strcmp0(type, "laptop"))
2966 sub_category = "0500";
2967 else if (!g_strcmp0(type, "desktop"))
2968 sub_category = "0600";
2969 else if (!g_strcmp0(type, "tablet"))
2970 sub_category = "0900";
2971 else if (!g_strcmp0(type, "watch"))
2974 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2977 static void p2p_support(GSupplicantInterface *interface)
2979 char dev_type[17] = {};
2980 const char *hostname;
2984 if (!g_supplicant_interface_has_p2p(interface))
2987 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2988 DBG("Could not register P2P technology driver");
2992 hostname = connman_utsname_get_hostname();
2994 hostname = "ConnMan";
2996 set_device_type(connman_machine_get_type(), dev_type);
2997 g_supplicant_interface_set_p2p_device_config(interface,
2998 hostname, dev_type);
2999 connman_peer_driver_register(&peer_driver);
3002 static void scan_started(GSupplicantInterface *interface)
3007 static void scan_finished(GSupplicantInterface *interface)
3009 #if defined TIZEN_EXT
3010 struct wifi_data *wifi;
3011 bool is_associating = false;
3012 static bool is_scanning = true;
3017 #if defined TIZEN_EXT
3018 wifi = g_supplicant_interface_get_data(interface);
3019 if (wifi && wifi->scan_pending_network) {
3020 network_connect(wifi->scan_pending_network);
3021 wifi->scan_pending_network = NULL;
3024 //service state - associating
3025 if(!wifi || !wifi->network)
3028 is_associating = connman_network_get_associating(wifi->network);
3029 if(is_associating && is_scanning){
3030 is_scanning = false;
3031 DBG("send scan for connecting");
3032 throw_wifi_scan(wifi->device, scan_callback);
3043 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3045 unsigned char strength;
3047 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3049 #if !defined TIZEN_EXT
3056 static void network_added(GSupplicantNetwork *supplicant_network)
3058 struct connman_network *network;
3059 GSupplicantInterface *interface;
3060 struct wifi_data *wifi;
3061 const char *name, *identifier, *security, *group, *mode;
3062 const unsigned char *ssid;
3063 unsigned int ssid_len;
3067 bool wps_advertizing;
3069 #if defined TIZEN_EXT
3070 const char *wifi_vsie;
3071 unsigned int wifi_vsie_len;
3074 mode = g_supplicant_network_get_mode(supplicant_network);
3075 identifier = g_supplicant_network_get_identifier(supplicant_network);
3077 DBG("%s", identifier);
3079 if (!g_strcmp0(mode, "adhoc"))
3082 interface = g_supplicant_network_get_interface(supplicant_network);
3083 wifi = g_supplicant_interface_get_data(interface);
3084 name = g_supplicant_network_get_name(supplicant_network);
3085 security = g_supplicant_network_get_security(supplicant_network);
3086 group = g_supplicant_network_get_identifier(supplicant_network);
3087 wps = g_supplicant_network_get_wps(supplicant_network);
3088 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3089 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3090 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3091 supplicant_network);
3096 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3098 #if defined TIZEN_EXT
3099 wifi_vsie = g_supplicant_network_get_wifi_vsie(supplicant_network, &wifi_vsie_len);
3101 network = connman_device_get_network(wifi->device, identifier);
3104 network = connman_network_create(identifier,
3105 CONNMAN_NETWORK_TYPE_WIFI);
3109 connman_network_set_index(network, wifi->index);
3111 if (connman_device_add_network(wifi->device, network) < 0) {
3112 connman_network_unref(network);
3116 wifi->networks = g_slist_prepend(wifi->networks, network);
3119 if (name && name[0] != '\0')
3120 connman_network_set_name(network, name);
3122 connman_network_set_blob(network, "WiFi.SSID",
3124 #if defined TIZEN_EXT
3125 if(wifi_vsie_len > 0 && wifi_vsie)
3126 connman_network_set_blob(network, "WiFi.Vsie",
3127 wifi_vsie, wifi_vsie_len);
3129 connman_network_set_string(network, "WiFi.Security", security);
3130 connman_network_set_strength(network,
3131 calculate_strength(supplicant_network));
3132 connman_network_set_bool(network, "WiFi.WPS", wps);
3135 /* Is AP advertizing for WPS association?
3136 * If so, we decide to use WPS by default */
3137 if (wps_ready && wps_pbc &&
3139 #if !defined TIZEN_EXT
3140 connman_network_set_bool(network, "WiFi.UseWPS", true);
3142 DBG("wps is activating by ap but ignore it.");
3147 connman_network_set_frequency(network,
3148 g_supplicant_network_get_frequency(supplicant_network));
3149 #if defined TIZEN_EXT
3150 connman_network_set_bssid(network,
3151 g_supplicant_network_get_bssid(supplicant_network));
3152 connman_network_set_maxrate(network,
3153 g_supplicant_network_get_maxrate(supplicant_network));
3154 connman_network_set_enc_mode(network,
3155 g_supplicant_network_get_enc_mode(supplicant_network));
3156 connman_network_set_rsn_mode(network,
3157 g_supplicant_network_get_rsn_mode(supplicant_network));
3158 connman_network_set_keymgmt(network,
3159 g_supplicant_network_get_keymgmt(supplicant_network));
3161 connman_network_set_available(network, true);
3162 connman_network_set_string(network, "WiFi.Mode", mode);
3164 #if defined TIZEN_EXT
3169 connman_network_set_group(network, group);
3171 #if defined TIZEN_EXT
3172 if (wifi_first_scan == true)
3173 found_with_first_scan = true;
3176 if (wifi->hidden && ssid) {
3177 #if defined TIZEN_EXT
3178 if (network_security(wifi->hidden->security) ==
3179 network_security(security) &&
3181 if (!g_strcmp0(wifi->hidden->security, security) &&
3183 wifi->hidden->ssid_len == ssid_len &&
3184 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3185 connman_network_connect_hidden(network,
3186 wifi->hidden->identity,
3187 wifi->hidden->passphrase,
3188 wifi->hidden->user_data);
3189 wifi->hidden->user_data = NULL;
3190 hidden_free(wifi->hidden);
3191 wifi->hidden = NULL;
3196 static void network_removed(GSupplicantNetwork *network)
3198 GSupplicantInterface *interface;
3199 struct wifi_data *wifi;
3200 const char *name, *identifier;
3201 struct connman_network *connman_network;
3203 interface = g_supplicant_network_get_interface(network);
3204 wifi = g_supplicant_interface_get_data(interface);
3205 identifier = g_supplicant_network_get_identifier(network);
3206 name = g_supplicant_network_get_name(network);
3208 DBG("name %s", name);
3213 connman_network = connman_device_get_network(wifi->device, identifier);
3214 if (!connman_network)
3217 #if defined TIZEN_EXT
3218 if (connman_network == wifi->scan_pending_network)
3219 wifi->scan_pending_network = NULL;
3221 if (connman_network == wifi->pending_network)
3222 wifi->pending_network = NULL;
3224 if(connman_network_get_connecting(connman_network) == true){
3225 connman_network_set_connected(connman_network, false);
3229 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3231 connman_device_remove_network(wifi->device, connman_network);
3232 connman_network_unref(connman_network);
3235 static void network_changed(GSupplicantNetwork *network, const char *property)
3237 GSupplicantInterface *interface;
3238 struct wifi_data *wifi;
3239 const char *name, *identifier;
3240 struct connman_network *connman_network;
3242 #if defined TIZEN_EXT
3243 const unsigned char *bssid;
3244 unsigned int maxrate;
3249 interface = g_supplicant_network_get_interface(network);
3250 wifi = g_supplicant_interface_get_data(interface);
3251 identifier = g_supplicant_network_get_identifier(network);
3252 name = g_supplicant_network_get_name(network);
3254 DBG("name %s", name);
3259 connman_network = connman_device_get_network(wifi->device, identifier);
3260 if (!connman_network)
3263 if (g_str_equal(property, "Signal")) {
3264 connman_network_set_strength(connman_network,
3265 calculate_strength(network));
3266 connman_network_update(connman_network);
3269 #if defined TIZEN_EXT
3270 bssid = g_supplicant_network_get_bssid(network);
3271 maxrate = g_supplicant_network_get_maxrate(network);
3272 frequency = g_supplicant_network_get_frequency(network);
3273 wps = g_supplicant_network_get_wps(network);
3275 connman_network_set_bssid(connman_network, bssid);
3276 connman_network_set_maxrate(connman_network, maxrate);
3277 connman_network_set_frequency(connman_network, frequency);
3278 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3282 static void apply_peer_services(GSupplicantPeer *peer,
3283 struct connman_peer *connman_peer)
3285 const unsigned char *data;
3290 connman_peer_reset_services(connman_peer);
3292 data = g_supplicant_peer_get_widi_ies(peer, &length);
3294 connman_peer_add_service(connman_peer,
3295 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3299 static void add_station(const char *mac)
3301 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3305 static void remove_station(const char *mac)
3307 connman_technology_tethering_remove_station(mac);
3310 static void peer_found(GSupplicantPeer *peer)
3312 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3313 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3314 struct connman_peer *connman_peer;
3315 const char *identifier, *name;
3318 identifier = g_supplicant_peer_get_identifier(peer);
3319 name = g_supplicant_peer_get_name(peer);
3321 DBG("ident: %s", identifier);
3323 connman_peer = connman_peer_get(wifi->device, identifier);
3327 connman_peer = connman_peer_create(identifier);
3328 connman_peer_set_name(connman_peer, name);
3329 connman_peer_set_device(connman_peer, wifi->device);
3330 apply_peer_services(peer, connman_peer);
3332 ret = connman_peer_register(connman_peer);
3333 if (ret < 0 && ret != -EALREADY)
3334 connman_peer_unref(connman_peer);
3337 static void peer_lost(GSupplicantPeer *peer)
3339 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3340 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3341 struct connman_peer *connman_peer;
3342 const char *identifier;
3347 identifier = g_supplicant_peer_get_identifier(peer);
3349 DBG("ident: %s", identifier);
3351 connman_peer = connman_peer_get(wifi->device, identifier);
3353 if (wifi->p2p_connecting &&
3354 wifi->pending_peer == connman_peer) {
3355 peer_connect_timeout(wifi);
3357 connman_peer_unregister(connman_peer);
3358 connman_peer_unref(connman_peer);
3362 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3364 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3365 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3366 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3367 struct connman_peer *connman_peer;
3368 const char *identifier;
3370 identifier = g_supplicant_peer_get_identifier(peer);
3372 DBG("ident: %s", identifier);
3374 connman_peer = connman_peer_get(wifi->device, identifier);
3379 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3380 apply_peer_services(peer, connman_peer);
3381 connman_peer_services_changed(connman_peer);
3383 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3384 if (!g_supplicant_peer_is_in_a_group(peer))
3385 p_state = CONNMAN_PEER_STATE_IDLE;
3387 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3389 case G_SUPPLICANT_PEER_GROUP_STARTED:
3391 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3392 p_state = CONNMAN_PEER_STATE_IDLE;
3394 case G_SUPPLICANT_PEER_GROUP_JOINED:
3395 connman_peer_set_iface_address(connman_peer,
3396 g_supplicant_peer_get_iface_address(peer));
3398 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3399 p_state = CONNMAN_PEER_STATE_IDLE;
3401 case G_SUPPLICANT_PEER_GROUP_FAILED:
3402 if (g_supplicant_peer_has_requested_connection(peer))
3403 p_state = CONNMAN_PEER_STATE_IDLE;
3405 p_state = CONNMAN_PEER_STATE_FAILURE;
3409 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3410 p_state == CONNMAN_PEER_STATE_FAILURE) {
3411 if (wifi->p2p_connecting
3412 && connman_peer == wifi->pending_peer)
3413 peer_cancel_timeout(wifi);
3415 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3418 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3421 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3422 GSupplicantInterface *g_iface;
3423 struct wifi_data *g_wifi;
3425 g_iface = g_supplicant_peer_get_group_interface(peer);
3429 g_wifi = g_supplicant_interface_get_data(g_iface);
3433 connman_peer_set_as_master(connman_peer,
3434 !g_supplicant_peer_is_client(peer));
3435 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3438 connman_peer_set_state(connman_peer, p_state);
3441 static void peer_request(GSupplicantPeer *peer)
3443 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3444 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3445 struct connman_peer *connman_peer;
3446 const char *identifier;
3448 identifier = g_supplicant_peer_get_identifier(peer);
3450 DBG("ident: %s", identifier);
3452 connman_peer = connman_peer_get(wifi->device, identifier);
3456 connman_peer_request_connection(connman_peer);
3459 #if defined TIZEN_EXT
3460 static void system_power_off(void)
3463 struct wifi_data *wifi;
3464 struct connman_service *service;
3465 struct connman_ipconfig *ipconfig_ipv4;
3467 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3468 for (list = iface_list; list; list = list->next) {
3471 if (wifi->network != NULL) {
3472 service = connman_service_lookup_from_network(wifi->network);
3473 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3474 __connman_dhcp_stop(ipconfig_ipv4);
3480 static void network_merged(GSupplicantNetwork *network)
3482 GSupplicantInterface *interface;
3483 GSupplicantState state;
3484 struct wifi_data *wifi;
3485 const char *identifier;
3486 struct connman_network *connman_network;
3487 unsigned int ishs20AP = 0;
3490 interface = g_supplicant_network_get_interface(network);
3494 state = g_supplicant_interface_get_state(interface);
3495 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3498 wifi = g_supplicant_interface_get_data(interface);
3502 identifier = g_supplicant_network_get_identifier(network);
3504 connman_network = connman_device_get_network(wifi->device, identifier);
3505 if (!connman_network)
3508 DBG("merged identifier %s", identifier);
3510 if (wifi->connected == FALSE) {
3512 case G_SUPPLICANT_STATE_AUTHENTICATING:
3513 case G_SUPPLICANT_STATE_ASSOCIATING:
3514 case G_SUPPLICANT_STATE_ASSOCIATED:
3515 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3516 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3517 connman_network_set_associating(connman_network, TRUE);
3519 case G_SUPPLICANT_STATE_COMPLETED:
3520 connman_network_set_connected(connman_network, TRUE);
3523 DBG("Not handled the state : %d", state);
3528 ishs20AP = g_supplicant_network_is_hs20AP(network);
3529 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3532 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3533 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3534 connman_network_set_string(connman_network, "WiFi.EAP",
3536 connman_network_set_string(connman_network, "WiFi.Identity",
3537 g_supplicant_network_get_identity(network));
3538 connman_network_set_string(connman_network, "WiFi.Phase2",
3539 g_supplicant_network_get_phase2(network));
3544 wifi->network = connman_network;
3548 static void debug(const char *str)
3550 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3551 connman_debug("%s", str);
3554 static void disconnect_reasoncode(GSupplicantInterface *interface,
3557 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3560 wifi->disconnect_code = reasoncode;
3565 static const GSupplicantCallbacks callbacks = {
3566 .system_ready = system_ready,
3567 .system_killed = system_killed,
3568 .interface_added = interface_added,
3569 .interface_state = interface_state,
3570 .interface_removed = interface_removed,
3571 .p2p_support = p2p_support,
3572 .scan_started = scan_started,
3573 .scan_finished = scan_finished,
3574 .network_added = network_added,
3575 .network_removed = network_removed,
3576 .network_changed = network_changed,
3577 .add_station = add_station,
3578 .remove_station = remove_station,
3579 .peer_found = peer_found,
3580 .peer_lost = peer_lost,
3581 .peer_changed = peer_changed,
3582 .peer_request = peer_request,
3583 #if defined TIZEN_EXT
3584 .system_power_off = system_power_off,
3585 .network_merged = network_merged,
3587 .disconnect_reasoncode = disconnect_reasoncode,
3592 static int tech_probe(struct connman_technology *technology)
3594 wifi_technology = technology;
3599 static void tech_remove(struct connman_technology *technology)
3601 wifi_technology = NULL;
3604 struct wifi_tethering_info {
3605 struct wifi_data *wifi;
3606 struct connman_technology *technology;
3608 GSupplicantSSID *ssid;
3611 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3612 const char *passphrase, bool hidden)
3614 GSupplicantSSID *ap;
3616 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3620 ap->mode = G_SUPPLICANT_MODE_MASTER;
3622 ap->ssid_len = strlen(ssid);
3626 if (!passphrase || strlen(passphrase) == 0) {
3627 ap->security = G_SUPPLICANT_SECURITY_NONE;
3628 ap->passphrase = NULL;
3630 ap->security = G_SUPPLICANT_SECURITY_PSK;
3631 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3632 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3633 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3634 ap->passphrase = passphrase;
3638 ap->ignore_broadcast_ssid =
3639 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3641 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3646 static void ap_start_callback(int result, GSupplicantInterface *interface,
3649 struct wifi_tethering_info *info = user_data;
3651 DBG("result %d index %d bridge %s",
3652 result, info->wifi->index, info->wifi->bridge);
3655 connman_inet_remove_from_bridge(info->wifi->index,
3656 info->wifi->bridge);
3657 connman_technology_tethering_notify(info->technology, false);
3660 g_free(info->ifname);
3664 static void ap_create_callback(int result,
3665 GSupplicantInterface *interface,
3668 struct wifi_tethering_info *info = user_data;
3670 DBG("result %d ifname %s", result,
3671 g_supplicant_interface_get_ifname(interface));
3674 connman_inet_remove_from_bridge(info->wifi->index,
3675 info->wifi->bridge);
3676 connman_technology_tethering_notify(info->technology, false);
3678 g_free(info->ifname);
3684 info->wifi->interface = interface;
3685 g_supplicant_interface_set_data(interface, info->wifi);
3687 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3688 connman_error("Failed to set interface ap_scan property");
3690 g_supplicant_interface_connect(interface, info->ssid,
3691 ap_start_callback, info);
3694 static void sta_remove_callback(int result,
3695 GSupplicantInterface *interface,
3698 struct wifi_tethering_info *info = user_data;
3699 const char *driver = connman_option_get_string("wifi");
3701 DBG("ifname %s result %d ", info->ifname, result);
3704 info->wifi->tethering = true;
3706 g_free(info->ifname);
3712 info->wifi->interface = NULL;
3714 connman_technology_tethering_notify(info->technology, true);
3716 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3721 static int tech_set_tethering(struct connman_technology *technology,
3722 const char *identifier, const char *passphrase,
3723 const char *bridge, bool enabled, bool hidden)
3726 GSupplicantInterface *interface;
3727 struct wifi_data *wifi;
3728 struct wifi_tethering_info *info;
3736 for (list = iface_list; list; list = list->next) {
3739 if (wifi->tethering) {
3740 wifi->tethering = false;
3742 connman_inet_remove_from_bridge(wifi->index,
3744 wifi->bridged = false;
3748 connman_technology_tethering_notify(technology, false);
3753 for (list = iface_list; list; list = list->next) {
3756 interface = wifi->interface;
3761 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3763 mode = g_supplicant_interface_get_mode(interface);
3764 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3765 DBG("%s does not support AP mode", ifname);
3769 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3774 info->technology = technology;
3775 info->wifi->bridge = bridge;
3776 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3781 info->ifname = g_strdup(ifname);
3782 if (!info->ifname) {
3788 info->wifi->tethering = true;
3790 err = g_supplicant_interface_remove(interface,
3791 sta_remove_callback,
3800 static void regdom_callback(int result, const char *alpha2, void *user_data)
3804 if (!wifi_technology)
3810 connman_technology_regdom_notify(wifi_technology, alpha2);
3813 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3815 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3818 static struct connman_technology_driver tech_driver = {
3820 .type = CONNMAN_SERVICE_TYPE_WIFI,
3821 .probe = tech_probe,
3822 .remove = tech_remove,
3823 .set_tethering = tech_set_tethering,
3824 .set_regdom = tech_set_regdom,
3827 static int wifi_init(void)
3831 err = connman_network_driver_register(&network_driver);
3835 err = g_supplicant_register(&callbacks);
3837 connman_network_driver_unregister(&network_driver);
3841 err = connman_technology_driver_register(&tech_driver);
3843 g_supplicant_unregister(&callbacks);
3844 connman_network_driver_unregister(&network_driver);
3851 static void wifi_exit(void)
3855 connman_technology_driver_unregister(&tech_driver);
3857 g_supplicant_unregister(&callbacks);
3859 connman_network_driver_unregister(&network_driver);
3862 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3863 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)